dbrownell-parserlib 0.8.3__tar.gz → 0.8.4__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.
- {dbrownell_parserlib-0.8.3 → dbrownell_parserlib-0.8.4}/PKG-INFO +31 -26
- {dbrownell_parserlib-0.8.3 → dbrownell_parserlib-0.8.4}/README.md +30 -25
- {dbrownell_parserlib-0.8.3 → dbrownell_parserlib-0.8.4}/pyproject.toml +1 -1
- {dbrownell_parserlib-0.8.3 → dbrownell_parserlib-0.8.4}/src/dbrownell_ParserLib/__init__.py +0 -0
- {dbrownell_parserlib-0.8.3 → dbrownell_parserlib-0.8.4}/src/dbrownell_ParserLib/antlr/__init__.py +0 -0
- {dbrownell_parserlib-0.8.3 → dbrownell_parserlib-0.8.4}/src/dbrownell_ParserLib/antlr/antlr_parser.py +0 -0
- {dbrownell_parserlib-0.8.3 → dbrownell_parserlib-0.8.4}/src/dbrownell_ParserLib/antlr/antlr_visitor_mixins.py +0 -0
- {dbrownell_parserlib-0.8.3 → dbrownell_parserlib-0.8.4}/src/dbrownell_ParserLib/antlr/build_antlr_grammar/__init__.py +0 -0
- {dbrownell_parserlib-0.8.3 → dbrownell_parserlib-0.8.4}/src/dbrownell_ParserLib/antlr/build_antlr_grammar/antlr-4.13.2-complete.jar +0 -0
- {dbrownell_parserlib-0.8.3 → dbrownell_parserlib-0.8.4}/src/dbrownell_ParserLib/errors.py +0 -0
- {dbrownell_parserlib-0.8.3 → dbrownell_parserlib-0.8.4}/src/dbrownell_ParserLib/expression.py +0 -0
- {dbrownell_parserlib-0.8.3 → dbrownell_parserlib-0.8.4}/src/dbrownell_ParserLib/location.py +0 -0
- {dbrownell_parserlib-0.8.3 → dbrownell_parserlib-0.8.4}/src/dbrownell_ParserLib/py.typed +0 -0
- {dbrownell_parserlib-0.8.3 → dbrownell_parserlib-0.8.4}/src/dbrownell_ParserLib/region.py +0 -0
- {dbrownell_parserlib-0.8.3 → dbrownell_parserlib-0.8.4}/src/dbrownell_ParserLib/terminal_expression.py +0 -0
- {dbrownell_parserlib-0.8.3 → dbrownell_parserlib-0.8.4}/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.
|
|
3
|
+
Version: 0.8.4
|
|
4
4
|
Summary: Functionality useful when creating parsers.
|
|
5
5
|
Author: Dave Brownell
|
|
6
6
|
Author-email: Dave Brownell <github@DavidBrownell.com>
|
|
@@ -61,16 +61,18 @@ Description-Content-Type: text/markdown
|
|
|
61
61
|
|
|
62
62
|
### How to use `dbrownell_ParserLib`
|
|
63
63
|
|
|
64
|
-
The typical workflow for creating a parser with this library involves
|
|
64
|
+
The typical workflow for creating a parser with this library involves the following steps. For detailed examples, see the test files in the repository, particularly the end-to-end tests that demonstrate complete parsing workflows.
|
|
65
|
+
|
|
65
66
|
|
|
66
67
|
#### 1. Define an ANTLR Grammar
|
|
67
68
|
Create a `.g4` grammar file defining your language syntax:
|
|
69
|
+
|
|
68
70
|
```antlr
|
|
69
71
|
grammar Calculator;
|
|
70
72
|
|
|
71
|
-
expr : expr
|
|
72
|
-
| expr
|
|
73
|
-
| INT
|
|
73
|
+
expr : expr ('*'|'/') expr # BinaryOp
|
|
74
|
+
| expr ('+'|'-') expr # BinaryOp
|
|
75
|
+
| INT # Number
|
|
74
76
|
;
|
|
75
77
|
|
|
76
78
|
INT : [0-9]+ ;
|
|
@@ -79,10 +81,13 @@ WS : [ \t\n\r]+ -> skip ;
|
|
|
79
81
|
|
|
80
82
|
#### 2. Build the Grammar
|
|
81
83
|
Use `BuildAntlrGrammar` to generate the lexer and parser:
|
|
84
|
+
|
|
82
85
|
```python
|
|
83
|
-
from dbrownell_ParserLib import BuildAntlrGrammar
|
|
84
86
|
from pathlib import Path
|
|
85
87
|
|
|
88
|
+
from dbrownell_ParserLib import BuildAntlrGrammar
|
|
89
|
+
|
|
90
|
+
|
|
86
91
|
BuildAntlrGrammar(
|
|
87
92
|
dm, # DoneManager instance
|
|
88
93
|
Path("Calculator.g4"),
|
|
@@ -92,18 +97,19 @@ BuildAntlrGrammar(
|
|
|
92
97
|
|
|
93
98
|
#### 3. Create Custom Visitor
|
|
94
99
|
Implement a visitor that converts ANTLR parse trees to Expression objects:
|
|
100
|
+
|
|
95
101
|
```python
|
|
102
|
+
from dataclasses import dataclass
|
|
103
|
+
|
|
96
104
|
from dbrownell_ParserLib import (
|
|
97
105
|
Expression,
|
|
98
106
|
InsignificantWhitespaceAntlrVisitorMixin,
|
|
99
107
|
TerminalExpression,
|
|
100
108
|
)
|
|
101
|
-
from dataclasses import dataclass
|
|
102
109
|
|
|
103
110
|
from CalculatorVisitor import CalculatorVisitor as GeneratedVisitor
|
|
104
111
|
|
|
105
112
|
|
|
106
|
-
|
|
107
113
|
@dataclass(eq=False)
|
|
108
114
|
class BinaryExpression(Expression):
|
|
109
115
|
left: Expression
|
|
@@ -115,30 +121,35 @@ class BinaryExpression(Expression):
|
|
|
115
121
|
yield "operator", self.operator
|
|
116
122
|
yield "right", self.right
|
|
117
123
|
|
|
118
|
-
class CalculatorVisitor(InsignificantWhitespaceAntlrVisitorMixin, GeneratedVisitor):
|
|
119
124
|
|
|
120
|
-
|
|
125
|
+
class CalculatorVisitor(InsignificantWhitespaceAntlrVisitorMixin, GeneratedVisitor):
|
|
126
|
+
def visitExpr(self, ctx):
|
|
121
127
|
children = self.GetChildren(ctx)
|
|
128
|
+
assert len(children) == 2, children
|
|
129
|
+
|
|
122
130
|
self._stack.append(
|
|
123
131
|
BinaryExpression(
|
|
124
132
|
self.CreateRegion(ctx),
|
|
125
133
|
children[0],
|
|
126
|
-
TerminalExpression[str](self.CreateRegion(ctx.children[1]), ctx.children[1].getText()),
|
|
134
|
+
TerminalExpression[str](self.CreateRegion(ctx.children[1]), ctx.children[1].getText()),
|
|
135
|
+
|
|
127
136
|
children[1],
|
|
128
137
|
)
|
|
129
138
|
)
|
|
130
139
|
|
|
131
140
|
def visitNumber(self, ctx):
|
|
132
141
|
self._stack.append(
|
|
133
|
-
TerminalExpression(self.CreateRegion(ctx), int(ctx.
|
|
142
|
+
TerminalExpression(self.CreateRegion(ctx), int(ctx.getText()))
|
|
134
143
|
)
|
|
135
144
|
```
|
|
136
145
|
|
|
137
146
|
#### 4. Create Parser Instance
|
|
138
147
|
Use `CreateAntlrParser` to build a callable parser:
|
|
148
|
+
|
|
139
149
|
```python
|
|
140
150
|
from dbrownell_ParserLib import CreateAntlrParser
|
|
141
151
|
|
|
152
|
+
|
|
142
153
|
parser = CreateAntlrParser(
|
|
143
154
|
CalculatorLexer,
|
|
144
155
|
CalculatorParser,
|
|
@@ -146,15 +157,14 @@ parser = CreateAntlrParser(
|
|
|
146
157
|
lambda p: p.expr(), # Entry point rule
|
|
147
158
|
)
|
|
148
159
|
```
|
|
149
|
-
from pathlib import Path
|
|
150
|
-
|
|
151
|
-
from dbrownell_ParserLib import Error
|
|
152
|
-
|
|
153
|
-
|
|
154
160
|
|
|
155
161
|
#### 5. Parse Files
|
|
156
162
|
Parse single files, multiple files, or entire workspaces:
|
|
163
|
+
|
|
157
164
|
```python
|
|
165
|
+
from dbrownell_ParserLib import Error
|
|
166
|
+
|
|
167
|
+
|
|
158
168
|
# Parse a single file
|
|
159
169
|
results = parser(dm, Path("input.txt"), None)
|
|
160
170
|
|
|
@@ -171,30 +181,25 @@ for filepath, result in results.items():
|
|
|
171
181
|
# Process the AST
|
|
172
182
|
```
|
|
173
183
|
|
|
174
|
-
from contextlib import contextmanager
|
|
175
|
-
|
|
176
184
|
#### 6. Traverse the AST
|
|
177
185
|
Use the visitor pattern to process your AST:
|
|
186
|
+
|
|
178
187
|
```python
|
|
179
|
-
|
|
188
|
+
from contextlib import contextmanager
|
|
180
189
|
|
|
181
190
|
from dbrownell_ParserLib import ExpressionVisitorHelper, VisitResult
|
|
182
191
|
|
|
192
|
+
|
|
183
193
|
class EvaluatorVisitor(ExpressionVisitorHelper):
|
|
184
|
-
def OnBinaryExpression(self, expression):
|
|
185
194
|
@contextmanager
|
|
186
|
-
|
|
195
|
+
def OnBinaryExpression(self, expression):
|
|
187
196
|
# Process binary expressions
|
|
188
197
|
yield VisitResult.Continue
|
|
189
198
|
|
|
190
|
-
# Process terminal values
|
|
191
|
-
yield VisitResult.Continue
|
|
192
199
|
|
|
193
200
|
ast.Accept(EvaluatorVisitor())
|
|
194
201
|
```
|
|
195
202
|
|
|
196
|
-
For detailed examples, see the test files in the repository, particularly the end-to-end tests that demonstrate complete parsing workflows.
|
|
197
|
-
|
|
198
203
|
<!-- 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. -->
|
|
199
204
|
|
|
200
205
|
## Installation
|
|
@@ -39,16 +39,18 @@
|
|
|
39
39
|
|
|
40
40
|
### How to use `dbrownell_ParserLib`
|
|
41
41
|
|
|
42
|
-
The typical workflow for creating a parser with this library involves
|
|
42
|
+
The typical workflow for creating a parser with this library involves the following steps. For detailed examples, see the test files in the repository, particularly the end-to-end tests that demonstrate complete parsing workflows.
|
|
43
|
+
|
|
43
44
|
|
|
44
45
|
#### 1. Define an ANTLR Grammar
|
|
45
46
|
Create a `.g4` grammar file defining your language syntax:
|
|
47
|
+
|
|
46
48
|
```antlr
|
|
47
49
|
grammar Calculator;
|
|
48
50
|
|
|
49
|
-
expr : expr
|
|
50
|
-
| expr
|
|
51
|
-
| INT
|
|
51
|
+
expr : expr ('*'|'/') expr # BinaryOp
|
|
52
|
+
| expr ('+'|'-') expr # BinaryOp
|
|
53
|
+
| INT # Number
|
|
52
54
|
;
|
|
53
55
|
|
|
54
56
|
INT : [0-9]+ ;
|
|
@@ -57,10 +59,13 @@ WS : [ \t\n\r]+ -> skip ;
|
|
|
57
59
|
|
|
58
60
|
#### 2. Build the Grammar
|
|
59
61
|
Use `BuildAntlrGrammar` to generate the lexer and parser:
|
|
62
|
+
|
|
60
63
|
```python
|
|
61
|
-
from dbrownell_ParserLib import BuildAntlrGrammar
|
|
62
64
|
from pathlib import Path
|
|
63
65
|
|
|
66
|
+
from dbrownell_ParserLib import BuildAntlrGrammar
|
|
67
|
+
|
|
68
|
+
|
|
64
69
|
BuildAntlrGrammar(
|
|
65
70
|
dm, # DoneManager instance
|
|
66
71
|
Path("Calculator.g4"),
|
|
@@ -70,18 +75,19 @@ BuildAntlrGrammar(
|
|
|
70
75
|
|
|
71
76
|
#### 3. Create Custom Visitor
|
|
72
77
|
Implement a visitor that converts ANTLR parse trees to Expression objects:
|
|
78
|
+
|
|
73
79
|
```python
|
|
80
|
+
from dataclasses import dataclass
|
|
81
|
+
|
|
74
82
|
from dbrownell_ParserLib import (
|
|
75
83
|
Expression,
|
|
76
84
|
InsignificantWhitespaceAntlrVisitorMixin,
|
|
77
85
|
TerminalExpression,
|
|
78
86
|
)
|
|
79
|
-
from dataclasses import dataclass
|
|
80
87
|
|
|
81
88
|
from CalculatorVisitor import CalculatorVisitor as GeneratedVisitor
|
|
82
89
|
|
|
83
90
|
|
|
84
|
-
|
|
85
91
|
@dataclass(eq=False)
|
|
86
92
|
class BinaryExpression(Expression):
|
|
87
93
|
left: Expression
|
|
@@ -93,30 +99,35 @@ class BinaryExpression(Expression):
|
|
|
93
99
|
yield "operator", self.operator
|
|
94
100
|
yield "right", self.right
|
|
95
101
|
|
|
96
|
-
class CalculatorVisitor(InsignificantWhitespaceAntlrVisitorMixin, GeneratedVisitor):
|
|
97
102
|
|
|
98
|
-
|
|
103
|
+
class CalculatorVisitor(InsignificantWhitespaceAntlrVisitorMixin, GeneratedVisitor):
|
|
104
|
+
def visitExpr(self, ctx):
|
|
99
105
|
children = self.GetChildren(ctx)
|
|
106
|
+
assert len(children) == 2, children
|
|
107
|
+
|
|
100
108
|
self._stack.append(
|
|
101
109
|
BinaryExpression(
|
|
102
110
|
self.CreateRegion(ctx),
|
|
103
111
|
children[0],
|
|
104
|
-
TerminalExpression[str](self.CreateRegion(ctx.children[1]), ctx.children[1].getText()),
|
|
112
|
+
TerminalExpression[str](self.CreateRegion(ctx.children[1]), ctx.children[1].getText()),
|
|
113
|
+
|
|
105
114
|
children[1],
|
|
106
115
|
)
|
|
107
116
|
)
|
|
108
117
|
|
|
109
118
|
def visitNumber(self, ctx):
|
|
110
119
|
self._stack.append(
|
|
111
|
-
TerminalExpression(self.CreateRegion(ctx), int(ctx.
|
|
120
|
+
TerminalExpression(self.CreateRegion(ctx), int(ctx.getText()))
|
|
112
121
|
)
|
|
113
122
|
```
|
|
114
123
|
|
|
115
124
|
#### 4. Create Parser Instance
|
|
116
125
|
Use `CreateAntlrParser` to build a callable parser:
|
|
126
|
+
|
|
117
127
|
```python
|
|
118
128
|
from dbrownell_ParserLib import CreateAntlrParser
|
|
119
129
|
|
|
130
|
+
|
|
120
131
|
parser = CreateAntlrParser(
|
|
121
132
|
CalculatorLexer,
|
|
122
133
|
CalculatorParser,
|
|
@@ -124,15 +135,14 @@ parser = CreateAntlrParser(
|
|
|
124
135
|
lambda p: p.expr(), # Entry point rule
|
|
125
136
|
)
|
|
126
137
|
```
|
|
127
|
-
from pathlib import Path
|
|
128
|
-
|
|
129
|
-
from dbrownell_ParserLib import Error
|
|
130
|
-
|
|
131
|
-
|
|
132
138
|
|
|
133
139
|
#### 5. Parse Files
|
|
134
140
|
Parse single files, multiple files, or entire workspaces:
|
|
141
|
+
|
|
135
142
|
```python
|
|
143
|
+
from dbrownell_ParserLib import Error
|
|
144
|
+
|
|
145
|
+
|
|
136
146
|
# Parse a single file
|
|
137
147
|
results = parser(dm, Path("input.txt"), None)
|
|
138
148
|
|
|
@@ -149,30 +159,25 @@ for filepath, result in results.items():
|
|
|
149
159
|
# Process the AST
|
|
150
160
|
```
|
|
151
161
|
|
|
152
|
-
from contextlib import contextmanager
|
|
153
|
-
|
|
154
162
|
#### 6. Traverse the AST
|
|
155
163
|
Use the visitor pattern to process your AST:
|
|
164
|
+
|
|
156
165
|
```python
|
|
157
|
-
|
|
166
|
+
from contextlib import contextmanager
|
|
158
167
|
|
|
159
168
|
from dbrownell_ParserLib import ExpressionVisitorHelper, VisitResult
|
|
160
169
|
|
|
170
|
+
|
|
161
171
|
class EvaluatorVisitor(ExpressionVisitorHelper):
|
|
162
|
-
def OnBinaryExpression(self, expression):
|
|
163
172
|
@contextmanager
|
|
164
|
-
|
|
173
|
+
def OnBinaryExpression(self, expression):
|
|
165
174
|
# Process binary expressions
|
|
166
175
|
yield VisitResult.Continue
|
|
167
176
|
|
|
168
|
-
# Process terminal values
|
|
169
|
-
yield VisitResult.Continue
|
|
170
177
|
|
|
171
178
|
ast.Accept(EvaluatorVisitor())
|
|
172
179
|
```
|
|
173
180
|
|
|
174
|
-
For detailed examples, see the test files in the repository, particularly the end-to-end tests that demonstrate complete parsing workflows.
|
|
175
|
-
|
|
176
181
|
<!-- 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. -->
|
|
177
182
|
|
|
178
183
|
## Installation
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "dbrownell-parserlib"
|
|
3
|
-
version = "0.8.
|
|
3
|
+
version = "0.8.4"
|
|
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:
|
|
File without changes
|
{dbrownell_parserlib-0.8.3 → dbrownell_parserlib-0.8.4}/src/dbrownell_ParserLib/antlr/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dbrownell_parserlib-0.8.3 → dbrownell_parserlib-0.8.4}/src/dbrownell_ParserLib/expression.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|