Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -140,5 +140,6 @@ cython_debug/
*.egg-info

.pytest_cache/
.vscode/settings.json
.claude/worktrees/

24 changes: 18 additions & 6 deletions PRD.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
## Overview

**Project:** OpenSCAD Parser
**Version:** 2.0.0
**Version:** 2.2.0
**Status:** Beta
**License:** MIT

Expand Down Expand Up @@ -41,7 +41,7 @@ OpenSCAD is a popular programming language for creating parametric 3D CAD models
| Support comments in AST for documentation tools | Medium |
| Parse invalid code gracefully with useful errors | Medium |

## Current Capabilities (v2.0.0)
## Current Capabilities (v2.2.0)

### Language Support

Expand All @@ -63,7 +63,9 @@ Full parsing support for OpenSCAD 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 |
| Comment Preservation | Optional inclusion of comments in AST, including inside statement blocks |
| AST Serialization | JSON and YAML export/import of full ASTs |
| Scope Resolution | Lexical scope building with three separate namespaces (variables, functions, modules) |

### API Surface

Expand All @@ -77,6 +79,16 @@ from openscad_parser.ast import (
clear_ast_cache, # Clear AST cache
)

# Serialization
from openscad_parser.ast.serialization import (
ast_to_json, ast_from_json,
ast_to_yaml, ast_from_yaml,
ast_to_dict, ast_from_dict,
)

# Scope resolution
from openscad_parser.ast.scope import Scope, build_scopes

# Lower-level access
from openscad_parser import getOpenSCADParser
from openscad_parser.ast import parse_ast
Expand Down Expand Up @@ -117,6 +129,8 @@ from openscad_parser.ast import parse_ast
| 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 |
| Scope | `ast/scope.py` | Lexical scope building across three namespaces |
| Serialization | `ast/serialization.py` | JSON/YAML export and import of ASTs |
| API | `ast/__init__.py` | Public convenience functions |

## Quality Attributes
Expand Down Expand Up @@ -149,10 +163,9 @@ 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 |
| **Type Inference** | Infer types from scope analysis | Enable advanced linting, autocomplete |

### Medium Value

Expand Down Expand Up @@ -186,7 +199,6 @@ For open source contributors, consider these indicators of project health:

### Good First Issues

- 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
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "uv_build"

[project]
name = "openscad_parser"
version = "2.1.0"
version = "2.3.0"
description = "A PEG parser to read OpenSCAD language source code, with optional AST tree generation."
readme = "README.rst"
authors = [
Expand Down Expand Up @@ -33,12 +33,12 @@ classifiers = [
keywords = ["openscad", "openscad parser", "parser"]
dependencies = [
"arpeggio>=2.0.3",
"pytest-cov>=7.1.0",
]

[project.optional-dependencies]
dev = [
"pytest>=7.0.0",
"pytest-cov>=7.1.0",
]
yaml = [
"PyYAML>=6.0",
Expand Down
6 changes: 6 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ def parser_reduced():
return getOpenSCADParser(reduce_tree=True)


@pytest.fixture
def parser_comments():
"""Create a parser instance with comment inclusion enabled."""
return getOpenSCADParser(reduce_tree=False, include_comments=True)


def parse_success(parser, code):
"""Helper function to parse code and assert success."""
result = parser.parse(code)
Expand Down
6 changes: 2 additions & 4 deletions tests/test_modules.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import pytest
from tests.conftest import parse_success
from openscad_parser import getOpenSCADParser


class TestModuleDefinition:
Expand Down Expand Up @@ -53,12 +52,11 @@ def test_module_nested(self, parser):
code = "module outer() { module inner() {} }"
parse_success(parser, code)

def test_module_with_comment(self, parser):
def test_module_with_comment(self, parser, parser_comments):
"""Test module defined with comments"""
comment_parser = getOpenSCADParser(reduce_tree=False, include_comments=True)
code = "module test() {\nsphere(5);\n// comment\ncube(10);}"
parse_success(parser, code)
parse_success(comment_parser, code)
parse_success(parser_comments, code)

class TestModuleInstantiation:
"""Test module instantiation parsing."""
Expand Down
5 changes: 3 additions & 2 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading