Project: OpenSCAD Parser Version: 2.0.0 Status: Beta License: MIT
OpenSCAD Parser is a Python library that parses OpenSCAD language source code using a PEG (Parsing Expression Grammar) approach and generates an Abstract Syntax Tree (AST) for programmatic analysis and manipulation.
OpenSCAD is a popular programming language for creating parametric 3D CAD models. However, there is limited tooling for programmatically analyzing, transforming, or working with OpenSCAD source code. Developers building tools like:
- Code editors and IDE plugins
- Linters and static analyzers
- Code formatters
- Refactoring tools
- Documentation generators
- Model converters
...need a reliable parser that produces a well-structured AST with accurate source position tracking.
- Tool Developers - Building IDE plugins, linters, formatters, or other developer tools for OpenSCAD
- Library Authors - Creating higher-level abstractions on top of OpenSCAD
- Researchers - Analyzing OpenSCAD codebases for patterns, complexity metrics, or academic study
- Automation Engineers - Building pipelines that programmatically modify or generate OpenSCAD models
| Need | Priority |
|---|---|
| Parse valid OpenSCAD code into a traversable structure | Critical |
| Accurate source position tracking for error reporting | High |
| Handle include/use statements correctly | High |
| Support comments in AST for documentation tools | Medium |
| Parse invalid code gracefully with useful errors | Medium |
Full parsing support for OpenSCAD language constructs:
- Declarations: Module definitions, function definitions, variable assignments
- Expressions: Arithmetic, logical, comparison, bitwise, ternary operators with correct precedence
- Literals: Numbers, strings, booleans, vectors, ranges
- Control Structures: if/else, for loops, let expressions, assert, echo
- Module System: Module calls with modifiers (!, #, %, *), use/include statements
- Advanced: List comprehensions, nested expressions, complex nesting
| Feature | Description |
|---|---|
| PEG Grammar | Complete grammar covering OpenSCAD language (~420 rules) |
| AST Generation | Dataclass-based nodes for all language constructs |
| Source Mapping | Track positions across multiple files (essential for includes) |
| Caching | In-memory AST cache with modification time validation |
| Library Resolution | Platform-aware search paths matching OpenSCAD behavior |
| Comment Preservation | Optional inclusion of comments in AST |
# High-level convenience functions
from openscad_parser.ast import (
getASTfromString, # Parse code from string
getASTfromFile, # Parse file with caching
getASTfromLibraryFile, # Resolve and parse library files
findLibraryFile, # Locate library files
clear_ast_cache, # Clear AST cache
)
# Lower-level access
from openscad_parser import getOpenSCADParser
from openscad_parser.ast import parse_ast┌─────────────────────────────────────────────────────────────┐
│ User Code │
├─────────────────────────────────────────────────────────────┤
│ Convenience API: getASTfromString, getASTfromFile, etc. │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
│ │ Parser │───►│ Parse Tree │───►│ ASTBuilder │ │
│ │ (Arpeggio) │ │ │ │ (Visitor) │ │
│ └─────────────┘ └─────────────┘ └─────────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────────┐ │
│ │ grammar.py │ │ AST Nodes │ │
│ │ (PEG rules) │ │ (dataclasses) │ │
│ └─────────────┘ └─────────────────┘ │
│ │ │
│ ┌────────┴────────┐ │
│ │ SourceMap │ │
│ │ (position track)│ │
│ └─────────────────┘ │
└─────────────────────────────────────────────────────────────┘
| Component | File | Responsibility |
|---|---|---|
| Grammar | grammar.py |
PEG parsing rules for OpenSCAD syntax |
| AST Nodes | ast/nodes.py |
Dataclass definitions for all node types |
| Builder | ast/builder.py |
Visitor that converts parse tree to AST |
| Source Map | ast/source_map.py |
Tracks positions across multiple origins |
| API | ast/__init__.py |
Public convenience functions |
- Parser memoization via Arpeggio
- AST caching with modification time validation
- Efficient source map lookups
- Comprehensive test suite (~200+ tests)
- Tests organized by language feature
- No known parsing failures for valid OpenSCAD code
- Simple high-level API for common use cases
- Lower-level access available when needed
- Accurate error messages with source positions
- Clean separation between parsing and AST construction
- Dataclass-based nodes are easy to extend
- Type hints throughout codebase
The following are potential enhancements for contributors to consider:
| Enhancement | Description | Rationale |
|---|---|---|
| AST Serialization | JSON/YAML export of AST | Enable language-agnostic tooling |
| Code Generation | AST to OpenSCAD source | Enable refactoring tools, formatters |
| Error Recovery | Parse partial/invalid code | Better IDE integration, real-time parsing |
| Semantic Analysis | Type inference, scope resolution | Enable advanced linting, autocomplete |
| Enhancement | Description | Rationale |
|---|---|---|
| AST Diffing | Compare two ASTs structurally | Enable change detection tools |
| Tree Walkers | Pre-built visitor utilities | Reduce boilerplate for common traversals |
| Pretty Printer | Configurable code formatting | Standardize code style |
| Symbol Table | Track variable/function definitions | Enable go-to-definition, find-references |
| Enhancement | Description | Rationale |
|---|---|---|
| Language Server Protocol | LSP implementation | Full IDE integration |
| Incremental Parsing | Re-parse only changed sections | Performance for large files |
| Custom Extensions | Support for OpenSCAD variants | Handle customizer syntax, etc. |
For open source contributors, consider these indicators of project health:
| Metric | Current | Notes |
|---|---|---|
| Test Coverage | High | Comprehensive suite, no skipped tests |
| Documentation | Good | README, docstrings, source map guide |
| API Stability | Improving | v2.0.0 indicates recent breaking changes |
| Dependencies | Minimal | Only Arpeggio required |
- Add JSON serialization for AST nodes
- Create utility functions for common AST traversals
- Improve error messages for parse failures
- Add examples for common use cases
git clone https://github.com/belfryscad/openscad_parser.git
cd openscad_parser
pip install -e ".[dev]"
pytest tests/- Use type hints for all public APIs
- Follow existing patterns for AST node definitions
- Add tests for any new functionality
- Keep dependencies minimal