omextra 0.0.0.dev497__py3-none-any.whl → 0.0.0.dev499__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.
@@ -13,10 +13,37 @@ TODO:
13
13
  - opto
14
14
  - error reporting
15
15
  - codegen?
16
+ - | as either(first_match=True)
17
+ - optional auto SPACE channel for ALL-UPCASE-RULE-NAMES
16
18
  - fix_ws problem
17
19
  - auto? no, need to keep lines / offsets accurate for errors
18
20
  - relax CRLF rule by default?
19
21
  - grammar transform? helper kwarg?
22
+ - kwarg to mark uppercase rules insignificant
23
+ - ebnf mode?
24
+ - peg / lalr engines?
25
+ - must always keep true abnf mode
26
+ - optionally separate lexing step
27
+
28
+ ====
29
+
30
+ | Feature | EBNF | ABNF |
31
+ | ------------------------- | -------------- | ---------------- |
32
+ | Rule terminator | `;` | none |
33
+ | Alternation | `|` | `/` |
34
+ | Optional | `[a]` or `a?` | `[a]` |
35
+ | Zero or more | `a*` | `*a` |
36
+ | One or more | `a+` | `1*a` |
37
+ | Bounded repetition | `1..5 a` | `1*5a` |
38
+ | Character ranges | sometimes: | `%xNN-NN` |
39
+ | | `"0" .. "9"` | |
40
+ | Literal chars | `'a'` or `"a"` | `"a"` only |
41
+ | Case-insensitive literals | no | `%i"..."` |
42
+ | Comments | `(* *)` or | `;` |
43
+ | | `/* */` or | |
44
+ | | `-- ` | |
45
+ | Rule names | case-sensitive | case-insensitive |
46
+
20
47
  """
21
48
  from omlish import dataclasses as _dc # noqa
22
49
 
@@ -31,16 +58,7 @@ _dc.init_package(
31
58
 
32
59
 
33
60
  from .base import ( # noqa
34
- Match,
35
- longest_match,
36
-
37
61
  Op,
38
-
39
- Rule,
40
- Grammar,
41
-
42
- iter_parse,
43
- parse,
44
62
  )
45
63
 
46
64
  from .core import ( # noqa
@@ -52,6 +70,21 @@ from .errors import ( # noqa
52
70
  AbnfGrammarParseError,
53
71
  )
54
72
 
73
+ from .grammars import ( # noqa
74
+ Channel,
75
+ Rule,
76
+ RulesCollection,
77
+
78
+ Grammar,
79
+ )
80
+
81
+ from .matches import ( # noqa
82
+ Match,
83
+
84
+ longest_match,
85
+ filter_matches,
86
+ )
87
+
55
88
  from .meta import ( # noqa
56
89
  META_GRAMMAR_RULES,
57
90
  META_GRAMMAR,
@@ -80,15 +113,13 @@ from .ops import ( # noqa
80
113
  rule,
81
114
  )
82
115
 
83
- from .opto import ( # noqa
84
- optimize_op,
116
+ from .parsing import ( # noqa
117
+ iter_parse,
118
+ parse,
85
119
  )
86
120
 
87
121
  from .utils import ( # noqa
88
- strip_insignificant_match_rules,
89
122
  only_match_rules,
90
123
 
91
- parse_rules,
92
-
93
124
  fix_ws,
94
125
  )
@@ -39,6 +39,8 @@ def _register(**kwargs):
39
39
  cls_names=(
40
40
  ('omextra.text.abnf', 'MetaGrammarRuleMatchVisitor.QuotedString'),
41
41
  ('omextra.text.abnf', 'MetaGrammarRuleMatchVisitor.RuleName'),
42
+ ('omextra.text.abnf', '_CaseInsensitiveStringLiteralRegexItem'),
43
+ ('omextra.text.abnf', '_StringLiteralRegexItem'),
42
44
  ),
43
45
  )
44
46
  def _process_dataclass__30a5dd74853303d917aae5f67d4e7189615d1440():
@@ -436,3 +438,247 @@ def _process_dataclass__3dce49e08774c707abbc7a6513e35ccdc43001c9():
436
438
  setattr(__dataclass__cls, '__init__', __init__)
437
439
 
438
440
  return _process_dataclass
441
+
442
+
443
+ @_register(
444
+ plan_repr=(
445
+ "Plans(tup=(CopyPlan(fields=()), EqPlan(fields=()), FrozenPlan(fields=(), allow_dynamic_dunder_attrs=False), Ha"
446
+ "shPlan(action='add', fields=(), cache=False), InitPlan(fields=(), self_param='self', std_params=(), kw_only_pa"
447
+ "rams=(), frozen=True, slots=False, post_init_params=None, init_fns=(), validate_fns=()), ReprPlan(fields=(), i"
448
+ "d=False, terse=False, default_fn=None)))"
449
+ ),
450
+ plan_repr_sha1='e1f7edfe11f2b721d6a656c46e698fedc95461bb',
451
+ op_ref_idents=(),
452
+ cls_names=(
453
+ ('omextra.text.abnf', '_RegexItem'),
454
+ ),
455
+ )
456
+ def _process_dataclass__e1f7edfe11f2b721d6a656c46e698fedc95461bb():
457
+ def _process_dataclass(
458
+ *,
459
+ __dataclass__cls,
460
+ __dataclass__FieldFnValidationError, # noqa
461
+ __dataclass__FieldTypeValidationError, # noqa
462
+ __dataclass__FnValidationError, # noqa
463
+ __dataclass__FrozenInstanceError=dataclasses.FrozenInstanceError, # noqa
464
+ __dataclass__FunctionType=types.FunctionType, # noqa
465
+ __dataclass__HAS_DEFAULT_FACTORY=dataclasses._HAS_DEFAULT_FACTORY, # noqa
466
+ __dataclass__MISSING=dataclasses.MISSING, # noqa
467
+ __dataclass__None=None, # noqa
468
+ __dataclass__TypeError=TypeError, # noqa
469
+ __dataclass___recursive_repr=reprlib.recursive_repr, # noqa
470
+ __dataclass__isinstance=isinstance, # noqa
471
+ __dataclass__object_setattr=object.__setattr__, # noqa
472
+ __dataclass__property=property, # noqa
473
+ ):
474
+ def __copy__(self):
475
+ if self.__class__ is not __dataclass__cls:
476
+ raise TypeError(self)
477
+ return __dataclass__cls() # noqa
478
+
479
+ __copy__.__qualname__ = f"{__dataclass__cls.__qualname__}.__copy__"
480
+ if '__copy__' in __dataclass__cls.__dict__:
481
+ raise __dataclass__TypeError(f"Cannot overwrite attribute __copy__ in class {__dataclass__cls.__name__}")
482
+ setattr(__dataclass__cls, '__copy__', __copy__)
483
+
484
+ def __eq__(self, other):
485
+ if self is other:
486
+ return True
487
+ if self.__class__ is not other.__class__:
488
+ return NotImplemented
489
+ return True
490
+
491
+ __eq__.__qualname__ = f"{__dataclass__cls.__qualname__}.__eq__"
492
+ if '__eq__' in __dataclass__cls.__dict__:
493
+ raise __dataclass__TypeError(f"Cannot overwrite attribute __eq__ in class {__dataclass__cls.__name__}")
494
+ setattr(__dataclass__cls, '__eq__', __eq__)
495
+
496
+ def __setattr__(self, name, value):
497
+ if (
498
+ type(self) is __dataclass__cls
499
+ ):
500
+ raise __dataclass__FrozenInstanceError(f"cannot assign to field {name!r}")
501
+ super(__dataclass__cls, self).__setattr__(name, value)
502
+
503
+ __setattr__.__qualname__ = f"{__dataclass__cls.__qualname__}.__setattr__"
504
+ if '__setattr__' in __dataclass__cls.__dict__:
505
+ raise __dataclass__TypeError(f"Cannot overwrite attribute __setattr__ in class {__dataclass__cls.__name__}")
506
+ setattr(__dataclass__cls, '__setattr__', __setattr__)
507
+
508
+ def __delattr__(self, name):
509
+ if (
510
+ type(self) is __dataclass__cls
511
+ ):
512
+ raise __dataclass__FrozenInstanceError(f"cannot delete field {name!r}")
513
+ super(__dataclass__cls, self).__delattr__(name)
514
+
515
+ __delattr__.__qualname__ = f"{__dataclass__cls.__qualname__}.__delattr__"
516
+ if '__delattr__' in __dataclass__cls.__dict__:
517
+ raise __dataclass__TypeError(f"Cannot overwrite attribute __delattr__ in class {__dataclass__cls.__name__}")
518
+ setattr(__dataclass__cls, '__delattr__', __delattr__)
519
+
520
+ def __hash__(self):
521
+ return hash(())
522
+
523
+ __hash__.__qualname__ = f"{__dataclass__cls.__qualname__}.__hash__"
524
+ setattr(__dataclass__cls, '__hash__', __hash__)
525
+
526
+ def __init__(
527
+ self,
528
+ ) -> __dataclass__None:
529
+ pass
530
+
531
+ __init__.__qualname__ = f"{__dataclass__cls.__qualname__}.__init__"
532
+ if '__init__' in __dataclass__cls.__dict__:
533
+ raise __dataclass__TypeError(f"Cannot overwrite attribute __init__ in class {__dataclass__cls.__name__}")
534
+ setattr(__dataclass__cls, '__init__', __init__)
535
+
536
+ @__dataclass___recursive_repr()
537
+ def __repr__(self):
538
+ parts = []
539
+ return (
540
+ f"{self.__class__.__qualname__}("
541
+ f"{', '.join(parts)}"
542
+ f")"
543
+ )
544
+
545
+ __repr__.__qualname__ = f"{__dataclass__cls.__qualname__}.__repr__"
546
+ if '__repr__' in __dataclass__cls.__dict__:
547
+ raise __dataclass__TypeError(f"Cannot overwrite attribute __repr__ in class {__dataclass__cls.__name__}")
548
+ setattr(__dataclass__cls, '__repr__', __repr__)
549
+
550
+ return _process_dataclass
551
+
552
+
553
+ @_register(
554
+ plan_repr=(
555
+ "Plans(tup=(CopyPlan(fields=('ps',)), EqPlan(fields=('ps',)), FrozenPlan(fields=('ps',), allow_dynamic_dunder_a"
556
+ "ttrs=False), HashPlan(action='add', fields=('ps',), cache=False), InitPlan(fields=(InitPlan.Field(name='ps', a"
557
+ "nnotation=OpRef(name='init.fields.0.annotation'), default=None, default_factory=None, init=True, override=Fals"
558
+ "e, field_type=FieldType.INSTANCE, coerce=None, validate=None, check_type=None),), self_param='self', std_param"
559
+ "s=('ps',), kw_only_params=(), frozen=True, slots=False, post_init_params=None, init_fns=(), validate_fns=()), "
560
+ "ReprPlan(fields=(ReprPlan.Field(name='ps', kw_only=False, fn=None),), id=False, terse=False, default_fn=None))"
561
+ ")"
562
+ ),
563
+ plan_repr_sha1='f7dc3147180d5d4dc248e9c0d94aa0f1e503c4c7',
564
+ op_ref_idents=(
565
+ '__dataclass__init__fields__0__annotation',
566
+ ),
567
+ cls_names=(
568
+ ('omextra.text.abnf', '_RegexRegexItem'),
569
+ ),
570
+ )
571
+ def _process_dataclass__f7dc3147180d5d4dc248e9c0d94aa0f1e503c4c7():
572
+ def _process_dataclass(
573
+ *,
574
+ __dataclass__cls,
575
+ __dataclass__init__fields__0__annotation,
576
+ __dataclass__FieldFnValidationError, # noqa
577
+ __dataclass__FieldTypeValidationError, # noqa
578
+ __dataclass__FnValidationError, # noqa
579
+ __dataclass__FrozenInstanceError=dataclasses.FrozenInstanceError, # noqa
580
+ __dataclass__FunctionType=types.FunctionType, # noqa
581
+ __dataclass__HAS_DEFAULT_FACTORY=dataclasses._HAS_DEFAULT_FACTORY, # noqa
582
+ __dataclass__MISSING=dataclasses.MISSING, # noqa
583
+ __dataclass__None=None, # noqa
584
+ __dataclass__TypeError=TypeError, # noqa
585
+ __dataclass___recursive_repr=reprlib.recursive_repr, # noqa
586
+ __dataclass__isinstance=isinstance, # noqa
587
+ __dataclass__object_setattr=object.__setattr__, # noqa
588
+ __dataclass__property=property, # noqa
589
+ ):
590
+ def __copy__(self):
591
+ if self.__class__ is not __dataclass__cls:
592
+ raise TypeError(self)
593
+ return __dataclass__cls( # noqa
594
+ ps=self.ps,
595
+ )
596
+
597
+ __copy__.__qualname__ = f"{__dataclass__cls.__qualname__}.__copy__"
598
+ if '__copy__' in __dataclass__cls.__dict__:
599
+ raise __dataclass__TypeError(f"Cannot overwrite attribute __copy__ in class {__dataclass__cls.__name__}")
600
+ setattr(__dataclass__cls, '__copy__', __copy__)
601
+
602
+ def __eq__(self, other):
603
+ if self is other:
604
+ return True
605
+ if self.__class__ is not other.__class__:
606
+ return NotImplemented
607
+ return (
608
+ self.ps == other.ps
609
+ )
610
+
611
+ __eq__.__qualname__ = f"{__dataclass__cls.__qualname__}.__eq__"
612
+ if '__eq__' in __dataclass__cls.__dict__:
613
+ raise __dataclass__TypeError(f"Cannot overwrite attribute __eq__ in class {__dataclass__cls.__name__}")
614
+ setattr(__dataclass__cls, '__eq__', __eq__)
615
+
616
+ __dataclass___setattr_frozen_fields = {
617
+ 'ps',
618
+ }
619
+
620
+ def __setattr__(self, name, value):
621
+ if (
622
+ type(self) is __dataclass__cls
623
+ or name in __dataclass___setattr_frozen_fields
624
+ ):
625
+ raise __dataclass__FrozenInstanceError(f"cannot assign to field {name!r}")
626
+ super(__dataclass__cls, self).__setattr__(name, value)
627
+
628
+ __setattr__.__qualname__ = f"{__dataclass__cls.__qualname__}.__setattr__"
629
+ if '__setattr__' in __dataclass__cls.__dict__:
630
+ raise __dataclass__TypeError(f"Cannot overwrite attribute __setattr__ in class {__dataclass__cls.__name__}")
631
+ setattr(__dataclass__cls, '__setattr__', __setattr__)
632
+
633
+ __dataclass___delattr_frozen_fields = {
634
+ 'ps',
635
+ }
636
+
637
+ def __delattr__(self, name):
638
+ if (
639
+ type(self) is __dataclass__cls
640
+ or name in __dataclass___delattr_frozen_fields
641
+ ):
642
+ raise __dataclass__FrozenInstanceError(f"cannot delete field {name!r}")
643
+ super(__dataclass__cls, self).__delattr__(name)
644
+
645
+ __delattr__.__qualname__ = f"{__dataclass__cls.__qualname__}.__delattr__"
646
+ if '__delattr__' in __dataclass__cls.__dict__:
647
+ raise __dataclass__TypeError(f"Cannot overwrite attribute __delattr__ in class {__dataclass__cls.__name__}")
648
+ setattr(__dataclass__cls, '__delattr__', __delattr__)
649
+
650
+ def __hash__(self):
651
+ return hash((
652
+ self.ps,
653
+ ))
654
+
655
+ __hash__.__qualname__ = f"{__dataclass__cls.__qualname__}.__hash__"
656
+ setattr(__dataclass__cls, '__hash__', __hash__)
657
+
658
+ def __init__(
659
+ self,
660
+ ps: __dataclass__init__fields__0__annotation,
661
+ ) -> __dataclass__None:
662
+ __dataclass__object_setattr(self, 'ps', ps)
663
+
664
+ __init__.__qualname__ = f"{__dataclass__cls.__qualname__}.__init__"
665
+ if '__init__' in __dataclass__cls.__dict__:
666
+ raise __dataclass__TypeError(f"Cannot overwrite attribute __init__ in class {__dataclass__cls.__name__}")
667
+ setattr(__dataclass__cls, '__init__', __init__)
668
+
669
+ @__dataclass___recursive_repr()
670
+ def __repr__(self):
671
+ parts = []
672
+ parts.append(f"ps={self.ps!r}")
673
+ return (
674
+ f"{self.__class__.__qualname__}("
675
+ f"{', '.join(parts)}"
676
+ f")"
677
+ )
678
+
679
+ __repr__.__qualname__ = f"{__dataclass__cls.__qualname__}.__repr__"
680
+ if '__repr__' in __dataclass__cls.__dict__:
681
+ raise __dataclass__TypeError(f"Cannot overwrite attribute __repr__ in class {__dataclass__cls.__name__}")
682
+ setattr(__dataclass__cls, '__repr__', __repr__)
683
+
684
+ return _process_dataclass
omextra/text/abnf/base.py CHANGED
@@ -1,109 +1,11 @@
1
1
  import abc
2
- import io
3
- import itertools
4
2
  import typing as ta
5
3
 
6
4
  from omlish import check
7
5
  from omlish import lang
8
6
 
9
- from .errors import AbnfError
10
- from .errors import AbnfIncompleteParseError
11
7
 
12
-
13
- with lang.auto_proxy_import(globals()):
14
- from . import internal
15
- from . import ops
16
- from . import parsing
17
-
18
-
19
- ##
20
-
21
-
22
- @ta.final
23
- class Match(ta.NamedTuple):
24
- op: 'Op'
25
- start: int
26
- end: int
27
- children: tuple['Match', ...]
28
-
29
- @property
30
- def length(self) -> int:
31
- return self.end - self.start
32
-
33
- #
34
-
35
- def __repr__(self) -> str:
36
- return (
37
- f'{self.__class__.__name__}('
38
- f'{self.op._match_repr()}, ' # noqa
39
- f'{self.start}, {self.end}'
40
- f'{f", {self.children!r}" if self.children else ""})'
41
- )
42
-
43
- def render_to(
44
- self,
45
- write: ta.Callable[[str], ta.Any],
46
- *,
47
- indent: int | None = None,
48
- _depth: int = 0,
49
- ) -> None:
50
- ix: str | None = (' ' * (indent * _depth)) if indent is not None else None
51
- if ix:
52
- write(ix)
53
- o = self.op
54
- if isinstance(o, (ops.StringLiteral, ops.CaseInsensitiveStringLiteral)):
55
- write(f'literal<{self.start}-{self.end}>({o.value!r})')
56
- elif isinstance(o, ops.RangeLiteral):
57
- write(f'literal<{self.start}-{self.end}>({o.value.lo!r}-{o.value.hi!r})')
58
- elif isinstance(o, internal.Regex):
59
- write(f'regex<{self.start}-{self.end}>({o.pat.pattern!r})')
60
- else:
61
- write(f'{o.__class__.__name__.lower()}<{self.start}-{self.end}>')
62
- if isinstance(o, ops.RuleRef):
63
- write(f':{o.name}')
64
- if self.children:
65
- write('(')
66
- if ix is not None:
67
- write('\n')
68
- for i, c in enumerate(self.children):
69
- if i and ix is None:
70
- write(', ')
71
- c.render_to(write, indent=indent, _depth=_depth + 1)
72
- if ix is not None:
73
- write(',\n')
74
- if ix:
75
- write(ix)
76
- write(')')
77
-
78
- def render(
79
- self,
80
- *,
81
- indent: int | None = None,
82
- ) -> str:
83
- sb = io.StringIO()
84
- self.render_to(sb.write, indent=indent)
85
- return sb.getvalue()
86
-
87
- def __str__(self) -> str:
88
- return self.render()
89
-
90
- #
91
-
92
- def map_children(self, fn: ta.Callable[['Match'], 'Match']) -> 'Match':
93
- return self._replace(children=tuple(map(fn, self.children)))
94
-
95
- def flat_map_children(self, fn: ta.Callable[['Match'], ta.Iterable['Match']]) -> 'Match':
96
- return self._replace(children=tuple(itertools.chain.from_iterable(map(fn, self.children))))
97
-
98
-
99
- def longest_match(ms: ta.Iterable[Match]) -> Match | None:
100
- bm: Match | None = None
101
- bl = 0
102
- for m in ms:
103
- l = m.length
104
- if bm is None or l > bl:
105
- bm, bl = m, l
106
- return bm
8
+ OpTuple: ta.TypeAlias = tuple['Op', ...]
107
9
 
108
10
 
109
11
  ##
@@ -127,7 +29,11 @@ class CompositeOp(Op, lang.Abstract):
127
29
 
128
30
  @property
129
31
  @abc.abstractmethod
130
- def children(self) -> ta.Sequence[Op]:
32
+ def children(self) -> OpTuple:
33
+ raise NotImplementedError
34
+
35
+ @abc.abstractmethod
36
+ def replace_children(self, *children: Op) -> Op:
131
37
  raise NotImplementedError
132
38
 
133
39
 
@@ -136,182 +42,3 @@ class LeafOp(Op, lang.Abstract):
136
42
  super().__init_subclass__(**kwargs)
137
43
 
138
44
  check.not_issubclass(cls, CompositeOp)
139
-
140
-
141
- ##
142
-
143
-
144
- class Rule(lang.Final):
145
- def __init__(
146
- self,
147
- name: str,
148
- op: Op,
149
- *,
150
- insignificant: bool = False,
151
- ) -> None:
152
- super().__init__()
153
-
154
- self._name = check.non_empty_str(name)
155
- self._op = check.isinstance(op, Op)
156
- self._insignificant = insignificant
157
-
158
- self._name_f = name.casefold()
159
-
160
- def __repr__(self) -> str:
161
- return f'{self.__class__.__name__}({self._name!r})'
162
-
163
- def replace_op(self, op: Op) -> 'Rule':
164
- return Rule(
165
- self._name,
166
- op,
167
- insignificant=self._insignificant,
168
- )
169
-
170
- @property
171
- def name(self) -> str:
172
- return self._name
173
-
174
- @property
175
- def name_f(self) -> str:
176
- return self._name_f
177
-
178
- @property
179
- def op(self) -> Op:
180
- return self._op
181
-
182
- @property
183
- def insignificant(self) -> bool:
184
- return self._insignificant
185
-
186
-
187
- class Grammar(lang.Final):
188
- def __init__(
189
- self,
190
- *rules: Rule,
191
- root: Rule | str | None = None,
192
- ) -> None:
193
- super().__init__()
194
-
195
- rules_set: set[Rule] = set()
196
- rules_by_name: dict[str, Rule] = {}
197
- rules_by_name_f: dict[str, Rule] = {}
198
- rules_by_op: dict[Op, Rule] = {}
199
- for gr in rules:
200
- check.isinstance(gr, Rule)
201
- check.not_in(gr, rules_set)
202
- check.not_in(gr._name, rules_by_name) # noqa
203
- check.not_in(gr._name_f, rules_by_name_f) # noqa
204
- check.not_in(gr._op, rules_by_op) # noqa
205
- rules_set.add(gr)
206
- rules_by_name[gr._name] = gr # noqa
207
- rules_by_name_f[gr._name_f] = gr # noqa
208
- rules_by_op[gr._op] = gr # noqa
209
- self._rules = rules_set
210
- self._rules_by_name: ta.Mapping[str, Rule] = rules_by_name
211
- self._rules_by_name_f: ta.Mapping[str, Rule] = rules_by_name_f
212
- self._rules_by_op: ta.Mapping[Op, Rule] = rules_by_op
213
-
214
- if isinstance(root, str):
215
- root = rules_by_name_f[root.casefold()]
216
- self._root = root
217
-
218
- @property
219
- def root(self) -> Rule | None:
220
- return self._root
221
-
222
- def rule(self, name: str) -> Rule | None:
223
- return self._rules_by_name_f.get(name.casefold())
224
-
225
- def iter_parse(
226
- self,
227
- source: str,
228
- root: Rule | str | None = None,
229
- *,
230
- start: int = 0,
231
- debug: int = 0,
232
- **kwargs: ta.Any,
233
- ) -> ta.Iterator[Match]:
234
- if root is None:
235
- if (root := self._root) is None:
236
- raise AbnfError('No root or default root specified')
237
- else:
238
- if isinstance(root, str):
239
- root = self._rules_by_name_f[root.casefold()]
240
- else:
241
- root = check.in_(check.isinstance(root, Rule), self._rules)
242
-
243
- return parsing._iter_parse( # noqa
244
- self,
245
- source,
246
- root._op, # noqa
247
- start,
248
- debug=debug,
249
- **kwargs,
250
- )
251
-
252
- def parse(
253
- self,
254
- source: str,
255
- root: str | None = None,
256
- *,
257
- start: int = 0,
258
- complete: bool = False,
259
- debug: int = 0,
260
- **kwargs: ta.Any,
261
- ) -> Match | None:
262
- if (match := longest_match(self.iter_parse(
263
- source,
264
- root,
265
- start=start,
266
- debug=debug,
267
- **kwargs,
268
- ))) is None:
269
- return None
270
-
271
- if complete and (match.start, match.end) != (start, len(source)):
272
- raise AbnfIncompleteParseError
273
-
274
- return match
275
-
276
-
277
- ##
278
-
279
-
280
- def iter_parse(
281
- obj: Grammar | Rule | Op,
282
- src: str,
283
- *,
284
- root: str | None = None,
285
- start: int = 0,
286
- ) -> ta.Iterator[Match]:
287
- if isinstance(obj, Grammar):
288
- gram = obj
289
- elif isinstance(obj, Rule):
290
- check.none(root)
291
- gram = Grammar(obj, root=obj)
292
- elif isinstance(obj, Op):
293
- check.none(root)
294
- gram = Grammar(Rule('root', obj), root='root')
295
- else:
296
- raise TypeError(obj)
297
-
298
- return gram.iter_parse(
299
- src,
300
- root,
301
- start=start,
302
- )
303
-
304
-
305
- def parse(
306
- obj: Grammar | Rule | Op,
307
- src: str,
308
- *,
309
- root: str | None = None,
310
- start: int = 0,
311
- ) -> Match | None:
312
- return longest_match(iter_parse(
313
- obj,
314
- src,
315
- root=root,
316
- start=start,
317
- ))