dbrownell-parserlib 0.8.2__tar.gz → 0.8.3__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.
Files changed (16) hide show
  1. {dbrownell_parserlib-0.8.2 → dbrownell_parserlib-0.8.3}/PKG-INFO +146 -3
  2. {dbrownell_parserlib-0.8.2 → dbrownell_parserlib-0.8.3}/README.md +145 -2
  3. {dbrownell_parserlib-0.8.2 → dbrownell_parserlib-0.8.3}/pyproject.toml +1 -1
  4. {dbrownell_parserlib-0.8.2 → dbrownell_parserlib-0.8.3}/src/dbrownell_ParserLib/__init__.py +0 -0
  5. {dbrownell_parserlib-0.8.2 → dbrownell_parserlib-0.8.3}/src/dbrownell_ParserLib/antlr/__init__.py +0 -0
  6. {dbrownell_parserlib-0.8.2 → dbrownell_parserlib-0.8.3}/src/dbrownell_ParserLib/antlr/antlr_parser.py +0 -0
  7. {dbrownell_parserlib-0.8.2 → dbrownell_parserlib-0.8.3}/src/dbrownell_ParserLib/antlr/antlr_visitor_mixins.py +0 -0
  8. {dbrownell_parserlib-0.8.2 → dbrownell_parserlib-0.8.3}/src/dbrownell_ParserLib/antlr/build_antlr_grammar/__init__.py +0 -0
  9. {dbrownell_parserlib-0.8.2 → dbrownell_parserlib-0.8.3}/src/dbrownell_ParserLib/antlr/build_antlr_grammar/antlr-4.13.2-complete.jar +0 -0
  10. {dbrownell_parserlib-0.8.2 → dbrownell_parserlib-0.8.3}/src/dbrownell_ParserLib/errors.py +0 -0
  11. {dbrownell_parserlib-0.8.2 → dbrownell_parserlib-0.8.3}/src/dbrownell_ParserLib/expression.py +0 -0
  12. {dbrownell_parserlib-0.8.2 → dbrownell_parserlib-0.8.3}/src/dbrownell_ParserLib/location.py +0 -0
  13. {dbrownell_parserlib-0.8.2 → dbrownell_parserlib-0.8.3}/src/dbrownell_ParserLib/py.typed +0 -0
  14. {dbrownell_parserlib-0.8.2 → dbrownell_parserlib-0.8.3}/src/dbrownell_ParserLib/region.py +0 -0
  15. {dbrownell_parserlib-0.8.2 → dbrownell_parserlib-0.8.3}/src/dbrownell_ParserLib/terminal_expression.py +0 -0
  16. {dbrownell_parserlib-0.8.2 → dbrownell_parserlib-0.8.3}/src/dbrownell_ParserLib/visitors.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: dbrownell-parserlib
3
- Version: 0.8.2
3
+ Version: 0.8.3
4
4
  Summary: Functionality useful when creating parsers.
5
5
  Author: Dave Brownell
6
6
  Author-email: Dave Brownell <github@DavidBrownell.com>
