Skip to main content

A fast LALR(1) parser for the OpenSCAD language with AST generation, powered by Lark.

Project description

openscad_lalr_parser

A fast LALR(1) parser for the OpenSCAD language with AST generation, powered by Lark.

Tests PyPI version License: MIT

Overview

openscad_lalr_parser parses OpenSCAD source code using a Lark-based LALR(1) parser and produces an abstract syntax tree (AST). The AST node classes are identical to those in the openscad_parser library, making it a drop-in replacement with significantly better performance.

Why LALR?

  • Speed: LALR(1) parsing is O(n) in the input size — no PEG backtracking overhead.
  • Predictability: Parse time is always proportional to input size.
  • Compatibility: Produces the same AST node types as openscad_parser.

Installation

pip install openscad-lalr-parser

For YAML output support:

pip install openscad-lalr-parser[yaml]

From Source

git clone https://github.com/BelfrySCAD/openscad_lalr_parser.git
cd openscad_lalr_parser
pip install -e ".[dev]"

Quick Start

Parse a String

from openscad_lalr_parser import getASTfromString

ast = getASTfromString("cube([1, 2, 3]);")
for node in ast:
    print(node)

Parse a File

from openscad_lalr_parser import getASTfromFile

ast = getASTfromFile("model.scad")
for node in ast:
    print(node)

Files are cached by modification time — repeated calls to getASTfromFile() with the same unchanged file return instantly. A disk cache is also maintained for persistence across interpreter sessions.

Include Comments

ast = getASTfromString("""
    // A comment
    x = 42; /* inline */
""", include_comments=True)

Comments are returned as CommentLine, CommentSpan, and BlankLine nodes at the top level. Inline comments adjacent to expressions are wrapped in CommentedExpr nodes with leading_comments and trailing_comments fields.

Scope Analysis

from openscad_lalr_parser import getASTfromString, build_scopes

ast = getASTfromString('''
    x = 10;
    function double(n) = n * 2;
    module box(size) { cube(size); }
''')

root_scope = build_scopes(ast)
print(root_scope.lookup_variable("x"))
print(root_scope.lookup_function("double"))
print(root_scope.lookup_module("box"))

Serialization

from openscad_lalr_parser import getASTfromString, ast_to_json, ast_from_json

ast = getASTfromString("cube(10);")

# Serialize to JSON
json_str = ast_to_json(ast, indent=2)

# Deserialize back to AST nodes
ast2 = ast_from_json(json_str)

YAML serialization is available when PyYAML is installed:

from openscad_lalr_parser import ast_to_yaml, ast_from_yaml

yaml_str = ast_to_yaml(ast)
ast2 = ast_from_yaml(yaml_str)

Pretty-Printing

from openscad_lalr_parser import getASTfromString, to_openscad

ast = getASTfromString("module box(w,h){cube([w,h,1]);}")
print(to_openscad(ast, indent_width=4))

Output:

module box(w, h) {
    cube([w, h, 1]);
}

CLI

The openscad-lalr command-line tool parses OpenSCAD files and outputs JSON, YAML, or reformatted source.

# Parse to JSON (default)
openscad-lalr model.scad

# Pretty-print / reformat
openscad-lalr --format model.scad

# YAML output
openscad-lalr --yaml model.scad

# Read from stdin
echo 'cube(10);' | openscad-lalr -

# Include comments in output
openscad-lalr --with-comments model.scad

# Custom indentation
openscad-lalr --format --indent 2 model.scad

# Skip include resolution
openscad-lalr --no-includes model.scad

API Reference

Parsing Functions

Function Description
getASTfromString(code, include_comments=False, origin="<string>") Parse OpenSCAD source code and return its AST.
getASTfromFile(file, include_comments=False, process_includes=True) Parse a file with mtime-based caching and optional include resolution.
getASTfromLibraryFile(currfile, libfile, ...) Find and parse a library file using OpenSCAD's search path rules.
parse_ast(code, origin="<string>") Low-level parse returning AST nodes (no comment processing).
findLibraryFile(currfile, libfile) Find a library file path without parsing it.
clear_ast_cache() Clear the in-memory and on-disk AST caches.

Serialization Functions

Function Description
ast_to_json(ast, indent=None) Serialize AST nodes to a JSON string.
ast_from_json(json_str) Deserialize AST nodes from a JSON string.
ast_to_dict(ast) Convert AST nodes to plain dicts.
ast_from_dict(data) Reconstruct AST nodes from dicts.
ast_to_yaml(ast) Serialize AST nodes to YAML (requires PyYAML).
ast_from_yaml(yaml_str) Deserialize AST nodes from YAML.
to_openscad(ast, indent_width=4) Pretty-print AST back to OpenSCAD source.

