A comprehensive static analysis linter for ANTLR v4 grammar files
Project description
ANTLR v4 Grammar Linter
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-specificthresholds - excludePatterns: Glob patterns for files to skip
- outputFormat: Choose between
text,json,xml, orsarif
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.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - 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
- PyPI Package: https://pypi.org/project/antlr-v4-linter/
- GitHub Repository: https://github.com/bytebase/antlr-v4-linter
- Issue Tracker: https://github.com/bytebase/antlr-v4-linter/issues
- ANTLR Documentation: https://www.antlr.org/
📊 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:
- Built and tested
- Published to Test PyPI
- Published to Production PyPI
- 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:
- Go to Actions → Manual Release
- Click "Run workflow"
- Enter version number
- 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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e45d7b2f6409b53d32091877991fe44cbc9d759562f5f8bbc07c1cc4c1510d3c
|
|
| MD5 |
d54362f9337ff16068150d7fba704c13
|
|
| BLAKE2b-256 |
2889b6a787e59bf7084f499f73ec2714cbf5f58965cc71bb8a70dfa1b9ceae60
|
File details
Details for the file antlr_v4_linter-0.1.4-py3-none-any.whl.
File metadata
- Download URL: antlr_v4_linter-0.1.4-py3-none-any.whl
- Upload date:
- Size: 67.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
67ade8b8f77e30d0d78d177f900f5a262df73fe85cb614954b196ae34ebbd908
|
|
| MD5 |
94db5e1d785a96bcda599bd7c722eee8
|
|
| BLAKE2b-256 |
4494e45812dbaa85d636a36bb969a3a76ba8c05aba1e783df35cef8260598265
|