openscad-parser 1.0.1__tar.gz → 2.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {openscad_parser-1.0.1 → openscad_parser-2.2.0}/PKG-INFO +178 -4
- {openscad_parser-1.0.1 → openscad_parser-2.2.0}/README.rst +174 -2
- {openscad_parser-1.0.1 → openscad_parser-2.2.0}/pyproject.toml +5 -2
- openscad_parser-2.2.0/src/openscad_parser/__init__.py +38 -0
- openscad_parser-2.2.0/src/openscad_parser/ast/__init__.py +434 -0
- openscad_parser-2.2.0/src/openscad_parser/ast/builder.py +1254 -0
- openscad_parser-2.2.0/src/openscad_parser/ast/nodes.py +2011 -0
- openscad_parser-2.2.0/src/openscad_parser/ast/scope.py +122 -0
- openscad_parser-2.2.0/src/openscad_parser/ast/serialization.py +436 -0
- openscad_parser-2.2.0/src/openscad_parser/ast/source_map.py +606 -0
- openscad_parser-2.2.0/src/openscad_parser/grammar.py +701 -0
- openscad_parser-1.0.1/src/openscad_parser/__init__.py +0 -491
- openscad_parser-1.0.1/src/openscad_parser/ast.py +0 -2975
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openscad_parser
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.2.0
|
|
4
4
|
Summary: A PEG parser to read OpenSCAD language source code, with optional AST tree generation.
|
|
5
5
|
Keywords: openscad,openscad parser,parser
|
|
6
6
|
Author: Revar Desmera
|
|
@@ -21,9 +21,10 @@ Classifier: Topic :: Software Development :: Libraries
|
|
|
21
21
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
22
|
Requires-Dist: arpeggio>=2.0.3
|
|
23
23
|
Requires-Dist: pytest>=7.0.0 ; extra == 'dev'
|
|
24
|
+
Requires-Dist: pyyaml>=6.0 ; extra == 'yaml'
|
|
24
25
|
Maintainer: Revar Desmera
|
|
25
26
|
Maintainer-email: Revar Desmera <revarbat@gmail.com>
|
|
26
|
-
Requires-Python: >=3.
|
|
27
|
+
Requires-Python: >=3.11
|
|
27
28
|
Project-URL: Bug Tracker, https://github.com/belfryscad/openscad_parser/issues
|
|
28
29
|
Project-URL: Documentation, https://github.com/belfryscad/openscad_parser/WRITING_DOCS.md
|
|
29
30
|
Project-URL: Homepage, https://github.com/belfryscad/openscad_parser
|
|
@@ -31,6 +32,7 @@ Project-URL: Releases, https://github.com/belfryscad/openscad_parser/releases
|
|
|
31
32
|
Project-URL: Repository, https://github.com/belfryscad/openscad_parser
|
|
32
33
|
Project-URL: Usage, https://github.com/belfryscad/openscad_parser/README.rst
|
|
33
34
|
Provides-Extra: dev
|
|
35
|
+
Provides-Extra: yaml
|
|
34
36
|
Description-Content-Type: text/x-rst
|
|
35
37
|
|
|
36
38
|
OpenSCAD Parser
|
|
@@ -53,6 +55,7 @@ Features
|
|
|
53
55
|
- Source position tracking for all AST nodes
|
|
54
56
|
- AST tree can contain comment nodes (single-line and multi-line)
|
|
55
57
|
- AST tree uses dataclasses and can be pickled/unpickled for caching/serialization
|
|
58
|
+
- JSON and YAML serialization/deserialization of AST trees
|
|
56
59
|
|
|
57
60
|
Installation
|
|
58
61
|
------------
|
|
@@ -145,6 +148,13 @@ Use ``getASTfromFile()`` to parse an OpenSCAD file. This function includes autom
|
|
|
145
148
|
|
|
146
149
|
The cache is automatically invalidated when the file is modified, ensuring you always get up-to-date results.
|
|
147
150
|
|
|
151
|
+
**Include Processing:** By default, ``getASTfromFile()`` processes ``include <file>`` statements before parsing (``process_includes=True``). This means the AST will NOT contain ``IncludeStatement`` nodes - instead, the included file contents are expanded into the AST. Set ``process_includes=False`` to preserve ``IncludeStatement`` nodes in the AST::
|
|
152
|
+
|
|
153
|
+
# Get AST with IncludeStatement nodes preserved
|
|
154
|
+
ast_with_includes = getASTfromFile("my_model.scad", process_includes=False)
|
|
155
|
+
|
|
156
|
+
**Note:** Unlike ``include`` statements, ``use <file>`` statements are ALWAYS parsed into ``UseStatement`` AST nodes, regardless of the ``process_includes`` setting. This is because ``use`` statements only affect module and function lookup at runtime, not source inclusion.
|
|
157
|
+
|
|
148
158
|
Parsing Library Files
|
|
149
159
|
^^^^^^^^^^^^^^^^^^^^^^
|
|
150
160
|
|
|
@@ -466,27 +476,43 @@ Main Functions
|
|
|
466
476
|
:returns: AST node or list of AST nodes (for top-level statements)
|
|
467
477
|
:rtype: ASTNode | list[ASTNode] | None
|
|
468
478
|
|
|
469
|
-
``getASTfromFile(file: str)``
|
|
479
|
+
``getASTfromFile(file: str, include_comments: bool = False, process_includes: bool = True)``
|
|
470
480
|
Parse an OpenSCAD source file and return its AST. Includes automatic caching
|
|
471
481
|
that invalidates when the file's modification timestamp changes.
|
|
472
482
|
|
|
473
483
|
:param file: The OpenSCAD source file to be parsed
|
|
484
|
+
:param include_comments: If True, include comments in the AST (default: False)
|
|
485
|
+
:param process_includes: If True, process include statements and replace with file contents (default: True).
|
|
486
|
+
When False, the AST will contain IncludeStatement nodes where includes appear.
|
|
474
487
|
:returns: List of AST nodes (for top-level statements)
|
|
475
488
|
:rtype: list[ASTNode] | None
|
|
476
489
|
:raises FileNotFoundError: If the specified file does not exist
|
|
477
490
|
:raises Exception: If there is an error while reading the file
|
|
478
491
|
|
|
479
|
-
``
|
|
492
|
+
**Note:** When ``process_includes=True`` (default), the AST will NOT contain ``IncludeStatement`` nodes
|
|
493
|
+
because includes are processed before parsing. When ``process_includes=False``, ``IncludeStatement``
|
|
494
|
+
nodes will appear in the AST where ``include <file>`` statements exist in the source code.
|
|
495
|
+
|
|
496
|
+
Unlike ``include`` statements, ``use <file>`` statements are ALWAYS parsed into ``UseStatement``
|
|
497
|
+
AST nodes regardless of the ``process_includes`` setting, since ``use`` only affects runtime
|
|
498
|
+
lookup, not source inclusion.
|
|
499
|
+
|
|
500
|
+
``getASTfromLibraryFile(currfile: str, libfile: str, include_comments: bool = False, process_includes: bool = True)``
|
|
480
501
|
Find and parse an OpenSCAD library file using OpenSCAD's search path rules.
|
|
481
502
|
Searches in: current file directory, OPENSCADPATH, and platform default paths.
|
|
482
503
|
|
|
483
504
|
:param currfile: Full path to the current OpenSCAD file (can be empty string)
|
|
484
505
|
:param libfile: Partial or full path to the library file to find
|
|
506
|
+
:param include_comments: If True, include comments in the AST (default: False)
|
|
507
|
+
:param process_includes: If True, process include statements (default: True).
|
|
508
|
+
When False, the AST will contain IncludeStatement nodes where includes appear.
|
|
485
509
|
:returns: Tuple of (AST nodes list, absolute file path). The AST list is None if empty or not valid.
|
|
486
510
|
:rtype: tuple[list[ASTNode] | None, str]
|
|
487
511
|
:raises FileNotFoundError: If the library file cannot be found
|
|
488
512
|
:raises Exception: If there is an error while reading or parsing the file
|
|
489
513
|
|
|
514
|
+
**Note:** The ``process_includes`` parameter affects the AST structure (see ``getASTfromFile`` documentation).
|
|
515
|
+
|
|
490
516
|
``parse_ast(parser, code, file="")``
|
|
491
517
|
Parse OpenSCAD code and generate an AST (lower-level API).
|
|
492
518
|
|
|
@@ -501,6 +527,65 @@ Main Functions
|
|
|
501
527
|
|
|
502
528
|
This function removes all cached AST trees from memory.
|
|
503
529
|
|
|
530
|
+
Serialization Functions
|
|
531
|
+
~~~~~~~~~~~~~~~~~~~~~~~
|
|
532
|
+
|
|
533
|
+
``ast_to_dict(ast: ASTNode | Sequence[ASTNode] | None, include_position: bool = True)``
|
|
534
|
+
Convert an AST to a Python dictionary (JSON-serializable).
|
|
535
|
+
|
|
536
|
+
:param ast: An AST node, sequence of AST nodes, or None
|
|
537
|
+
:param include_position: If True, include source position information (default: True)
|
|
538
|
+
:returns: A dictionary representation of the AST, a list of dictionaries, or None
|
|
539
|
+
:rtype: dict[str, Any] | list[dict[str, Any]] | None
|
|
540
|
+
|
|
541
|
+
``ast_to_json(ast: ASTNode | Sequence[ASTNode] | None, include_position: bool = True, indent: int | None = 2)``
|
|
542
|
+
Serialize an AST to a JSON string.
|
|
543
|
+
|
|
544
|
+
:param ast: An AST node, sequence of AST nodes, or None
|
|
545
|
+
:param include_position: If True, include source position information (default: True)
|
|
546
|
+
:param indent: Indentation level for pretty-printing. Use None for compact output (default: 2)
|
|
547
|
+
:returns: A JSON string representation of the AST
|
|
548
|
+
:rtype: str
|
|
549
|
+
|
|
550
|
+
``ast_from_dict(data: dict[str, Any] | list[dict[str, Any]] | None)``
|
|
551
|
+
Reconstruct an AST from a Python dictionary.
|
|
552
|
+
|
|
553
|
+
:param data: A dictionary, list of dictionaries, or None (as returned by ast_to_dict)
|
|
554
|
+
:returns: An AST node, list of AST nodes, or None
|
|
555
|
+
:rtype: ASTNode | list[ASTNode] | None
|
|
556
|
+
:raises ValueError: If the data contains an unknown node type or is malformed
|
|
557
|
+
|
|
558
|
+
``ast_from_json(json_str: str)``
|
|
559
|
+
Deserialize an AST from a JSON string.
|
|
560
|
+
|
|
561
|
+
:param json_str: A JSON string (as returned by ast_to_json)
|
|
562
|
+
:returns: An AST node, list of AST nodes, or None
|
|
563
|
+
:rtype: ASTNode | list[ASTNode] | None
|
|
564
|
+
:raises ValueError: If the JSON contains an unknown node type or is malformed
|
|
565
|
+
:raises json.JSONDecodeError: If the string is not valid JSON
|
|
566
|
+
|
|
567
|
+
``ast_to_yaml(ast: ASTNode | Sequence[ASTNode] | None, include_position: bool = True)``
|
|
568
|
+
Serialize an AST to a YAML string.
|
|
569
|
+
|
|
570
|
+
Requires PyYAML to be installed: ``pip install openscad_parser[yaml]``
|
|
571
|
+
|
|
572
|
+
:param ast: An AST node, sequence of AST nodes, or None
|
|
573
|
+
:param include_position: If True, include source position information (default: True)
|
|
574
|
+
:returns: A YAML string representation of the AST
|
|
575
|
+
:rtype: str
|
|
576
|
+
:raises ImportError: If PyYAML is not installed
|
|
577
|
+
|
|
578
|
+
``ast_from_yaml(yaml_str: str)``
|
|
579
|
+
Deserialize an AST from a YAML string.
|
|
580
|
+
|
|
581
|
+
Requires PyYAML to be installed: ``pip install openscad_parser[yaml]``
|
|
582
|
+
|
|
583
|
+
:param yaml_str: A YAML string (as returned by ast_to_yaml)
|
|
584
|
+
:returns: An AST node, list of AST nodes, or None
|
|
585
|
+
:rtype: ASTNode | list[ASTNode] | None
|
|
586
|
+
:raises ImportError: If PyYAML is not installed
|
|
587
|
+
:raises ValueError: If the YAML contains an unknown node type or is malformed
|
|
588
|
+
|
|
504
589
|
AST Node Classes
|
|
505
590
|
~~~~~~~~~~~~~~~~
|
|
506
591
|
|
|
@@ -557,6 +642,95 @@ All AST nodes include source position information::
|
|
|
557
642
|
|
|
558
643
|
The ``Position`` class provides lazy evaluation of line/column numbers from character positions.
|
|
559
644
|
|
|
645
|
+
Serialization
|
|
646
|
+
-------------
|
|
647
|
+
|
|
648
|
+
AST trees can be serialized to JSON or YAML formats and deserialized back to AST nodes. This is useful for caching, storage, or transferring AST data between processes.
|
|
649
|
+
|
|
650
|
+
JSON Serialization
|
|
651
|
+
~~~~~~~~~~~~~~~~~~
|
|
652
|
+
|
|
653
|
+
Serialize an AST to JSON::
|
|
654
|
+
|
|
655
|
+
from openscad_parser.ast import getASTfromString, ast_to_json, ast_from_json
|
|
656
|
+
|
|
657
|
+
# Parse code to AST
|
|
658
|
+
ast = getASTfromString("cube(10);")
|
|
659
|
+
|
|
660
|
+
# Serialize to JSON string
|
|
661
|
+
json_str = ast_to_json(ast, include_position=True, indent=2)
|
|
662
|
+
|
|
663
|
+
# Deserialize back to AST
|
|
664
|
+
ast_restored = ast_from_json(json_str)
|
|
665
|
+
|
|
666
|
+
The ``ast_to_json()`` function accepts:
|
|
667
|
+
- ``ast``: An AST node, sequence of AST nodes, or None
|
|
668
|
+
- ``include_position``: If True, include source position information (default: True)
|
|
669
|
+
- ``indent``: Indentation level for pretty-printing. Use None for compact output (default: 2)
|
|
670
|
+
|
|
671
|
+
Dictionary Serialization
|
|
672
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
673
|
+
|
|
674
|
+
You can also work with Python dictionaries directly::
|
|
675
|
+
|
|
676
|
+
from openscad_parser.ast import getASTfromString, ast_to_dict, ast_from_dict
|
|
677
|
+
|
|
678
|
+
ast = getASTfromString("x = 42;")
|
|
679
|
+
|
|
680
|
+
# Convert to dictionary
|
|
681
|
+
data = ast_to_dict(ast, include_position=True)
|
|
682
|
+
|
|
683
|
+
# Convert back to AST
|
|
684
|
+
ast_restored = ast_from_dict(data)
|
|
685
|
+
|
|
686
|
+
YAML Serialization
|
|
687
|
+
~~~~~~~~~~~~~~~~~~
|
|
688
|
+
|
|
689
|
+
For YAML serialization, you need to install PyYAML::
|
|
690
|
+
|
|
691
|
+
pip install openscad_parser[yaml]
|
|
692
|
+
|
|
693
|
+
Then serialize to YAML::
|
|
694
|
+
|
|
695
|
+
from openscad_parser.ast import getASTfromString, ast_to_yaml, ast_from_yaml
|
|
696
|
+
|
|
697
|
+
ast = getASTfromString("cube(10);")
|
|
698
|
+
|
|
699
|
+
# Serialize to YAML string
|
|
700
|
+
yaml_str = ast_to_yaml(ast, include_position=True)
|
|
701
|
+
|
|
702
|
+
# Deserialize back to AST
|
|
703
|
+
ast_restored = ast_from_yaml(yaml_str)
|
|
704
|
+
|
|
705
|
+
The ``ast_to_yaml()`` function accepts:
|
|
706
|
+
- ``ast``: An AST node, sequence of AST nodes, or None
|
|
707
|
+
- ``include_position``: If True, include source position information (default: True)
|
|
708
|
+
|
|
709
|
+
Serialization Functions
|
|
710
|
+
~~~~~~~~~~~~~~~~~~~~~~~
|
|
711
|
+
|
|
712
|
+
All serialization functions can be imported directly from ``openscad_parser.ast`` (recommended)::
|
|
713
|
+
|
|
714
|
+
from openscad_parser.ast import (
|
|
715
|
+
ast_to_dict,
|
|
716
|
+
ast_to_json,
|
|
717
|
+
ast_to_yaml,
|
|
718
|
+
ast_from_dict,
|
|
719
|
+
ast_from_json,
|
|
720
|
+
ast_from_yaml,
|
|
721
|
+
)
|
|
722
|
+
|
|
723
|
+
They are also available from ``openscad_parser.ast.serialization``::
|
|
724
|
+
|
|
725
|
+
from openscad_parser.ast.serialization import (
|
|
726
|
+
ast_to_dict,
|
|
727
|
+
ast_to_json,
|
|
728
|
+
ast_to_yaml,
|
|
729
|
+
ast_from_dict,
|
|
730
|
+
ast_from_json,
|
|
731
|
+
ast_from_yaml,
|
|
732
|
+
)
|
|
733
|
+
|
|
560
734
|
Error Handling
|
|
561
735
|
--------------
|
|
562
736
|
|
|
@@ -18,6 +18,7 @@ Features
|
|
|
18
18
|
- Source position tracking for all AST nodes
|
|
19
19
|
- AST tree can contain comment nodes (single-line and multi-line)
|
|
20
20
|
- AST tree uses dataclasses and can be pickled/unpickled for caching/serialization
|
|
21
|
+
- JSON and YAML serialization/deserialization of AST trees
|
|
21
22
|
|
|
22
23
|
Installation
|
|
23
24
|
------------
|
|
@@ -110,6 +111,13 @@ Use ``getASTfromFile()`` to parse an OpenSCAD file. This function includes autom
|
|
|
110
111
|
|
|
111
112
|
The cache is automatically invalidated when the file is modified, ensuring you always get up-to-date results.
|
|
112
113
|
|
|
114
|
+
**Include Processing:** By default, ``getASTfromFile()`` processes ``include <file>`` statements before parsing (``process_includes=True``). This means the AST will NOT contain ``IncludeStatement`` nodes - instead, the included file contents are expanded into the AST. Set ``process_includes=False`` to preserve ``IncludeStatement`` nodes in the AST::
|
|
115
|
+
|
|
116
|
+
# Get AST with IncludeStatement nodes preserved
|
|
117
|
+
ast_with_includes = getASTfromFile("my_model.scad", process_includes=False)
|
|
118
|
+
|
|
119
|
+
**Note:** Unlike ``include`` statements, ``use <file>`` statements are ALWAYS parsed into ``UseStatement`` AST nodes, regardless of the ``process_includes`` setting. This is because ``use`` statements only affect module and function lookup at runtime, not source inclusion.
|
|
120
|
+
|
|
113
121
|
Parsing Library Files
|
|
114
122
|
^^^^^^^^^^^^^^^^^^^^^^
|
|
115
123
|
|
|
@@ -431,27 +439,43 @@ Main Functions
|
|
|
431
439
|
:returns: AST node or list of AST nodes (for top-level statements)
|
|
432
440
|
:rtype: ASTNode | list[ASTNode] | None
|
|
433
441
|
|
|
434
|
-
``getASTfromFile(file: str)``
|
|
442
|
+
``getASTfromFile(file: str, include_comments: bool = False, process_includes: bool = True)``
|
|
435
443
|
Parse an OpenSCAD source file and return its AST. Includes automatic caching
|
|
436
444
|
that invalidates when the file's modification timestamp changes.
|
|
437
445
|
|
|
438
446
|
:param file: The OpenSCAD source file to be parsed
|
|
447
|
+
:param include_comments: If True, include comments in the AST (default: False)
|
|
448
|
+
:param process_includes: If True, process include statements and replace with file contents (default: True).
|
|
449
|
+
When False, the AST will contain IncludeStatement nodes where includes appear.
|
|
439
450
|
:returns: List of AST nodes (for top-level statements)
|
|
440
451
|
:rtype: list[ASTNode] | None
|
|
441
452
|
:raises FileNotFoundError: If the specified file does not exist
|
|
442
453
|
:raises Exception: If there is an error while reading the file
|
|
443
454
|
|
|
444
|
-
``
|
|
455
|
+
**Note:** When ``process_includes=True`` (default), the AST will NOT contain ``IncludeStatement`` nodes
|
|
456
|
+
because includes are processed before parsing. When ``process_includes=False``, ``IncludeStatement``
|
|
457
|
+
nodes will appear in the AST where ``include <file>`` statements exist in the source code.
|
|
458
|
+
|
|
459
|
+
Unlike ``include`` statements, ``use <file>`` statements are ALWAYS parsed into ``UseStatement``
|
|
460
|
+
AST nodes regardless of the ``process_includes`` setting, since ``use`` only affects runtime
|
|
461
|
+
lookup, not source inclusion.
|
|
462
|
+
|
|
463
|
+
``getASTfromLibraryFile(currfile: str, libfile: str, include_comments: bool = False, process_includes: bool = True)``
|
|
445
464
|
Find and parse an OpenSCAD library file using OpenSCAD's search path rules.
|
|
446
465
|
Searches in: current file directory, OPENSCADPATH, and platform default paths.
|
|
447
466
|
|
|
448
467
|
:param currfile: Full path to the current OpenSCAD file (can be empty string)
|
|
449
468
|
:param libfile: Partial or full path to the library file to find
|
|
469
|
+
:param include_comments: If True, include comments in the AST (default: False)
|
|
470
|
+
:param process_includes: If True, process include statements (default: True).
|
|
471
|
+
When False, the AST will contain IncludeStatement nodes where includes appear.
|
|
450
472
|
:returns: Tuple of (AST nodes list, absolute file path). The AST list is None if empty or not valid.
|
|
451
473
|
:rtype: tuple[list[ASTNode] | None, str]
|
|
452
474
|
:raises FileNotFoundError: If the library file cannot be found
|
|
453
475
|
:raises Exception: If there is an error while reading or parsing the file
|
|
454
476
|
|
|
477
|
+
**Note:** The ``process_includes`` parameter affects the AST structure (see ``getASTfromFile`` documentation).
|
|
478
|
+
|
|
455
479
|
``parse_ast(parser, code, file="")``
|
|
456
480
|
Parse OpenSCAD code and generate an AST (lower-level API).
|
|
457
481
|
|
|
@@ -466,6 +490,65 @@ Main Functions
|
|
|
466
490
|
|
|
467
491
|
This function removes all cached AST trees from memory.
|
|
468
492
|
|
|
493
|
+
Serialization Functions
|
|
494
|
+
~~~~~~~~~~~~~~~~~~~~~~~
|
|
495
|
+
|
|
496
|
+
``ast_to_dict(ast: ASTNode | Sequence[ASTNode] | None, include_position: bool = True)``
|
|
497
|
+
Convert an AST to a Python dictionary (JSON-serializable).
|
|
498
|
+
|
|
499
|
+
:param ast: An AST node, sequence of AST nodes, or None
|
|
500
|
+
:param include_position: If True, include source position information (default: True)
|
|
501
|
+
:returns: A dictionary representation of the AST, a list of dictionaries, or None
|
|
502
|
+
:rtype: dict[str, Any] | list[dict[str, Any]] | None
|
|
503
|
+
|
|
504
|
+
``ast_to_json(ast: ASTNode | Sequence[ASTNode] | None, include_position: bool = True, indent: int | None = 2)``
|
|
505
|
+
Serialize an AST to a JSON string.
|
|
506
|
+
|
|
507
|
+
:param ast: An AST node, sequence of AST nodes, or None
|
|
508
|
+
:param include_position: If True, include source position information (default: True)
|
|
509
|
+
:param indent: Indentation level for pretty-printing. Use None for compact output (default: 2)
|
|
510
|
+
:returns: A JSON string representation of the AST
|
|
511
|
+
:rtype: str
|
|
512
|
+
|
|
513
|
+
``ast_from_dict(data: dict[str, Any] | list[dict[str, Any]] | None)``
|
|
514
|
+
Reconstruct an AST from a Python dictionary.
|
|
515
|
+
|
|
516
|
+
:param data: A dictionary, list of dictionaries, or None (as returned by ast_to_dict)
|
|
517
|
+
:returns: An AST node, list of AST nodes, or None
|
|
518
|
+
:rtype: ASTNode | list[ASTNode] | None
|
|
519
|
+
:raises ValueError: If the data contains an unknown node type or is malformed
|
|
520
|
+
|
|
521
|
+
``ast_from_json(json_str: str)``
|
|
522
|
+
Deserialize an AST from a JSON string.
|
|
523
|
+
|
|
524
|
+
:param json_str: A JSON string (as returned by ast_to_json)
|
|
525
|
+
:returns: An AST node, list of AST nodes, or None
|
|
526
|
+
:rtype: ASTNode | list[ASTNode] | None
|
|
527
|
+
:raises ValueError: If the JSON contains an unknown node type or is malformed
|
|
528
|
+
:raises json.JSONDecodeError: If the string is not valid JSON
|
|
529
|
+
|
|
530
|
+
``ast_to_yaml(ast: ASTNode | Sequence[ASTNode] | None, include_position: bool = True)``
|
|
531
|
+
Serialize an AST to a YAML string.
|
|
532
|
+
|
|
533
|
+
Requires PyYAML to be installed: ``pip install openscad_parser[yaml]``
|
|
534
|
+
|
|
535
|
+
:param ast: An AST node, sequence of AST nodes, or None
|
|
536
|
+
:param include_position: If True, include source position information (default: True)
|
|
537
|
+
:returns: A YAML string representation of the AST
|
|
538
|
+
:rtype: str
|
|
539
|
+
:raises ImportError: If PyYAML is not installed
|
|
540
|
+
|
|
541
|
+
``ast_from_yaml(yaml_str: str)``
|
|
542
|
+
Deserialize an AST from a YAML string.
|
|
543
|
+
|
|
544
|
+
Requires PyYAML to be installed: ``pip install openscad_parser[yaml]``
|
|
545
|
+
|
|
546
|
+
:param yaml_str: A YAML string (as returned by ast_to_yaml)
|
|
547
|
+
:returns: An AST node, list of AST nodes, or None
|
|
548
|
+
:rtype: ASTNode | list[ASTNode] | None
|
|
549
|
+
:raises ImportError: If PyYAML is not installed
|
|
550
|
+
:raises ValueError: If the YAML contains an unknown node type or is malformed
|
|
551
|
+
|
|
469
552
|
AST Node Classes
|
|
470
553
|
~~~~~~~~~~~~~~~~
|
|
471
554
|
|
|
@@ -522,6 +605,95 @@ All AST nodes include source position information::
|
|
|
522
605
|
|
|
523
606
|
The ``Position`` class provides lazy evaluation of line/column numbers from character positions.
|
|
524
607
|
|
|
608
|
+
Serialization
|
|
609
|
+
-------------
|
|
610
|
+
|
|
611
|
+
AST trees can be serialized to JSON or YAML formats and deserialized back to AST nodes. This is useful for caching, storage, or transferring AST data between processes.
|
|
612
|
+
|
|
613
|
+
JSON Serialization
|
|
614
|
+
~~~~~~~~~~~~~~~~~~
|
|
615
|
+
|
|
616
|
+
Serialize an AST to JSON::
|
|
617
|
+
|
|
618
|
+
from openscad_parser.ast import getASTfromString, ast_to_json, ast_from_json
|
|
619
|
+
|
|
620
|
+
# Parse code to AST
|
|
621
|
+
ast = getASTfromString("cube(10);")
|
|
622
|
+
|
|
623
|
+
# Serialize to JSON string
|
|
624
|
+
json_str = ast_to_json(ast, include_position=True, indent=2)
|
|
625
|
+
|
|
626
|
+
# Deserialize back to AST
|
|
627
|
+
ast_restored = ast_from_json(json_str)
|
|
628
|
+
|
|
629
|
+
The ``ast_to_json()`` function accepts:
|
|
630
|
+
- ``ast``: An AST node, sequence of AST nodes, or None
|
|
631
|
+
- ``include_position``: If True, include source position information (default: True)
|
|
632
|
+
- ``indent``: Indentation level for pretty-printing. Use None for compact output (default: 2)
|
|
633
|
+
|
|
634
|
+
Dictionary Serialization
|
|
635
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
636
|
+
|
|
637
|
+
You can also work with Python dictionaries directly::
|
|
638
|
+
|
|
639
|
+
from openscad_parser.ast import getASTfromString, ast_to_dict, ast_from_dict
|
|
640
|
+
|
|
641
|
+
ast = getASTfromString("x = 42;")
|
|
642
|
+
|
|
643
|
+
# Convert to dictionary
|
|
644
|
+
data = ast_to_dict(ast, include_position=True)
|
|
645
|
+
|
|
646
|
+
# Convert back to AST
|
|
647
|
+
ast_restored = ast_from_dict(data)
|
|
648
|
+
|
|
649
|
+
YAML Serialization
|
|
650
|
+
~~~~~~~~~~~~~~~~~~
|
|
651
|
+
|
|
652
|
+
For YAML serialization, you need to install PyYAML::
|
|
653
|
+
|
|
654
|
+
pip install openscad_parser[yaml]
|
|
655
|
+
|
|
656
|
+
Then serialize to YAML::
|
|
657
|
+
|
|
658
|
+
from openscad_parser.ast import getASTfromString, ast_to_yaml, ast_from_yaml
|
|
659
|
+
|
|
660
|
+
ast = getASTfromString("cube(10);")
|
|
661
|
+
|
|
662
|
+
# Serialize to YAML string
|
|
663
|
+
yaml_str = ast_to_yaml(ast, include_position=True)
|
|
664
|
+
|
|
665
|
+
# Deserialize back to AST
|
|
666
|
+
ast_restored = ast_from_yaml(yaml_str)
|
|
667
|
+
|
|
668
|
+
The ``ast_to_yaml()`` function accepts:
|
|
669
|
+
- ``ast``: An AST node, sequence of AST nodes, or None
|
|
670
|
+
- ``include_position``: If True, include source position information (default: True)
|
|
671
|
+
|
|
672
|
+
Serialization Functions
|
|
673
|
+
~~~~~~~~~~~~~~~~~~~~~~~
|
|
674
|
+
|
|
675
|
+
All serialization functions can be imported directly from ``openscad_parser.ast`` (recommended)::
|
|
676
|
+
|
|
677
|
+
from openscad_parser.ast import (
|
|
678
|
+
ast_to_dict,
|
|
679
|
+
ast_to_json,
|
|
680
|
+
ast_to_yaml,
|
|
681
|
+
ast_from_dict,
|
|
682
|
+
ast_from_json,
|
|
683
|
+
ast_from_yaml,
|
|
684
|
+
)
|
|
685
|
+
|
|
686
|
+
They are also available from ``openscad_parser.ast.serialization``::
|
|
687
|
+
|
|
688
|
+
from openscad_parser.ast.serialization import (
|
|
689
|
+
ast_to_dict,
|
|
690
|
+
ast_to_json,
|
|
691
|
+
ast_to_yaml,
|
|
692
|
+
ast_from_dict,
|
|
693
|
+
ast_from_json,
|
|
694
|
+
ast_from_yaml,
|
|
695
|
+
)
|
|
696
|
+
|
|
525
697
|
Error Handling
|
|
526
698
|
--------------
|
|
527
699
|
|
|
@@ -4,7 +4,7 @@ build-backend = "uv_build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "openscad_parser"
|
|
7
|
-
version = "
|
|
7
|
+
version = "2.2.0"
|
|
8
8
|
description = "A PEG parser to read OpenSCAD language source code, with optional AST tree generation."
|
|
9
9
|
readme = "README.rst"
|
|
10
10
|
authors = [
|
|
@@ -14,7 +14,7 @@ maintainers = [
|
|
|
14
14
|
{ name="Revar Desmera", email="revarbat@gmail.com" },
|
|
15
15
|
]
|
|
16
16
|
license = "MIT"
|
|
17
|
-
requires-python = ">=3.
|
|
17
|
+
requires-python = ">=3.11"
|
|
18
18
|
classifiers = [
|
|
19
19
|
"Development Status :: 4 - Beta",
|
|
20
20
|
"Environment :: Console",
|
|
@@ -39,6 +39,9 @@ dependencies = [
|
|
|
39
39
|
dev = [
|
|
40
40
|
"pytest>=7.0.0",
|
|
41
41
|
]
|
|
42
|
+
yaml = [
|
|
43
|
+
"PyYAML>=6.0",
|
|
44
|
+
]
|
|
42
45
|
|
|
43
46
|
[project.urls]
|
|
44
47
|
"Homepage" = "https://github.com/belfryscad/openscad_parser"
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#######################################################################
|
|
2
|
+
# Arpeggio PEG Grammar for OpenSCAD
|
|
3
|
+
#######################################################################
|
|
4
|
+
|
|
5
|
+
from __future__ import unicode_literals
|
|
6
|
+
|
|
7
|
+
from arpeggio import ParserPython
|
|
8
|
+
from .grammar import openscad_language, openscad_language_with_comments, comment, whitespace_only
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# --- The parser ---
|
|
12
|
+
|
|
13
|
+
def getOpenSCADParser(reduce_tree=False, debug=False, include_comments=False):
|
|
14
|
+
"""Create an OpenSCAD parser instance.
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
reduce_tree: If True, reduce the parse tree (default: False)
|
|
18
|
+
debug: If True, enable debug output (default: False)
|
|
19
|
+
include_comments: If True, include comments in the AST instead of skipping them (default: False)
|
|
20
|
+
|
|
21
|
+
Returns:
|
|
22
|
+
ParserPython instance configured for OpenSCAD parsing
|
|
23
|
+
"""
|
|
24
|
+
if include_comments:
|
|
25
|
+
# When including comments, use whitespace-only rule and include comments in grammar
|
|
26
|
+
return ParserPython(
|
|
27
|
+
openscad_language_with_comments, whitespace_only, reduce_tree=reduce_tree,
|
|
28
|
+
memoization=True, autokwd=True, debug=debug
|
|
29
|
+
)
|
|
30
|
+
else:
|
|
31
|
+
# Default behavior: comments are skipped as whitespace
|
|
32
|
+
return ParserPython(
|
|
33
|
+
openscad_language, comment, reduce_tree=reduce_tree,
|
|
34
|
+
memoization=True, autokwd=True, debug=debug
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
# vim: set ts=4 sw=4 expandtab:
|