Skip to main content

A comprehensive static analysis linter for ANTLR v4 grammar files

Project description

ANTLR v4 Grammar Linter

PyPI version Python versions License: MIT

A comprehensive static analysis linter for ANTLR v4 grammar files (.g4) that identifies common issues, enforces best practices, and improves grammar quality and maintainability.

✨ Features

  • 24 Built-in Rules across 8 categories for comprehensive grammar analysis
  • Configurable Rule Severity - Set rules as error, warning, or info
  • Multiple Output Formats - Text (with colors), JSON, XML, SARIF
  • Smart Detection - Identifies naming issues, complexity problems, performance bottlenecks
  • Flexible Configuration - JSON-based configuration with rule-specific thresholds
  • CLI and Programmatic APIs - Use as command-line tool or Python library

📦 Installation

# Using pip
pip install antlr-v4-linter

# Using uv (faster)
uv pip install antlr-v4-linter

# Using pipx (isolated environment)
pipx install antlr-v4-linter

🚀 Quick Start

# Lint a single grammar file
antlr-lint lint MyGrammar.g4

# Lint multiple files or directories
antlr-lint lint src/
antlr-lint lint "*.g4"

# Use custom configuration
antlr-lint lint --config antlr-lint.json MyGrammar.g4

# Output in different formats
antlr-lint lint --format json MyGrammar.g4
antlr-lint lint --format xml MyGrammar.g4

# List all available rules
antlr-lint rules

# Create a configuration file
antlr-lint init

📋 Available Rules

The linter includes 24 rules organized into 8 categories:

Syntax and Structure (S001-S003)

  • S001: Missing EOF token - Main parser rule should end with EOF
  • S002: Incomplete input parsing - Lexer should have catch-all rule
  • S003: Ambiguous string literals - Same literal in multiple lexer rules

Naming and Convention (N001-N003)

  • N001: Parser rule naming - Must start with lowercase letter
  • N002: Lexer rule naming - Must start with uppercase letter
  • N003: Inconsistent naming convention - Mixed camelCase/snake_case

Labeling and Organization (L001-L003)

  • L001: Missing alternative labels - Multi-alternative rules need labels
  • L002: Inconsistent label naming - Labels should follow consistent style
  • L003: Duplicate labels - Labels must be unique within rule

Complexity and Maintainability (C001-C003)

  • C001: Excessive complexity - Rules exceed configurable thresholds
  • C002: Deeply nested rule - Too many nesting levels
  • C003: Very long rule - Rule definition spans too many lines

Token and Lexer (T001-T003)

  • T001: Overlapping tokens - Token definitions may conflict
  • T002: Unreachable token - Token shadowed by earlier rules
  • T003: Unused token - Token defined but never used

Error Handling (E001-E002)

  • E001: Missing error recovery - No error handling strategies
  • E002: Potential ambiguity - Grammar may have ambiguous paths

Performance (P001-P002)

  • P001: Excessive backtracking - Patterns causing performance issues
  • P002: Inefficient lexer pattern - Suboptimal regular expressions

Documentation (D001-D002)

  • D001: Missing rule documentation - Complex rules lack comments
  • D002: Missing grammar header - No file-level documentation

⚙️ Configuration

Create an antlr-lint.json file in your project root:

{
  "rules": {
    "S001": { "enabled": true, "severity": "error" },
    "N001": { "enabled": true, "severity": "error" },
    "C001": { 
      "enabled": true, 
      "severity": "warning",
      "thresholds": {
        "maxAlternatives": 10,
        "maxNestingDepth": 5,
        "maxTokens": 50
      }
    }
  },
  "excludePatterns": ["*.generated.g4", "build/**/*.g4"],
  "outputFormat": "text"
}

Configuration Options

  • rules: Configure individual rules with enabled, severity, and rule-specific thresholds
  • excludePatterns: Glob patterns for files to skip
  • outputFormat: Choose between text, json, xml, or sarif

Generate a default configuration:

antlr-lint init

🐍 Programmatic API

Use the linter in your Python code:

from antlr_v4_linter import ANTLRLinter, LinterConfig

# Create linter with default config
linter = ANTLRLinter()

# Or with custom config
config = LinterConfig.from_file("antlr-lint.json")
linter = ANTLRLinter(config)

# Lint a single file
result = linter.lint_file("MyGrammar.g4")
print(f"Found {result.total_issues} issues")

# Lint multiple files
results = linter.lint_files(["Grammar1.g4", "Grammar2.g4"])
for result in results:
    print(f"{result.file_path}: {result.error_count} errors, {result.warning_count} warnings")

🔧 Development

# Clone the repository
git clone https://github.com/bytebase/antlr-v4-linter.git
cd antlr-v4-linter

# Install in development mode
pip install -e ".[dev]"

# Run tests
pytest

# Format code
black src/ tests/
isort src/ tests/

# Type checking
mypy src/

# Build package
python -m build

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'Add some AmazingFeature')
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

📝 License

This project is licensed under the MIT License - see the LICENSE file for details.

🙏 Acknowledgments

  • The ANTLR project and community for the excellent parser generator
  • All contributors who help improve this linter

🔗 Links

📊 Project Status

  • ✅ All 24 rules implemented
  • ✅ Published to PyPI
  • ✅ Comprehensive test coverage
  • ✅ GitHub Actions CI/CD
  • 🚧 IDE extensions (coming soon)
  • 🚧 Auto-fix capabilities (coming soon)

🚀 GitHub Actions Integration

The project includes automated CI/CD workflows:

Automatic Release on Tag

When you push a version tag (e.g., 0.1.3), the package is automatically:

  1. Built and tested
  2. Published to Test PyPI
  3. Published to Production PyPI
  4. GitHub Release created
# Create and push a version tag
git tag 0.1.3
git push origin 0.1.3

Manual Release

Use the "Manual Release" workflow in GitHub Actions:

  1. Go to Actions → Manual Release
  2. Click "Run workflow"
  3. Enter version number
  4. Choose whether to test on Test PyPI first

Continuous Integration

All pushes and pull requests run:

  • Multi-platform tests (Linux, macOS)
  • Python 3.8-3.12 compatibility tests
  • Code quality checks (black, isort, flake8, mypy)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

antlr_v4_linter-0.1.4.tar.gz (59.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

antlr_v4_linter-0.1.4-py3-none-any.whl (67.7 kB view details)

Uploaded Python 3

File details

Details for the file antlr_v4_linter-0.1.4.tar.gz.

File metadata

  • Download URL: antlr_v4_linter-0.1.4.tar.gz
  • Upload date:
  • Size: 59.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for antlr_v4_linter-0.1.4.tar.gz
Algorithm Hash digest
SHA256 e45d7b2f6409b53d32091877991fe44cbc9d759562f5f8bbc07c1cc4c1510d3c
MD5 d54362f9337ff16068150d7fba704c13
BLAKE2b-256 2889b6a787e59bf7084f499f73ec2714cbf5f58965cc71bb8a70dfa1b9ceae60

See more details on using hashes here.

File details

Details for the file antlr_v4_linter-0.1.4-py3-none-any.whl.

File metadata

File hashes

Hashes for antlr_v4_linter-0.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 67ade8b8f77e30d0d78d177f900f5a262df73fe85cb614954b196ae34ebbd908
MD5 94db5e1d785a96bcda599bd7c722eee8
BLAKE2b-256 4494e45812dbaa85d636a36bb969a3a76ba8c05aba1e783df35cef8260598265

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page