omextra 0.0.0.dev493__py3-none-any.whl → 0.0.0.dev495__py3-none-any.whl
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.
- omextra/text/abnf/__init__.py +17 -4
- omextra/text/abnf/_dataclasses.py +438 -0
- omextra/text/abnf/base.py +49 -82
- omextra/text/abnf/core.py +5 -5
- omextra/text/abnf/docs/__init__.py +0 -0
- omextra/text/abnf/docs/rfc5234.txt +893 -0
- omextra/text/abnf/docs/rfc7405.txt +221 -0
- omextra/text/abnf/internal.py +32 -0
- omextra/text/abnf/meta.py +37 -36
- omextra/text/abnf/ops.py +276 -0
- omextra/text/abnf/parsing.py +212 -0
- omextra/text/abnf/utils.py +4 -9
- omextra/text/abnf/visitors.py +8 -8
- {omextra-0.0.0.dev493.dist-info → omextra-0.0.0.dev495.dist-info}/METADATA +2 -2
- {omextra-0.0.0.dev493.dist-info → omextra-0.0.0.dev495.dist-info}/RECORD +19 -13
- omextra/text/abnf/parsers.py +0 -343
- {omextra-0.0.0.dev493.dist-info → omextra-0.0.0.dev495.dist-info}/WHEEL +0 -0
- {omextra-0.0.0.dev493.dist-info → omextra-0.0.0.dev495.dist-info}/entry_points.txt +0 -0
- {omextra-0.0.0.dev493.dist-info → omextra-0.0.0.dev495.dist-info}/licenses/LICENSE +0 -0
- {omextra-0.0.0.dev493.dist-info → omextra-0.0.0.dev495.dist-info}/top_level.txt +0 -0
omextra/text/abnf/base.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import abc
|
|
2
1
|
import io
|
|
3
2
|
import itertools
|
|
4
3
|
import typing as ta
|
|
@@ -7,10 +6,12 @@ from omlish import check
|
|
|
7
6
|
from omlish import lang
|
|
8
7
|
|
|
9
8
|
from .errors import AbnfError
|
|
9
|
+
from .errors import AbnfIncompleteParseError
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
with lang.auto_proxy_import(globals()):
|
|
13
|
-
from . import
|
|
13
|
+
from . import ops
|
|
14
|
+
from . import parsing
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
##
|
|
@@ -18,7 +19,7 @@ with lang.auto_proxy_import(globals()):
|
|
|
18
19
|
|
|
19
20
|
@ta.final
|
|
20
21
|
class Match(ta.NamedTuple):
|
|
21
|
-
|
|
22
|
+
op: 'Op'
|
|
22
23
|
start: int
|
|
23
24
|
end: int
|
|
24
25
|
children: tuple['Match', ...]
|
|
@@ -32,7 +33,7 @@ class Match(ta.NamedTuple):
|
|
|
32
33
|
def __repr__(self) -> str:
|
|
33
34
|
return (
|
|
34
35
|
f'{self.__class__.__name__}('
|
|
35
|
-
f'{self.
|
|
36
|
+
f'{self.op._match_repr()}, ' # noqa
|
|
36
37
|
f'{self.start}, {self.end}'
|
|
37
38
|
f'{f", {self.children!r}" if self.children else ""})'
|
|
38
39
|
)
|
|
@@ -42,20 +43,20 @@ class Match(ta.NamedTuple):
|
|
|
42
43
|
write: ta.Callable[[str], ta.Any],
|
|
43
44
|
*,
|
|
44
45
|
indent: int | None = None,
|
|
45
|
-
|
|
46
|
+
_depth: int = 0,
|
|
46
47
|
) -> None:
|
|
47
|
-
ix: str | None = (' ' * (indent *
|
|
48
|
+
ix: str | None = (' ' * (indent * _depth)) if indent is not None else None
|
|
48
49
|
if ix:
|
|
49
50
|
write(ix)
|
|
50
|
-
|
|
51
|
-
if isinstance(
|
|
52
|
-
write(f'literal<{self.start}-{self.end}>({
|
|
53
|
-
elif isinstance(
|
|
54
|
-
write(f'literal<{self.start}-{self.end}>({
|
|
51
|
+
o = self.op
|
|
52
|
+
if isinstance(o, (ops.StringLiteral, ops.CaseInsensitiveStringLiteral)):
|
|
53
|
+
write(f'literal<{self.start}-{self.end}>({o.value!r})')
|
|
54
|
+
elif isinstance(o, ops.RangeLiteral):
|
|
55
|
+
write(f'literal<{self.start}-{self.end}>({o.value.lo!r}-{o.value.hi!r})')
|
|
55
56
|
else:
|
|
56
|
-
write(f'{
|
|
57
|
-
if isinstance(
|
|
58
|
-
write(f':{
|
|
57
|
+
write(f'{o.__class__.__name__.lower()}<{self.start}-{self.end}>')
|
|
58
|
+
if isinstance(o, ops.RuleRef):
|
|
59
|
+
write(f':{o.name}')
|
|
59
60
|
if self.children:
|
|
60
61
|
write('(')
|
|
61
62
|
if ix is not None:
|
|
@@ -63,7 +64,7 @@ class Match(ta.NamedTuple):
|
|
|
63
64
|
for i, c in enumerate(self.children):
|
|
64
65
|
if i and ix is None:
|
|
65
66
|
write(', ')
|
|
66
|
-
c.render_to(write, indent=indent,
|
|
67
|
+
c.render_to(write, indent=indent, _depth=_depth + 1)
|
|
67
68
|
if ix is not None:
|
|
68
69
|
write(',\n')
|
|
69
70
|
if ix:
|
|
@@ -104,13 +105,13 @@ def longest_match(ms: ta.Iterable[Match]) -> Match | None:
|
|
|
104
105
|
##
|
|
105
106
|
|
|
106
107
|
|
|
107
|
-
class
|
|
108
|
+
class Op(lang.Abstract, lang.PackageSealed):
|
|
108
109
|
def _match_repr(self) -> str:
|
|
109
|
-
return f'{self.__class__.__name__}@{id(self)}'
|
|
110
|
+
return f'{self.__class__.__name__}@{id(self):x}'
|
|
110
111
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
112
|
+
|
|
113
|
+
class LeafOp(Op, lang.Abstract):
|
|
114
|
+
pass
|
|
114
115
|
|
|
115
116
|
|
|
116
117
|
##
|
|
@@ -120,7 +121,7 @@ class Rule(lang.Final):
|
|
|
120
121
|
def __init__(
|
|
121
122
|
self,
|
|
122
123
|
name: str,
|
|
123
|
-
|
|
124
|
+
op: Op,
|
|
124
125
|
*,
|
|
125
126
|
insignificant: bool = False,
|
|
126
127
|
) -> None:
|
|
@@ -128,7 +129,7 @@ class Rule(lang.Final):
|
|
|
128
129
|
|
|
129
130
|
self._name = check.non_empty_str(name)
|
|
130
131
|
self._name_f = name.casefold()
|
|
131
|
-
self.
|
|
132
|
+
self._op = check.isinstance(op, Op)
|
|
132
133
|
self._insignificant = insignificant
|
|
133
134
|
|
|
134
135
|
def __repr__(self) -> str:
|
|
@@ -143,8 +144,8 @@ class Rule(lang.Final):
|
|
|
143
144
|
return self._name_f
|
|
144
145
|
|
|
145
146
|
@property
|
|
146
|
-
def
|
|
147
|
-
return self.
|
|
147
|
+
def op(self) -> Op:
|
|
148
|
+
return self._op
|
|
148
149
|
|
|
149
150
|
@property
|
|
150
151
|
def insignificant(self) -> bool:
|
|
@@ -162,19 +163,20 @@ class Grammar(lang.Final):
|
|
|
162
163
|
rules_set: set[Rule] = set()
|
|
163
164
|
rules_by_name: dict[str, Rule] = {}
|
|
164
165
|
rules_by_name_f: dict[str, Rule] = {}
|
|
165
|
-
|
|
166
|
+
rules_by_op: dict[Op, Rule] = {}
|
|
166
167
|
for gr in rules:
|
|
167
168
|
check.not_in(gr, rules_set)
|
|
168
169
|
check.not_in(gr._name, rules_by_name) # noqa
|
|
169
170
|
check.not_in(gr._name_f, rules_by_name_f) # noqa
|
|
170
|
-
check.not_in(gr.
|
|
171
|
+
check.not_in(gr._op, rules_by_op) # noqa
|
|
172
|
+
rules_set.add(gr)
|
|
171
173
|
rules_by_name[gr._name] = gr # noqa
|
|
172
174
|
rules_by_name_f[gr._name_f] = gr # noqa
|
|
173
|
-
|
|
175
|
+
rules_by_op[gr._op] = gr # noqa
|
|
174
176
|
self._rules = rules_set
|
|
175
177
|
self._rules_by_name: ta.Mapping[str, Rule] = rules_by_name
|
|
176
178
|
self._rules_by_name_f: ta.Mapping[str, Rule] = rules_by_name_f
|
|
177
|
-
self.
|
|
179
|
+
self._rules_by_op: ta.Mapping[Op, Rule] = rules_by_op
|
|
178
180
|
|
|
179
181
|
if isinstance(root, str):
|
|
180
182
|
root = rules_by_name_f[root.casefold()]
|
|
@@ -193,7 +195,7 @@ class Grammar(lang.Final):
|
|
|
193
195
|
root: Rule | str | None = None,
|
|
194
196
|
*,
|
|
195
197
|
start: int = 0,
|
|
196
|
-
debug:
|
|
198
|
+
debug: int = 0,
|
|
197
199
|
) -> ta.Iterator[Match]:
|
|
198
200
|
if root is None:
|
|
199
201
|
if (root := self._root) is None:
|
|
@@ -204,14 +206,13 @@ class Grammar(lang.Final):
|
|
|
204
206
|
else:
|
|
205
207
|
root = check.in_(check.isinstance(root, Rule), self._rules)
|
|
206
208
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
return ctx.iter_parse(root._parser, start) # noqa
|
|
209
|
+
return parsing._iter_parse( # noqa
|
|
210
|
+
self,
|
|
211
|
+
source,
|
|
212
|
+
root._op, # noqa
|
|
213
|
+
start,
|
|
214
|
+
debug=debug,
|
|
215
|
+
)
|
|
215
216
|
|
|
216
217
|
def parse(
|
|
217
218
|
self,
|
|
@@ -219,62 +220,28 @@ class Grammar(lang.Final):
|
|
|
219
220
|
root: str | None = None,
|
|
220
221
|
*,
|
|
221
222
|
start: int = 0,
|
|
222
|
-
|
|
223
|
+
complete: bool = False,
|
|
224
|
+
debug: int = 0,
|
|
223
225
|
) -> Match | None:
|
|
224
|
-
|
|
226
|
+
if (match := longest_match(self.iter_parse(
|
|
225
227
|
source,
|
|
226
228
|
root,
|
|
227
229
|
start=start,
|
|
228
230
|
debug=debug,
|
|
229
|
-
))
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
##
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
class _Context:
|
|
236
|
-
def __init__(
|
|
237
|
-
self,
|
|
238
|
-
grammar: Grammar,
|
|
239
|
-
source: str,
|
|
240
|
-
) -> None:
|
|
241
|
-
super().__init__()
|
|
242
|
-
|
|
243
|
-
self._grammar = grammar
|
|
244
|
-
self._source = source
|
|
245
|
-
|
|
246
|
-
@property
|
|
247
|
-
def grammar(self) -> Grammar:
|
|
248
|
-
return self._grammar
|
|
249
|
-
|
|
250
|
-
@property
|
|
251
|
-
def source(self) -> str:
|
|
252
|
-
return self._source
|
|
253
|
-
|
|
254
|
-
def iter_parse(self, parser: Parser, start: int) -> ta.Iterator[Match]:
|
|
255
|
-
return parser._iter_parse(self, start) # noqa
|
|
256
|
-
|
|
231
|
+
))) is None:
|
|
232
|
+
return None
|
|
257
233
|
|
|
258
|
-
|
|
259
|
-
|
|
234
|
+
if complete and (match.start, match.end) != (start, len(source)):
|
|
235
|
+
raise AbnfIncompleteParseError
|
|
260
236
|
|
|
261
|
-
|
|
262
|
-
print(f'{" " * self._level}enter: {parser=} {start=}')
|
|
263
|
-
try:
|
|
264
|
-
self._level += 1
|
|
265
|
-
for m in super().iter_parse(parser, start): # noqa
|
|
266
|
-
# print(f'{" " * (self._level - 1)}match: {parser=} {start=}')
|
|
267
|
-
yield m
|
|
268
|
-
finally:
|
|
269
|
-
self._level -= 1
|
|
270
|
-
print(f'{" " * self._level}exit: {parser=} {start=}')
|
|
237
|
+
return match
|
|
271
238
|
|
|
272
239
|
|
|
273
240
|
##
|
|
274
241
|
|
|
275
242
|
|
|
276
243
|
def iter_parse(
|
|
277
|
-
obj: Grammar | Rule |
|
|
244
|
+
obj: Grammar | Rule | Op,
|
|
278
245
|
src: str,
|
|
279
246
|
*,
|
|
280
247
|
root: str | None = None,
|
|
@@ -285,7 +252,7 @@ def iter_parse(
|
|
|
285
252
|
elif isinstance(obj, Rule):
|
|
286
253
|
check.none(root)
|
|
287
254
|
gram = Grammar(obj, root=obj)
|
|
288
|
-
elif isinstance(obj,
|
|
255
|
+
elif isinstance(obj, Op):
|
|
289
256
|
check.none(root)
|
|
290
257
|
gram = Grammar(Rule('root', obj), root='root')
|
|
291
258
|
else:
|
|
@@ -299,7 +266,7 @@ def iter_parse(
|
|
|
299
266
|
|
|
300
267
|
|
|
301
268
|
def parse(
|
|
302
|
-
obj: Grammar | Rule |
|
|
269
|
+
obj: Grammar | Rule | Op,
|
|
303
270
|
src: str,
|
|
304
271
|
*,
|
|
305
272
|
root: str | None = None,
|
omextra/text/abnf/core.py
CHANGED
|
@@ -5,11 +5,11 @@ import typing as ta
|
|
|
5
5
|
|
|
6
6
|
from .base import Grammar
|
|
7
7
|
from .base import Rule
|
|
8
|
-
from .
|
|
9
|
-
from .
|
|
10
|
-
from .
|
|
11
|
-
from .
|
|
12
|
-
from .
|
|
8
|
+
from .ops import concat
|
|
9
|
+
from .ops import either
|
|
10
|
+
from .ops import literal
|
|
11
|
+
from .ops import repeat
|
|
12
|
+
from .ops import rule
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
##
|
|
File without changes
|