Scope Analysis

Function / Class Description
build_scopes(ast) Build scope tree for top-level AST nodes. Returns root Scope.
Scope Lexical scope with lookup_variable(), lookup_function(), lookup_module().

AST Node Classes

All AST nodes inherit from ASTNode. The main categories are:

Literals: Identifier, StringLiteral, NumberLiteral, BooleanLiteral, UndefinedLiteral, RangeLiteral

Operators: AdditionOp, SubtractionOp, MultiplicationOp, DivisionOp, ModuloOp, ExponentOp, UnaryMinusOp, LogicalAndOp, LogicalOrOp, LogicalNotOp, BitwiseAndOp, BitwiseOrOp, BitwiseNotOp, BitwiseShiftLeftOp, BitwiseShiftRightOp, EqualityOp, InequalityOp, GreaterThanOp, GreaterThanOrEqualOp, LessThanOp, LessThanOrEqualOp, TernaryOp

Expressions: PrimaryCall, PrimaryIndex, PrimaryMember, LetOp, EchoOp, AssertOp, FunctionLiteral, ListComprehension

List Comprehensions: ListCompFor, ListCompCFor, ListCompIf, ListCompIfElse, ListCompLet, ListCompEach

Declarations: Assignment, FunctionDeclaration, ModuleDeclaration, ParameterDeclaration

Module Instantiations: ModularCall, ModularFor, ModularIntersectionFor, ModularLet, ModularEcho, ModularAssert, ModularIf, ModularIfElse

Modifiers: ModularModifierShowOnly, ModularModifierHighlight, ModularModifierBackground, ModularModifierDisable

Imports: UseStatement, IncludeStatement

Arguments: PositionalArgument, NamedArgument

Comments: CommentLine, CommentSpan, CommentedExpr, BlankLine

Comparison with openscad_parser

Feature openscad_parser openscad_lalr_parser
Parser type PEG (Arpeggio) LALR(1) (Lark)
AST nodes ✓ (identical)
Scope analysis
Comment preservation
Inline comment attachment
Serialization (JSON/YAML)
Pretty-printing
Source maps
CLI tool ✓ (openscad-parser) ✓ (openscad-lalr)
Disk caching
Performance Baseline Faster (LALR, no backtracking)

Development

Running Tests

pytest tests/ -v

Running Tests with Coverage

pytest tests/ --cov=src/openscad_lalr_parser --cov-report=term-missing

License

MIT License - Copyright (c) 2025 Belfry OpenSCAD Libraries

See LICENSE for full text.

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

openscad_lalr_parser-1.0.2.tar.gz (30.9 kB view details)

Uploaded Source

Built Distribution

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

openscad_lalr_parser-1.0.2-py3-none-any.whl (35.5 kB view details)

Uploaded Python 3

File details

Details for the file openscad_lalr_parser-1.0.2.tar.gz.

File metadata

  • Download URL: openscad_lalr_parser-1.0.2.tar.gz
  • Upload date:
  • Size: 30.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for openscad_lalr_parser-1.0.2.tar.gz
Algorithm Hash digest
SHA256 011bb56f96cbac22b0d750c1f4c004ddc2548909bda39bd237e0d8a3a11f7016
MD5 265dc9b6cd7f1db36de0408f406d76aa
BLAKE2b-256 55158acfaa01ff7d06c37d56a87b4333fdbb5220dd0faf4949562ff992fed4d8

See more details on using hashes here.

Provenance

The following attestation bundles were made for openscad_lalr_parser-1.0.2.tar.gz:

Publisher: publish.yml on BelfrySCAD/openscad_lalr_parser

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file openscad_lalr_parser-1.0.2-py3-none-any.whl.

File metadata

File hashes

Hashes for openscad_lalr_parser-1.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 41f158f04f9c8b46bb448cba757dbb475f64a835291c38f021ddbcbe3d76afeb
MD5 cca7ec2595148c8872a8a706b7677e18
BLAKE2b-256 d14a69f6256f4d7f6b4547af6dce532723b2db68afe17ae9b1064d6cb4c44ca9

See more details on using hashes here.

Provenance

The following attestation bundles were made for openscad_lalr_parser-1.0.2-py3-none-any.whl:

Publisher: publish.yml on BelfrySCAD/openscad_lalr_parser

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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