@@ -47,10 +47,153 @@ Description-Content-Type: text/markdown
47
47
  - [License](#license)
48
48
 
49
49
  ## Overview
50
- TODO: Complete this section
50
+ `dbrownell_ParserLib` is a Python library that provides utility functionality for creating parsers, with a primary focus on [ANTLR](https://antlr.org) (Another Tool for Language Recognition) integration. The library simplifies the process of building parsers that produce strongly-typed abstract syntax trees (ASTs) with comprehensive source location tracking.
51
+
52
+ ### Key Features
53
+ - **ANTLR Integration**: Streamlined wrapper around ANTLR for Python, handling grammar compilation and parser generation
54
+ - **AST Representation**: Expression-based AST nodes with automatic parent-child relationship management
55
+ - **Source Location Tracking**: Every AST node tracks its source file location (filename, line, column ranges) for detailed error reporting
56
+ - **Visitor Pattern**: Flexible visitor pattern implementation with fine-grained traversal control
57
+ - **Error Handling**: Rich error objects that associate messages with source locations and extract Python exception tracebacks
58
+ - **Multi-threaded Parsing**: Built-in support for parsing multiple files concurrently
59
+ - **Workspace Support**: Parse entire directory trees with customizable file filtering
60
+ - **Whitespace Handling**: Mixins for both insignificant and significant whitespace grammars (e.g., Python-like indentation)
51
61
 
52
62
  ### How to use `dbrownell_ParserLib`
53
- TODO: Complete this section
63
+
64
+ The typical workflow for creating a parser with this library involves:
65
+
66
+ #### 1. Define an ANTLR Grammar
67
+ Create a `.g4` grammar file defining your language syntax:
68
+ ```antlr
69
+ grammar Calculator;
70
+
71
+ expr : expr op=('*'|'/') expr # BinaryOp
72
+ | expr op=('+'|'-') expr # BinaryOp
73
+ | INT # Number
74
+ ;
75
+
76
+ INT : [0-9]+ ;
77
+ WS : [ \t\n\r]+ -> skip ;
78
+ ```
79
+
80
+ #### 2. Build the Grammar
81
+ Use `BuildAntlrGrammar` to generate the lexer and parser:
82
+ ```python
83
+ from dbrownell_ParserLib import BuildAntlrGrammar
84
+ from pathlib import Path
85
+
86
+ BuildAntlrGrammar(
87
+ dm, # DoneManager instance
88
+ Path("Calculator.g4"),
89
+ Path("output_dir"),
90
+ )
91
+ ```
92
+
93
+ #### 3. Create Custom Visitor
94
+ Implement a visitor that converts ANTLR parse trees to Expression objects:
95
+ ```python
96
+ from dbrownell_ParserLib import (
97
+ Expression,
98
+ InsignificantWhitespaceAntlrVisitorMixin,
99
+ TerminalExpression,
100
+ )
101
+ from dataclasses import dataclass
102
+
103
+ from CalculatorVisitor import CalculatorVisitor as GeneratedVisitor
104
+
105
+
106
+
107
+ @dataclass(eq=False)
108
+ class BinaryExpression(Expression):
109
+ left: Expression
110
+ operator: TerminalExpression[str]
111
+ right: Expression
112
+
113
+ def _GenerateAcceptDetails(self):
114
+ yield "left", self.left
115
+ yield "operator", self.operator
116
+ yield "right", self.right
117
+
118
+ class CalculatorVisitor(InsignificantWhitespaceAntlrVisitorMixin, GeneratedVisitor):
119
+
120
+ def visitBinaryOp(self, ctx):
121
+ children = self.GetChildren(ctx)
122
+ self._stack.append(
123
+ BinaryExpression(
124
+ self.CreateRegion(ctx),
125
+ children[0],
126
+ TerminalExpression[str](self.CreateRegion(ctx.children[1]), ctx.children[1].getText()),
127
+ children[1],
128
+ )
129
+ )
130
+
131
+ def visitNumber(self, ctx):
132
+ self._stack.append(
133
+ TerminalExpression(self.CreateRegion(ctx), int(ctx.INT().getText()))
134
+ )
135
+ ```
136
+
137
+ #### 4. Create Parser Instance
138
+ Use `CreateAntlrParser` to build a callable parser:
139
+ ```python
140
+ from dbrownell_ParserLib import CreateAntlrParser
141
+
142
+ parser = CreateAntlrParser(
143
+ CalculatorLexer,
144
+ CalculatorParser,
145
+ CalculatorVisitor,
146
+ lambda p: p.expr(), # Entry point rule
147
+ )
148
+ ```
149
+ from pathlib import Path
150
+
151
+ from dbrownell_ParserLib import Error
152
+
153
+
154
+
155
+ #### 5. Parse Files
156
+ Parse single files, multiple files, or entire workspaces:
157
+ ```python
158
+ # Parse a single file
159
+ results = parser(dm, Path("input.txt"), None)
160
+
161
+ # Parse multiple files
162
+ results = parser(dm, [Path("file1.txt"), Path("file2.txt")], None)
163
+
164
+ # Check results
165
+ for filepath, result in results.items():
166
+ if isinstance(result, Error):
167
+ print(f"Parse error in {filepath}: {result}")
168
+ else:
169
+ # result is the visitor containing the parsed AST
170
+ ast = result._stack[0]
171
+ # Process the AST
172
+ ```
173
+
174
+ from contextlib import contextmanager
175
+
176
+ #### 6. Traverse the AST
177
+ Use the visitor pattern to process your AST:
178
+ ```python
179
+ @contextmanager
180
+
181
+ from dbrownell_ParserLib import ExpressionVisitorHelper, VisitResult
182
+
183
+ class EvaluatorVisitor(ExpressionVisitorHelper):
184
+ def OnBinaryExpression(self, expression):
185
+ @contextmanager
186
+
187
+ # Process binary expressions
188
+ yield VisitResult.Continue
189
+
190
+ # Process terminal values
191
+ yield VisitResult.Continue
192
+
193
+ ast.Accept(EvaluatorVisitor())
194
+ ```
195
+
196
+ For detailed examples, see the test files in the repository, particularly the end-to-end tests that demonstrate complete parsing workflows.
54
197
 
55
198
  <!-- Content below this delimiter will be copied to the generated README.md file. DO NOT REMOVE THIS COMMENT, as it will cause regeneration to fail. -->
56
199
 
@@ -25,10 +25,153 @@
25
25
  - [License](#license)
26
26
 
27
27
  ## Overview
28
- TODO: Complete this section
28
+ `dbrownell_ParserLib` is a Python library that provides utility functionality for creating parsers, with a primary focus on [ANTLR](https://antlr.org) (Another Tool for Language Recognition) integration. The library simplifies the process of building parsers that produce strongly-typed abstract syntax trees (ASTs) with comprehensive source location tracking.
29
+
30
+ ### Key Features
31
+ - **ANTLR Integration**: Streamlined wrapper around ANTLR for Python, handling grammar compilation and parser generation
32
+ - **AST Representation**: Expression-based AST nodes with automatic parent-child relationship management
33
+ - **Source Location Tracking**: Every AST node tracks its source file location (filename, line, column ranges) for detailed error reporting
34
+ - **Visitor Pattern**: Flexible visitor pattern implementation with fine-grained traversal control
35
+ - **Error Handling**: Rich error objects that associate messages with source locations and extract Python exception tracebacks
36
+ - **Multi-threaded Parsing**: Built-in support for parsing multiple files concurrently
37
+ - **Workspace Support**: Parse entire directory trees with customizable file filtering
38
+ - **Whitespace Handling**: Mixins for both insignificant and significant whitespace grammars (e.g., Python-like indentation)
29
39
 
30
40
  ### How to use `dbrownell_ParserLib`
31
- TODO: Complete this section
41
+
42
+ The typical workflow for creating a parser with this library involves:
43
+
44
+ #### 1. Define an ANTLR Grammar
45
+ Create a `.g4` grammar file defining your language syntax:
46
+ ```antlr
47
+ grammar Calculator;
48
+
49
+ expr : expr op=('*'|'/') expr # BinaryOp
50
+ | expr op=('+'|'-') expr # BinaryOp
51
+ | INT # Number
52
+ ;
53
+
54
+ INT : [0-9]+ ;
55
+ WS : [ \t\n\r]+ -> skip ;
56
+ ```
57
+
58
+ #### 2. Build the Grammar
59
+ Use `BuildAntlrGrammar` to generate the lexer and parser:
60
+ ```python
61
+ from dbrownell_ParserLib import BuildAntlrGrammar
62
+ from pathlib import Path
63
+
64
+ BuildAntlrGrammar(
65
+ dm, # DoneManager instance
66
+ Path("Calculator.g4"),
67
+ Path("output_dir"),
68
+ )
69
+ ```
70
+
71
+ #### 3. Create Custom Visitor
72
+ Implement a visitor that converts ANTLR parse trees to Expression objects:
73
+ ```python
74
+ from dbrownell_ParserLib import (
75
+ Expression,
76
+ InsignificantWhitespaceAntlrVisitorMixin,
77
+ TerminalExpression,
78
+ )
79
+ from dataclasses import dataclass
80
+
81
+ from CalculatorVisitor import CalculatorVisitor as GeneratedVisitor
82
+
83
+
84
+
85
+ @dataclass(eq=False)
86
+ class BinaryExpression(Expression):
87
+ left: Expression
88
+ operator: TerminalExpression[str]
89
+ right: Expression
90
+
91
+ def _GenerateAcceptDetails(self):
92
+ yield "left", self.left
93
+ yield "operator", self.operator
94
+ yield "right", self.right
95
+
96
+ class CalculatorVisitor(InsignificantWhitespaceAntlrVisitorMixin, GeneratedVisitor):
97
+
98
+ def visitBinaryOp(self, ctx):
99
+ children = self.GetChildren(ctx)
100
+ self._stack.append(
101
+ BinaryExpression(
102
+ self.CreateRegion(ctx),
103
+ children[0],
104
+ TerminalExpression[str](self.CreateRegion(ctx.children[1]), ctx.children[1].getText()),
105
+ children[1],
106
+ )
107
+ )
108
+
109
+ def visitNumber(self, ctx):
110
+ self._stack.append(
111
+ TerminalExpression(self.CreateRegion(ctx), int(ctx.INT().getText()))
112
+ )
113
+ ```
114
+
115
+ #### 4. Create Parser Instance
116
+ Use `CreateAntlrParser` to build a callable parser:
117
+ ```python
118
+ from dbrownell_ParserLib import CreateAntlrParser
119
+
120
+ parser = CreateAntlrParser(
121
+ CalculatorLexer,
122
+ CalculatorParser,
123
+ CalculatorVisitor,
124
+ lambda p: p.expr(), # Entry point rule
125
+ )
126
+ ```
127
+ from pathlib import Path
128
+
129
+ from dbrownell_ParserLib import Error
130
+
131
+
132
+
133
+ #### 5. Parse Files
134
+ Parse single files, multiple files, or entire workspaces:
135
+ ```python
136
+ # Parse a single file
137
+ results = parser(dm, Path("input.txt"), None)
138
+
139
+ # Parse multiple files
140
+ results = parser(dm, [Path("file1.txt"), Path("file2.txt")], None)
141
+
142
+ # Check results
143
+ for filepath, result in results.items():
144
+ if isinstance(result, Error):
145
+ print(f"Parse error in {filepath}: {result}")
146
+ else:
147
+ # result is the visitor containing the parsed AST
148
+ ast = result._stack[0]
149
+ # Process the AST
150
+ ```
151
+
152
+ from contextlib import contextmanager
153
+
154
+ #### 6. Traverse the AST
155
+ Use the visitor pattern to process your AST:
156
+ ```python
157
+ @contextmanager
158
+
159
+ from dbrownell_ParserLib import ExpressionVisitorHelper, VisitResult
160
+
161
+ class EvaluatorVisitor(ExpressionVisitorHelper):
162
+ def OnBinaryExpression(self, expression):
163
+ @contextmanager
164
+
165
+ # Process binary expressions
166
+ yield VisitResult.Continue
167
+
168
+ # Process terminal values
169
+ yield VisitResult.Continue
170
+
171
+ ast.Accept(EvaluatorVisitor())
172
+ ```
173
+
174
+ For detailed examples, see the test files in the repository, particularly the end-to-end tests that demonstrate complete parsing workflows.
32
175
 
33
176
  <!-- Content below this delimiter will be copied to the generated README.md file. DO NOT REMOVE THIS COMMENT, as it will cause regeneration to fail. -->
34
177
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "dbrownell-parserlib"
3
- version = "0.8.2"
3
+ version = "0.8.3"
4
4
  # ^^^^^
5
5
  # Wheel names will be generated according to this value. Do not manually modify this value; instead
6
6
  # update it according to committed changes by running this command from the root of the repository: