omextra 0.0.0.dev494__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/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 parsers
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
- parser: 'Parser'
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.parser._match_repr()}, ' # noqa
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
- _level: int = 0,
46
+ _depth: int = 0,
46
47
  ) -> None:
47
- ix: str | None = (' ' * (indent * _level)) if indent is not None else None
48
+ ix: str | None = (' ' * (indent * _depth)) if indent is not None else None
48
49
  if ix:
49
50
  write(ix)
50
- p = self.parser
51
- if isinstance(p, (parsers.StringLiteral, parsers.CaseInsensitiveStringLiteral)):
52
- write(f'literal<{self.start}-{self.end}>({p.value!r})')
53
- elif isinstance(p, parsers.RangeLiteral):
54
- write(f'literal<{self.start}-{self.end}>({p.value.lo!r}-{p.value.hi!r})')
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'{p.__class__.__name__.lower()}<{self.start}-{self.end}>')
57
- if isinstance(p, parsers.RuleRef):
58
- write(f':{p.name}')
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, _level=_level + 1)
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 Parser(lang.Abstract, lang.PackageSealed):
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
- @abc.abstractmethod
112
- def _iter_parse(self, ctx: '_Context', start: int) -> ta.Iterator[Match]:
113
- raise NotImplementedError
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
- parser: Parser,
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._parser = check.isinstance(parser, Parser)
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 parser(self) -> Parser:
147
- return self._parser
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
- rules_by_parser: dict[Parser, Rule] = {}
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._parser, rules_by_parser) # noqa
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
- rules_by_parser[gr._parser] = gr # noqa
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._rules_by_parser: ta.Mapping[Parser, Rule] = rules_by_parser
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: bool = False,
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
- ctx_cls: type[_Context]
208
- if debug:
209
- ctx_cls = _DebugContext
210
- else:
211
- ctx_cls = _Context
212
- ctx = ctx_cls(self, source)
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
- debug: bool = False,
223
+ complete: bool = False,
224
+ debug: int = 0,
223
225
  ) -> Match | None:
224
- return longest_match(self.iter_parse(
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
- class _DebugContext(_Context):
259
- _level: int = 0
234
+ if complete and (match.start, match.end) != (start, len(source)):
235
+ raise AbnfIncompleteParseError
260
236
 
261
- def iter_parse(self, parser: Parser, start: int) -> ta.Iterator[Match]:
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 | Parser,
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, Parser):
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 | Parser,
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 .parsers import concat
9
- from .parsers import either
10
- from .parsers import literal
11
- from .parsers import repeat
12
- from .parsers import rule
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