1 from __future__ import annotations
2
3 from abc import abstractmethod
4 from typing import (
5 TYPE_CHECKING,
6 AbstractSet,
7 Any,
8 Dict,
9 Iterable,
10 Iterator,
11 List,
12 Optional,
13 Set,
14 Tuple,
15 Union,
16 )
17
18 if TYPE_CHECKING:
19 from pegen.parser_generator import ParserGenerator
20
21
22 class ESC[4;38;5;81mGrammarError(ESC[4;38;5;149mException):
23 pass
24
25
26 class ESC[4;38;5;81mGrammarVisitor:
27 def visit(self, node: Any, *args: Any, **kwargs: Any) -> Any:
28 """Visit a node."""
29 method = "visit_" + node.__class__.__name__
30 visitor = getattr(self, method, self.generic_visit)
31 return visitor(node, *args, **kwargs)
32
33 def generic_visit(self, node: Iterable[Any], *args: Any, **kwargs: Any) -> Any:
34 """Called if no explicit visitor function exists for a node."""
35 for value in node:
36 if isinstance(value, list):
37 for item in value:
38 self.visit(item, *args, **kwargs)
39 else:
40 self.visit(value, *args, **kwargs)
41
42
43 class ESC[4;38;5;81mGrammar:
44 def __init__(self, rules: Iterable[Rule], metas: Iterable[Tuple[str, Optional[str]]]):
45 self.rules = {rule.name: rule for rule in rules}
46 self.metas = dict(metas)
47
48 def __str__(self) -> str:
49 return "\n".join(str(rule) for name, rule in self.rules.items())
50
51 def __repr__(self) -> str:
52 lines = ["Grammar("]
53 lines.append(" [")
54 for rule in self.rules.values():
55 lines.append(f" {repr(rule)},")
56 lines.append(" ],")
57 lines.append(" {repr(list(self.metas.items()))}")
58 lines.append(")")
59 return "\n".join(lines)
60
61 def __iter__(self) -> Iterator[Rule]:
62 yield from self.rules.values()
63
64
65 # Global flag whether we want actions in __str__() -- default off.
66 SIMPLE_STR = True
67
68
69 class ESC[4;38;5;81mRule:
70 def __init__(self, name: str, type: Optional[str], rhs: Rhs, memo: Optional[object] = None):
71 self.name = name
72 self.type = type
73 self.rhs = rhs
74 self.memo = bool(memo)
75 self.left_recursive = False
76 self.leader = False
77
78 def is_loop(self) -> bool:
79 return self.name.startswith("_loop")
80
81 def is_gather(self) -> bool:
82 return self.name.startswith("_gather")
83
84 def __str__(self) -> str:
85 if SIMPLE_STR or self.type is None:
86 res = f"{self.name}: {self.rhs}"
87 else:
88 res = f"{self.name}[{self.type}]: {self.rhs}"
89 if len(res) < 88:
90 return res
91 lines = [res.split(":")[0] + ":"]
92 lines += [f" | {alt}" for alt in self.rhs.alts]
93 return "\n".join(lines)
94
95 def __repr__(self) -> str:
96 return f"Rule({self.name!r}, {self.type!r}, {self.rhs!r})"
97
98 def __iter__(self) -> Iterator[Rhs]:
99 yield self.rhs
100
101 def flatten(self) -> Rhs:
102 # If it's a single parenthesized group, flatten it.
103 rhs = self.rhs
104 if (
105 not self.is_loop()
106 and len(rhs.alts) == 1
107 and len(rhs.alts[0].items) == 1
108 and isinstance(rhs.alts[0].items[0].item, Group)
109 ):
110 rhs = rhs.alts[0].items[0].item.rhs
111 return rhs
112
113
114 class ESC[4;38;5;81mLeaf:
115 def __init__(self, value: str):
116 self.value = value
117
118 def __str__(self) -> str:
119 return self.value
120
121 def __iter__(self) -> Iterable[str]:
122 if False:
123 yield
124
125
126 class ESC[4;38;5;81mNameLeaf(ESC[4;38;5;149mLeaf):
127 """The value is the name."""
128
129 def __str__(self) -> str:
130 if self.value == "ENDMARKER":
131 return "$"
132 return super().__str__()
133
134 def __repr__(self) -> str:
135 return f"NameLeaf({self.value!r})"
136
137
138 class ESC[4;38;5;81mStringLeaf(ESC[4;38;5;149mLeaf):
139 """The value is a string literal, including quotes."""
140
141 def __repr__(self) -> str:
142 return f"StringLeaf({self.value!r})"
143
144
145 class ESC[4;38;5;81mRhs:
146 def __init__(self, alts: List[Alt]):
147 self.alts = alts
148 self.memo: Optional[Tuple[Optional[str], str]] = None
149
150 def __str__(self) -> str:
151 return " | ".join(str(alt) for alt in self.alts)
152
153 def __repr__(self) -> str:
154 return f"Rhs({self.alts!r})"
155
156 def __iter__(self) -> Iterator[List[Alt]]:
157 yield self.alts
158
159 @property
160 def can_be_inlined(self) -> bool:
161 if len(self.alts) != 1 or len(self.alts[0].items) != 1:
162 return False
163 # If the alternative has an action we cannot inline
164 if getattr(self.alts[0], "action", None) is not None:
165 return False
166 return True
167
168
169 class ESC[4;38;5;81mAlt:
170 def __init__(self, items: List[NamedItem], *, icut: int = -1, action: Optional[str] = None):
171 self.items = items
172 self.icut = icut
173 self.action = action
174
175 def __str__(self) -> str:
176 core = " ".join(str(item) for item in self.items)
177 if not SIMPLE_STR and self.action:
178 return f"{core} {{ {self.action} }}"
179 else:
180 return core
181
182 def __repr__(self) -> str:
183 args = [repr(self.items)]
184 if self.icut >= 0:
185 args.append(f"icut={self.icut}")
186 if self.action:
187 args.append(f"action={self.action!r}")
188 return f"Alt({', '.join(args)})"
189
190 def __iter__(self) -> Iterator[List[NamedItem]]:
191 yield self.items
192
193
194 class ESC[4;38;5;81mNamedItem:
195 def __init__(self, name: Optional[str], item: Item, type: Optional[str] = None):
196 self.name = name
197 self.item = item
198 self.type = type
199
200 def __str__(self) -> str:
201 if not SIMPLE_STR and self.name:
202 return f"{self.name}={self.item}"
203 else:
204 return str(self.item)
205
206 def __repr__(self) -> str:
207 return f"NamedItem({self.name!r}, {self.item!r})"
208
209 def __iter__(self) -> Iterator[Item]:
210 yield self.item
211
212
213 class ESC[4;38;5;81mForced:
214 def __init__(self, node: Plain):
215 self.node = node
216
217 def __str__(self) -> str:
218 return f"&&{self.node}"
219
220 def __iter__(self) -> Iterator[Plain]:
221 yield self.node
222
223
224 class ESC[4;38;5;81mLookahead:
225 def __init__(self, node: Plain, sign: str):
226 self.node = node
227 self.sign = sign
228
229 def __str__(self) -> str:
230 return f"{self.sign}{self.node}"
231
232 def __iter__(self) -> Iterator[Plain]:
233 yield self.node
234
235
236 class ESC[4;38;5;81mPositiveLookahead(ESC[4;38;5;149mLookahead):
237 def __init__(self, node: Plain):
238 super().__init__(node, "&")
239
240 def __repr__(self) -> str:
241 return f"PositiveLookahead({self.node!r})"
242
243
244 class ESC[4;38;5;81mNegativeLookahead(ESC[4;38;5;149mLookahead):
245 def __init__(self, node: Plain):
246 super().__init__(node, "!")
247
248 def __repr__(self) -> str:
249 return f"NegativeLookahead({self.node!r})"
250
251
252 class ESC[4;38;5;81mOpt:
253 def __init__(self, node: Item):
254 self.node = node
255
256 def __str__(self) -> str:
257 s = str(self.node)
258 # TODO: Decide whether to use [X] or X? based on type of X
259 if " " in s:
260 return f"[{s}]"
261 else:
262 return f"{s}?"
263
264 def __repr__(self) -> str:
265 return f"Opt({self.node!r})"
266
267 def __iter__(self) -> Iterator[Item]:
268 yield self.node
269
270
271 class ESC[4;38;5;81mRepeat:
272 """Shared base class for x* and x+."""
273
274 def __init__(self, node: Plain):
275 self.node = node
276 self.memo: Optional[Tuple[Optional[str], str]] = None
277
278 def __iter__(self) -> Iterator[Plain]:
279 yield self.node
280
281
282 class ESC[4;38;5;81mRepeat0(ESC[4;38;5;149mRepeat):
283 def __str__(self) -> str:
284 s = str(self.node)
285 # TODO: Decide whether to use (X)* or X* based on type of X
286 if " " in s:
287 return f"({s})*"
288 else:
289 return f"{s}*"
290
291 def __repr__(self) -> str:
292 return f"Repeat0({self.node!r})"
293
294
295 class ESC[4;38;5;81mRepeat1(ESC[4;38;5;149mRepeat):
296 def __str__(self) -> str:
297 s = str(self.node)
298 # TODO: Decide whether to use (X)+ or X+ based on type of X
299 if " " in s:
300 return f"({s})+"
301 else:
302 return f"{s}+"
303
304 def __repr__(self) -> str:
305 return f"Repeat1({self.node!r})"
306
307
308 class ESC[4;38;5;81mGather(ESC[4;38;5;149mRepeat):
309 def __init__(self, separator: Plain, node: Plain):
310 self.separator = separator
311 self.node = node
312
313 def __str__(self) -> str:
314 return f"{self.separator!s}.{self.node!s}+"
315
316 def __repr__(self) -> str:
317 return f"Gather({self.separator!r}, {self.node!r})"
318
319
320 class ESC[4;38;5;81mGroup:
321 def __init__(self, rhs: Rhs):
322 self.rhs = rhs
323
324 def __str__(self) -> str:
325 return f"({self.rhs})"
326
327 def __repr__(self) -> str:
328 return f"Group({self.rhs!r})"
329
330 def __iter__(self) -> Iterator[Rhs]:
331 yield self.rhs
332
333
334 class ESC[4;38;5;81mCut:
335 def __init__(self) -> None:
336 pass
337
338 def __repr__(self) -> str:
339 return f"Cut()"
340
341 def __str__(self) -> str:
342 return f"~"
343
344 def __iter__(self) -> Iterator[Tuple[str, str]]:
345 if False:
346 yield
347
348 def __eq__(self, other: object) -> bool:
349 if not isinstance(other, Cut):
350 return NotImplemented
351 return True
352
353 def initial_names(self) -> AbstractSet[str]:
354 return set()
355
356
357 Plain = Union[Leaf, Group]
358 Item = Union[Plain, Opt, Repeat, Forced, Lookahead, Rhs, Cut]
359 RuleName = Tuple[str, str]
360 MetaTuple = Tuple[str, Optional[str]]
361 MetaList = List[MetaTuple]
362 RuleList = List[Rule]
363 NamedItemList = List[NamedItem]
364 LookaheadOrCut = Union[Lookahead, Cut]