jaclang 0.7.30__py3-none-any.whl → 0.7.31__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.

Potentially problematic release.


This version of jaclang might be problematic. Click here for more details.

@@ -5,8 +5,7 @@ from __future__ import annotations
5
5
  import keyword
6
6
  import logging
7
7
  import os
8
- from typing import Callable, TypeAlias
9
-
8
+ from typing import Callable, TypeAlias, TypeVar
10
9
 
11
10
  import jaclang.compiler.absyntree as ast
12
11
  from jaclang.compiler import jac_lark as jl # type: ignore
@@ -15,6 +14,9 @@ from jaclang.compiler.passes.ir_pass import Pass
15
14
  from jaclang.vendor.lark import Lark, Transformer, Tree, logger
16
15
 
17
16
 
17
+ T = TypeVar("T", bound=ast.AstNode)
18
+
19
+
18
20
  class JacParser(Pass):
19
21
  """Jac Parser."""
20
22
 
@@ -76,12 +78,12 @@ class JacParser(Pass):
76
78
  orig_src=mod.loc.orig_src,
77
79
  name=token.type,
78
80
  value=token.value,
79
- line=token.line if token.line is not None else 0,
80
- end_line=token.end_line if token.end_line is not None else 0,
81
- col_start=token.column if token.column is not None else 0,
82
- col_end=token.end_column if token.end_column is not None else 0,
83
- pos_start=token.start_pos if token.start_pos is not None else 0,
84
- pos_end=token.end_pos if token.end_pos is not None else 0,
81
+ line=token.line or 0,
82
+ end_line=token.end_line or 0,
83
+ col_start=token.column or 0,
84
+ col_end=token.end_column or 0,
85
+ pos_start=token.start_pos or 0,
86
+ pos_end=token.end_pos or 0,
85
87
  kid=[],
86
88
  )
87
89
 
@@ -130,6 +132,10 @@ class JacParser(Pass):
130
132
  super().__init__(*args, **kwargs)
131
133
  self.parse_ref = parser
132
134
  self.terminals: list[ast.Token] = []
135
+ # TODO: Once the kid is removed from the ast, we can get rid of this
136
+ # node_idx and directly pop(0) kid as we process the nodes.
137
+ self.node_idx = 0
138
+ self.cur_nodes: list[ast.AstNode] = []
133
139
 
134
140
  def ice(self) -> Exception:
135
141
  """Raise internal compiler error."""
@@ -138,32 +144,119 @@ class JacParser(Pass):
138
144
  f"{self.parse_ref.__class__.__name__} - Internal Compiler Error, Invalid Parse Tree!"
139
145
  )
140
146
 
141
- def nu(self, node: ast.T) -> ast.T:
142
- """Update node."""
147
+ def _node_update(self, node: T) -> T:
143
148
  self.parse_ref.cur_node = node
144
149
  if node not in self.parse_ref.node_list:
145
150
  self.parse_ref.node_list.append(node)
146
151
  return node
147
152
 
148
- def start(self, kid: list[ast.Module]) -> ast.Module:
153
+ def _call_userfunc(
154
+ self, tree: jl.Tree, new_children: None | list[ast.AstNode] = None
155
+ ) -> ast.AstNode:
156
+ self.cur_nodes = new_children or tree.children # type: ignore[assignment]
157
+ try:
158
+ return self._node_update(super()._call_userfunc(tree, new_children))
159
+ finally:
160
+ self.cur_nodes = []
161
+ self.node_idx = 0
162
+
163
+ def _call_userfunc_token(self, token: jl.Token) -> ast.AstNode:
164
+ return self._node_update(super()._call_userfunc_token(token))
165
+
166
+ def _binary_expr_unwind(self, kid: list[ast.AstNode]) -> ast.Expr:
167
+ """Binary expression helper."""
168
+ if len(kid) > 1:
169
+ if (
170
+ isinstance(kid[0], ast.Expr)
171
+ and isinstance(
172
+ kid[1],
173
+ (ast.Token, ast.DisconnectOp, ast.ConnectOp),
174
+ )
175
+ and isinstance(kid[2], ast.Expr)
176
+ ):
177
+ return ast.BinaryExpr(
178
+ left=kid[0],
179
+ op=kid[1],
180
+ right=kid[2],
181
+ kid=kid,
182
+ )
183
+ else:
184
+ raise self.ice()
185
+ elif isinstance(kid[0], ast.Expr):
186
+ return kid[0]
187
+ else:
188
+ raise self.ice()
189
+
190
+ # ******************************************************************* #
191
+ # Parser Helper functions. #
192
+ # ******************************************************************* #
193
+
194
+ def match(self, ty: type[T]) -> T | None:
195
+ """Return a node matching type 'ty' if possible from the current nodes."""
196
+ if (self.node_idx < len(self.cur_nodes)) and isinstance(
197
+ self.cur_nodes[self.node_idx], ty
198
+ ):
199
+ self.node_idx += 1
200
+ return self.cur_nodes[self.node_idx - 1] # type: ignore[return-value]
201
+ return None
202
+
203
+ def consume(self, ty: type[T]) -> T:
204
+ """Consume and return the specified type, if it's not exists, will be an internal compiler error."""
205
+ if node := self.match(ty):
206
+ return node
207
+ raise self.ice()
208
+
209
+ def match_token(self, tok: Tok) -> ast.Token | None:
210
+ """Match a token with the given type and return it."""
211
+ if token := self.match(ast.Token):
212
+ if token.name == tok.name:
213
+ return token
214
+ self.node_idx -= (
215
+ 1 # We're already matched but wrong token so undo matching it.
216
+ )
217
+ return None
218
+
219
+ def consume_token(self, tok: Tok) -> ast.Token:
220
+ """Consume a token with the given type and return it."""
221
+ if token := self.match_token(tok):
222
+ return token
223
+ raise self.ice()
224
+
225
+ def match_many(self, ty: type[T]) -> list[T]:
226
+ """Match 0 or more of the given type and return the list."""
227
+ nodes: list[ast.AstNode] = []
228
+ while node := self.match(ty):
229
+ nodes.append(node)
230
+ return nodes # type: ignore[return-value]
231
+
232
+ def consume_many(self, ty: type[T]) -> list[T]:
233
+ """Match 1 or more of the given type and return the list."""
234
+ nodes: list[ast.AstNode] = [self.consume(ty)]
235
+ while node := self.match(ty):
236
+ nodes.append(node)
237
+ return nodes # type: ignore[return-value]
238
+
239
+ # ******************************************************************* #
240
+ # Parsing Rules #
241
+ # ******************************************************************* #
242
+
243
+ def start(self, _: None) -> ast.Module:
149
244
  """Grammar rule.
150
245
 
151
246
  start: module
152
247
  """
153
- kid[0]._in_mod_nodes = self.parse_ref.node_list
154
- return self.nu(kid[0])
248
+ module = self.consume(ast.Module)
249
+ module._in_mod_nodes = self.parse_ref.node_list
250
+ return module
155
251
 
156
- def module(
157
- self, kid: list[ast.ElementStmt | ast.String | ast.EmptyToken]
158
- ) -> ast.Module:
252
+ def module(self, _: None) -> ast.Module:
159
253
  """Grammar rule.
160
254
 
161
- module: (doc_tag? element (element_with_doc | element)*)?
162
- doc_tag (element_with_doc (element_with_doc | element)*)?
255
+ module: (toplevel_stmt (tl_stmt_with_doc | toplevel_stmt)*)?
256
+ | STRING (tl_stmt_with_doc | toplevel_stmt)*
163
257
  """
164
- doc = kid[0] if len(kid) and isinstance(kid[0], ast.String) else None
165
- body = kid[1:] if doc else kid
166
- body = [i for i in body if isinstance(i, ast.ElementStmt)]
258
+ doc = self.match(ast.String)
259
+ body = self.match_many(ast.ElementStmt)
167
260
  mod = ast.Module(
168
261
  name=self.parse_ref.mod_path.split(os.path.sep)[-1].rstrip(".jac"),
169
262
  source=self.parse_ref.source,
@@ -172,28 +265,24 @@ class JacParser(Pass):
172
265
  is_imported=False,
173
266
  terminals=self.terminals,
174
267
  kid=(
175
- kid
176
- if len(kid)
177
- else [ast.EmptyToken(ast.JacSource("", self.parse_ref.mod_path))]
268
+ self.cur_nodes
269
+ or [ast.EmptyToken(ast.JacSource("", self.parse_ref.mod_path))]
178
270
  ),
179
271
  )
180
- return self.nu(mod)
272
+ return mod
181
273
 
182
- def element_with_doc(
183
- self, kid: list[ast.ElementStmt | ast.String]
184
- ) -> ast.ElementStmt:
274
+ def tl_stmt_with_doc(self, _: None) -> ast.ElementStmt:
185
275
  """Grammar rule.
186
276
 
187
- element_with_doc: doc_tag element
277
+ tl_stmt_with_doc: doc_tag toplevel_stmt
188
278
  """
189
- if isinstance(kid[1], ast.ElementStmt) and isinstance(kid[0], ast.String):
190
- kid[1].doc = kid[0]
191
- kid[1].add_kids_left([kid[0]])
192
- return self.nu(kid[1])
193
- else:
194
- raise self.ice()
279
+ doc = self.consume(ast.String)
280
+ element = self.consume(ast.ElementStmt)
281
+ element.doc = doc
282
+ element.add_kids_left([doc])
283
+ return element
195
284
 
196
- def element(self, kid: list[ast.AstNode]) -> ast.ElementStmt:
285
+ def toplevel_stmt(self, _: None) -> ast.ElementStmt:
197
286
  """Grammar rule.
198
287
 
199
288
  element: py_code_block
@@ -204,270 +293,219 @@ class JacParser(Pass):
204
293
  | test
205
294
  | global_var
206
295
  """
207
- if isinstance(kid[0], ast.ElementStmt):
208
- return self.nu(kid[0])
209
- else:
210
- raise self.ice()
296
+ return self.consume(ast.ElementStmt)
211
297
 
212
- def global_var(self, kid: list[ast.AstNode]) -> ast.GlobalVars:
298
+ def global_var(self, _: None) -> ast.GlobalVars:
213
299
  """Grammar rule.
214
300
 
215
301
  global_var: (KW_LET | KW_GLOBAL) access_tag? assignment_list SEMI
216
302
  """
217
- is_frozen = isinstance(kid[0], ast.Token) and kid[0].name == Tok.KW_LET
218
- access = kid[1] if isinstance(kid[1], ast.SubTag) else None
219
- assignments = kid[2] if access else kid[1]
220
- if isinstance(assignments, ast.SubNodeList):
221
- return self.nu(
222
- ast.GlobalVars(
223
- access=access,
224
- assignments=assignments,
225
- is_frozen=is_frozen,
226
- kid=kid,
227
- )
228
- )
229
- else:
230
- raise self.ice()
303
+ is_frozen = self.consume(ast.Token).name == Tok.KW_LET
304
+ access_tag = self.match(ast.SubTag)
305
+ assignments = self.consume(ast.SubNodeList)
306
+ return ast.GlobalVars(
307
+ access=access_tag,
308
+ assignments=assignments,
309
+ is_frozen=is_frozen,
310
+ kid=self.cur_nodes,
311
+ )
231
312
 
232
- def access_tag(self, kid: list[ast.AstNode]) -> ast.SubTag[ast.Token]:
313
+ def access_tag(self, _: None) -> ast.SubTag[ast.Token]:
233
314
  """Grammar rule.
234
315
 
235
316
  access_tag: COLON ( KW_PROT | KW_PUB | KW_PRIV )
236
317
  """
237
- if isinstance(kid[0], ast.Token) and isinstance(kid[1], ast.Token):
238
- return self.nu(
239
- ast.SubTag[ast.Token](
240
- tag=kid[1],
241
- kid=kid,
242
- )
243
- )
244
- else:
245
- raise self.ice()
318
+ self.consume_token(Tok.COLON)
319
+ access = self.consume(ast.Token)
320
+ return ast.SubTag[ast.Token](tag=access, kid=self.cur_nodes)
246
321
 
247
- def test(self, kid: list[ast.AstNode]) -> ast.Test:
322
+ def test(self, _: None) -> ast.Test:
248
323
  """Grammar rule.
249
324
 
250
325
  test: KW_TEST NAME? code_block
251
326
  """
252
- name = kid[1] if isinstance(kid[1], ast.Name) else kid[0]
253
- codeblock = kid[2] if name != kid[0] else kid[1]
254
- if isinstance(codeblock, ast.SubNodeList) and isinstance(
255
- name, (ast.Name, ast.Token)
256
- ):
257
- return self.nu(
258
- ast.Test(
259
- name=name,
260
- body=codeblock,
261
- kid=kid,
262
- )
263
- )
264
- else:
265
- raise self.ice()
327
+ # Q(thakee): Why the name should be KW_TEST if no name present?
328
+ test_tok = self.consume_token(Tok.KW_TEST)
329
+ name = self.match(ast.Name) or test_tok
330
+ codeblock = self.consume(ast.SubNodeList)
331
+ return ast.Test(
332
+ name=name,
333
+ body=codeblock,
334
+ kid=self.cur_nodes,
335
+ )
266
336
 
267
- def free_code(self, kid: list[ast.AstNode]) -> ast.ModuleCode:
337
+ def free_code(self, _: None) -> ast.ModuleCode:
268
338
  """Grammar rule.
269
339
 
270
340
  free_code: KW_WITH KW_ENTRY sub_name? code_block
271
341
  """
272
- name = kid[2] if isinstance(kid[2], ast.SubTag) else None
273
- codeblock = kid[3] if name else kid[2]
274
- if isinstance(codeblock, ast.SubNodeList):
275
- return self.nu(
276
- ast.ModuleCode(
277
- name=name,
278
- body=codeblock,
279
- kid=kid,
280
- )
281
- )
282
- else:
283
- raise self.ice()
284
-
285
- def doc_tag(self, kid: list[ast.AstNode]) -> ast.String:
286
- """Grammar rule.
287
-
288
- doc_tag: ( STRING | DOC_STRING )
289
- """
290
- if isinstance(kid[0], ast.String):
291
- return self.nu(kid[0])
292
- else:
293
- raise self.ice()
342
+ self.consume_token(Tok.KW_WITH)
343
+ self.consume_token(Tok.KW_ENTRY)
344
+ name = self.match(ast.SubTag)
345
+ codeblock = self.consume(ast.SubNodeList)
346
+ return ast.ModuleCode(
347
+ name=name,
348
+ body=codeblock,
349
+ kid=self.cur_nodes,
350
+ )
294
351
 
295
- def py_code_block(self, kid: list[ast.AstNode]) -> ast.PyInlineCode:
352
+ def py_code_block(self, _: None) -> ast.PyInlineCode:
296
353
  """Grammar rule.
297
354
 
298
355
  py_code_block: PYNLINE
299
356
  """
300
- if isinstance(kid[0], ast.Token):
301
- return self.nu(
302
- ast.PyInlineCode(
303
- code=kid[0],
304
- kid=kid,
305
- )
306
- )
307
- else:
308
- raise self.ice()
357
+ pyinline = self.consume_token(Tok.PYNLINE)
358
+ return ast.PyInlineCode(
359
+ code=pyinline,
360
+ kid=self.cur_nodes,
361
+ )
309
362
 
310
- def import_stmt(self, kid: list[ast.AstNode]) -> ast.Import:
363
+ def import_stmt(self, _: None) -> ast.Import:
311
364
  """Grammar rule.
312
365
 
313
366
  import_stmt: KW_IMPORT sub_name? KW_FROM from_path LBRACE import_items RBRACE
314
- | KW_IMPORT sub_name? KW_FROM from_path COMMA import_items SEMI //Deprecated
315
- | KW_IMPORT sub_name? import_path (COMMA import_path)* SEMI
316
- | include_stmt
367
+ | KW_IMPORT sub_name? KW_FROM from_path COMMA import_items SEMI //Deprecated
368
+ | KW_IMPORT sub_name? import_path (COMMA import_path)* SEMI
369
+ | include_stmt
317
370
  """
318
- if len(kid) == 1 and isinstance(kid[0], ast.Import):
319
- return self.nu(kid[0])
320
- chomp = [*kid]
321
- lang = kid[1] if isinstance(kid[1], ast.SubTag) else None
322
- chomp = chomp[2:] if lang else chomp[1:]
323
- from_path = chomp[1] if isinstance(chomp[1], ast.ModulePath) else None
324
- if from_path:
325
- items = kid[-2] if isinstance(kid[-2], ast.SubNodeList) else None
371
+ if import_stmt := self.match(ast.Import): # Include Statement.
372
+ return import_stmt
373
+
374
+ # TODO: kid will be removed so let's keep as it is for now.
375
+ kid = self.cur_nodes
376
+
377
+ from_path: ast.ModulePath | None = None
378
+ self.consume_token(Tok.KW_IMPORT)
379
+ lang = self.match(ast.SubTag)
380
+
381
+ if self.match_token(Tok.KW_FROM):
382
+ from_path = self.consume(ast.ModulePath)
383
+ self.consume(ast.Token) # LBRACE or COMMA
384
+ items = self.consume(ast.SubNodeList)
385
+ if self.consume(ast.Token).name == Tok.SEMI: # RBRACE or SEMI
386
+ self.parse_ref.warning(
387
+ "Deprecated syntax, use braces for multiple imports (e.g, import from mymod {a, b, c})",
388
+ )
326
389
  else:
327
- paths = [i for i in kid if isinstance(i, ast.ModulePath)]
390
+ paths = [self.consume(ast.ModulePath)]
391
+ while self.match_token(Tok.COMMA):
392
+ paths.append(self.consume(ast.ModulePath))
393
+ self.consume_token(Tok.SEMI)
328
394
  items = ast.SubNodeList[ast.ModulePath](
329
- items=paths, delim=Tok.COMMA, kid=kid[2 if lang else 1 : -1]
395
+ items=paths,
396
+ delim=Tok.COMMA,
397
+ # TODO: kid will be removed so let's keep as it is for now.
398
+ kid=self.cur_nodes[2 if lang else 1 : -1],
330
399
  )
331
400
  kid = (kid[:2] if lang else kid[:1]) + [items] + kid[-1:]
332
401
 
333
402
  is_absorb = False
334
- if isinstance(items, ast.SubNodeList):
335
- ret = self.nu(
336
- ast.Import(
337
- hint=lang,
338
- from_loc=from_path,
339
- items=items,
340
- is_absorb=is_absorb,
341
- kid=kid,
342
- )
343
- )
344
- if (
345
- from_path
346
- and isinstance(kid[-1], ast.Token)
347
- and kid[-1].name == Tok.SEMI
348
- ):
349
- self.parse_ref.warning(
350
- "Deprecated syntax, use braces for multiple imports (e.g, import from mymod {a, b, c})",
351
- )
352
- return ret
353
- else:
354
- raise self.ice()
403
+ return ast.Import(
404
+ hint=lang,
405
+ from_loc=from_path,
406
+ items=items,
407
+ is_absorb=is_absorb,
408
+ kid=kid,
409
+ )
355
410
 
356
- def from_path(self, kid: list[ast.AstNode]) -> ast.ModulePath:
411
+ def from_path(self, _: None) -> ast.ModulePath:
357
412
  """Grammar rule.
358
413
 
359
414
  from_path: (DOT | ELLIPSIS)* import_path
360
- | (DOT | ELLIPSIS)+
415
+ | (DOT | ELLIPSIS)+
361
416
  """
362
417
  level = 0
363
- for i in kid:
364
- if isinstance(i, ast.Token):
365
- if i.name == Tok.DOT:
366
- level += 1
367
- elif i.name == Tok.ELLIPSIS:
368
- level += 3
369
- if isinstance(kid[-1], ast.ModulePath):
370
- ret = kid[-1]
371
- adds = [i for i in kid if isinstance(i, ast.Token)]
372
- ret.level = level
373
- ret.add_kids_left(adds)
374
- return ret
375
- else:
376
- return self.nu(
377
- ast.ModulePath(
378
- path=None,
379
- level=level,
380
- alias=None,
381
- kid=kid,
382
- )
383
- )
418
+ while True:
419
+ if self.match_token(Tok.DOT):
420
+ level += 1
421
+ elif self.match_token(Tok.ELLIPSIS):
422
+ level += 3
423
+ else:
424
+ break
425
+ if import_path := self.match(ast.ModulePath):
426
+ kids = [i for i in self.cur_nodes if isinstance(i, ast.Token)]
427
+ import_path.level = level
428
+ import_path.add_kids_left(kids)
429
+ return import_path
384
430
 
385
- def include_stmt(self, kid: list[ast.AstNode]) -> ast.Import:
431
+ return ast.ModulePath(
432
+ path=None,
433
+ level=level,
434
+ alias=None,
435
+ kid=self.cur_nodes,
436
+ )
437
+
438
+ def include_stmt(self, _: None) -> ast.Import:
386
439
  """Grammar rule.
387
440
 
388
- include_stmt: KW_INCLUDE sub_name import_path SEMI
441
+ include_stmt: KW_INCLUDE sub_name? import_path SEMI
389
442
  """
390
- lang = kid[1] if isinstance(kid[1], ast.SubTag) else None
391
- from_path = kid[2] if lang else kid[1]
392
- if not isinstance(from_path, ast.ModulePath):
393
- raise self.ice()
443
+ kid = self.cur_nodes # TODO: Will be removed.
444
+ self.consume_token(Tok.KW_INCLUDE)
445
+ lang = self.match(ast.SubTag)
446
+ from_path = self.consume(ast.ModulePath)
394
447
  items = ast.SubNodeList[ast.ModulePath](
395
448
  items=[from_path], delim=Tok.COMMA, kid=[from_path]
396
449
  )
397
- kid = (kid[:2] if lang else kid[:1]) + [items] + kid[-1:]
450
+ kid = (
451
+ (kid[:2] if lang else kid[:1]) + [items] + kid[-1:]
452
+ ) # TODO: Will be removed.
398
453
  is_absorb = True
399
- return self.nu(
400
- ast.Import(
401
- hint=lang,
402
- from_loc=None,
403
- items=items,
404
- is_absorb=is_absorb,
405
- kid=kid,
406
- )
454
+ return ast.Import(
455
+ hint=lang,
456
+ from_loc=None,
457
+ items=items,
458
+ is_absorb=is_absorb,
459
+ kid=kid,
407
460
  )
408
461
 
409
- def import_path(self, kid: list[ast.AstNode]) -> ast.ModulePath:
462
+ def import_path(self, _: None) -> ast.ModulePath:
410
463
  """Grammar rule.
411
464
 
412
465
  import_path: named_ref (DOT named_ref)* (KW_AS NAME)?
413
466
  """
414
- valid_path = [i for i in kid if isinstance(i, ast.Name)]
415
- alias = (
416
- kid[-1]
417
- if len(kid) > 2
418
- and isinstance(kid[-1], ast.Name)
419
- and isinstance(kid[-2], ast.Token)
420
- and kid[-2].name == Tok.KW_AS
421
- else None
467
+ valid_path = [self.consume(ast.Name)]
468
+ while self.match_token(Tok.DOT):
469
+ valid_path.append(self.consume(ast.Name))
470
+ alias = self.consume(ast.Name) if self.match_token(Tok.KW_AS) else None
471
+ return ast.ModulePath(
472
+ path=valid_path,
473
+ level=0,
474
+ alias=alias,
475
+ kid=self.cur_nodes,
422
476
  )
423
- if alias is not None:
424
- valid_path = valid_path[:-1]
425
477
 
426
- return self.nu(
427
- ast.ModulePath(
428
- path=valid_path,
429
- level=0,
430
- alias=alias,
431
- kid=kid,
432
- )
433
- )
434
-
435
- def import_items(
436
- self, kid: list[ast.AstNode]
437
- ) -> ast.SubNodeList[ast.ModuleItem]:
478
+ def import_items(self, _: None) -> ast.SubNodeList[ast.ModuleItem]:
438
479
  """Grammar rule.
439
480
 
440
481
  import_items: (import_item COMMA)* import_item COMMA?
441
482
  """
483
+ items = [self.consume(ast.ModuleItem)]
484
+ while self.match_token(Tok.COMMA):
485
+ if module_item := self.match(ast.ModuleItem):
486
+ items.append(module_item)
442
487
  ret = ast.SubNodeList[ast.ModuleItem](
443
- items=[i for i in kid if isinstance(i, ast.ModuleItem)],
488
+ items=items,
444
489
  delim=Tok.COMMA,
445
- kid=kid,
490
+ kid=self.cur_nodes,
446
491
  )
447
- return self.nu(ret)
492
+ return ret
448
493
 
449
- def import_item(self, kid: list[ast.AstNode]) -> ast.ModuleItem:
494
+ def import_item(self, _: None) -> ast.ModuleItem:
450
495
  """Grammar rule.
451
496
 
452
497
  import_item: named_ref (KW_AS NAME)?
453
498
  """
454
- name = kid[0]
455
- alias = kid[2] if len(kid) > 1 else None
456
- if isinstance(name, ast.Name) and (
457
- alias is None or isinstance(alias, ast.Name)
458
- ):
459
- return self.nu(
460
- ast.ModuleItem(
461
- name=name,
462
- alias=alias,
463
- kid=kid,
464
- )
465
- )
466
- else:
467
- raise self.ice()
499
+ name = self.consume(ast.Name)
500
+ alias = self.consume(ast.Name) if self.match_token(Tok.KW_AS) else None
501
+ return ast.ModuleItem(
502
+ name=name,
503
+ alias=alias,
504
+ kid=self.cur_nodes,
505
+ )
468
506
 
469
507
  def architype(
470
- self, kid: list[ast.AstNode]
508
+ self, _: None
471
509
  ) -> ast.ArchSpec | ast.ArchDef | ast.Enum | ast.EnumDef:
472
510
  """Grammar rule.
473
511
 
@@ -475,52 +513,49 @@ class JacParser(Pass):
475
513
  | architype_def
476
514
  | enum
477
515
  """
478
- if isinstance(kid[0], ast.SubNodeList):
479
- if isinstance(kid[1], ast.ArchSpec):
480
- kid[1].decorators = kid[0]
481
- kid[1].add_kids_left([kid[0]])
482
- return self.nu(kid[1])
483
- else:
484
- raise self.ice()
516
+ archspec: ast.ArchSpec | ast.ArchDef | ast.Enum | ast.EnumDef | None = None
485
517
 
486
- elif isinstance(kid[0], (ast.ArchSpec, ast.ArchDef, ast.Enum, ast.EnumDef)):
487
- return self.nu(kid[0])
518
+ decorators = self.match(ast.SubNodeList)
519
+ if decorators is not None:
520
+ archspec = self.consume(ast.ArchSpec)
521
+ archspec.decorators = decorators
522
+ archspec.add_kids_left([decorators])
488
523
  else:
489
- raise self.ice()
524
+ archspec = (
525
+ self.match(ast.ArchSpec)
526
+ or self.match(ast.ArchDef)
527
+ or self.match(ast.Enum)
528
+ or self.consume(ast.EnumDef)
529
+ )
530
+ return archspec
490
531
 
491
- def architype_decl(self, kid: list[ast.AstNode]) -> ast.ArchSpec:
532
+ def architype_decl(self, _: None) -> ast.ArchSpec:
492
533
  """Grammar rule.
493
534
 
494
535
  architype_decl: arch_type access_tag? STRING? NAME inherited_archs? (member_block | SEMI)
495
536
  """
496
- arch_type = kid[0]
497
- access = kid[1] if isinstance(kid[1], ast.SubTag) else None
498
- semstr = (
499
- kid[2]
500
- if (access and isinstance(kid[2], ast.String))
501
- else kid[1] if isinstance(kid[1], ast.String) else None
537
+ arch_type = self.consume(ast.Token)
538
+ access = self.match(ast.SubTag)
539
+ semstr = self.match(ast.String)
540
+ name = self.consume(ast.Name)
541
+ sub_list1 = self.match(ast.SubNodeList)
542
+ sub_list2 = self.match(ast.SubNodeList)
543
+ if self.match_token(Tok.SEMI):
544
+ inh, body = sub_list1, None
545
+ else:
546
+ body = (
547
+ sub_list2 or sub_list1
548
+ ) # if sub_list2 is None then body is sub_list1
549
+ inh = sub_list2 and sub_list1 # if sub_list2 is None then inh is None.
550
+ return ast.Architype(
551
+ arch_type=arch_type,
552
+ name=name,
553
+ semstr=semstr,
554
+ access=access,
555
+ base_classes=inh,
556
+ body=body,
557
+ kid=self.cur_nodes,
502
558
  )
503
- name = (
504
- kid[3]
505
- if (access and semstr)
506
- else kid[2] if (access or semstr) else kid[1]
507
- )
508
- inh = kid[-2] if isinstance(kid[-2], ast.SubNodeList) else None
509
- body = kid[-1] if isinstance(kid[-1], ast.SubNodeList) else None
510
- if isinstance(arch_type, ast.Token) and isinstance(name, ast.Name):
511
- return self.nu(
512
- ast.Architype(
513
- arch_type=arch_type,
514
- name=name,
515
- semstr=semstr,
516
- access=access,
517
- base_classes=inh,
518
- body=body,
519
- kid=kid,
520
- )
521
- )
522
- else:
523
- raise self.ice()
524
559
 
525
560
  def architype_def(self, kid: list[ast.AstNode]) -> ast.ArchDef:
526
561
  """Grammar rule.
@@ -530,12 +565,10 @@ class JacParser(Pass):
530
565
  if isinstance(kid[0], ast.ArchRefChain) and isinstance(
531
566
  kid[1], ast.SubNodeList
532
567
  ):
533
- return self.nu(
534
- ast.ArchDef(
535
- target=kid[0],
536
- body=kid[1],
537
- kid=kid,
538
- )
568
+ return ast.ArchDef(
569
+ target=kid[0],
570
+ body=kid[1],
571
+ kid=kid,
539
572
  )
540
573
  else:
541
574
  raise self.ice()
@@ -549,7 +582,7 @@ class JacParser(Pass):
549
582
  | KW_NODE
550
583
  """
551
584
  if isinstance(kid[0], ast.Token):
552
- return self.nu(kid[0])
585
+ return kid[0]
553
586
  else:
554
587
  raise self.ice()
555
588
 
@@ -560,12 +593,10 @@ class JacParser(Pass):
560
593
  """
561
594
  valid_decors = [i for i in kid if isinstance(i, ast.Expr)]
562
595
  if len(valid_decors) == len(kid) / 2:
563
- return self.nu(
564
- ast.SubNodeList[ast.Expr](
565
- items=valid_decors,
566
- delim=Tok.DECOR_OP,
567
- kid=kid,
568
- )
596
+ return ast.SubNodeList[ast.Expr](
597
+ items=valid_decors,
598
+ delim=Tok.DECOR_OP,
599
+ kid=kid,
569
600
  )
570
601
  else:
571
602
  raise self.ice()
@@ -577,12 +608,10 @@ class JacParser(Pass):
577
608
  | COLON (atomic_chain COMMA)* atomic_chain COLON
578
609
  """
579
610
  valid_inh = [i for i in kid if isinstance(i, ast.Expr)]
580
- return self.nu(
581
- ast.SubNodeList[ast.Expr](
582
- items=valid_inh,
583
- delim=Tok.COMMA,
584
- kid=kid,
585
- )
611
+ return ast.SubNodeList[ast.Expr](
612
+ items=valid_inh,
613
+ delim=Tok.COMMA,
614
+ kid=kid,
586
615
  )
587
616
 
588
617
  def sub_name(self, kid: list[ast.AstNode]) -> ast.SubTag[ast.Name]:
@@ -591,11 +620,9 @@ class JacParser(Pass):
591
620
  sub_name: COLON NAME
592
621
  """
593
622
  if isinstance(kid[1], ast.Name):
594
- return self.nu(
595
- ast.SubTag[ast.Name](
596
- tag=kid[1],
597
- kid=kid,
598
- )
623
+ return ast.SubTag[ast.Name](
624
+ tag=kid[1],
625
+ kid=kid,
599
626
  )
600
627
  else:
601
628
  raise self.ice()
@@ -608,7 +635,7 @@ class JacParser(Pass):
608
635
  | NAME
609
636
  """
610
637
  if isinstance(kid[0], ast.NameAtom):
611
- return self.nu(kid[0])
638
+ return kid[0]
612
639
  else:
613
640
  raise self.ice()
614
641
 
@@ -623,60 +650,47 @@ class JacParser(Pass):
623
650
  | KW_HERE
624
651
  """
625
652
  if isinstance(kid[0], ast.Name):
626
- return self.nu(ast.SpecialVarRef(var=kid[0]))
653
+ return ast.SpecialVarRef(var=kid[0])
627
654
  else:
628
655
  raise self.ice()
629
656
 
630
- def enum(self, kid: list[ast.AstNode]) -> ast.Enum | ast.EnumDef:
657
+ def enum(self, _: None) -> ast.Enum | ast.EnumDef:
631
658
  """Grammar rule.
632
659
 
633
660
  enum: decorators? enum_decl
634
661
  | enum_def
635
662
  """
636
- if isinstance(kid[0], ast.SubNodeList):
637
- if isinstance(kid[1], ast.Enum):
638
- kid[1].decorators = kid[0]
639
- kid[1].add_kids_left([kid[0]])
640
- return self.nu(kid[1])
641
- else:
642
- raise self.ice()
643
- elif isinstance(kid[0], (ast.Enum, ast.EnumDef)):
644
- return self.nu(kid[0])
645
- else:
646
-
647
- raise self.ice()
663
+ if decorator := self.match(ast.SubNodeList):
664
+ enum_decl = self.consume(ast.Enum)
665
+ enum_decl.decorators = decorator
666
+ enum_decl.add_kids_left([decorator])
667
+ return enum_decl
668
+ return self.match(ast.Enum) or self.consume(ast.EnumDef)
648
669
 
649
- def enum_decl(self, kid: list[ast.AstNode]) -> ast.Enum:
670
+ def enum_decl(self, _: None) -> ast.Enum:
650
671
  """Grammar rule.
651
672
 
652
673
  enum_decl: KW_ENUM access_tag? STRING? NAME inherited_archs? (enum_block | SEMI)
653
674
  """
654
- access = kid[1] if isinstance(kid[1], ast.SubTag) else None
655
- semstr = (
656
- kid[2]
657
- if (access and isinstance(kid[2], ast.String))
658
- else kid[1] if isinstance(kid[1], ast.String) else None
675
+ self.consume_token(Tok.KW_ENUM)
676
+ access = self.match(ast.SubTag)
677
+ semstr = self.match(ast.String)
678
+ name = self.consume(ast.Name)
679
+ sub_list1 = self.match(ast.SubNodeList)
680
+ sub_list2 = self.match(ast.SubNodeList)
681
+ if self.match_token(Tok.SEMI):
682
+ inh, body = sub_list1, None
683
+ else:
684
+ body = sub_list2 or sub_list1
685
+ inh = sub_list2 and sub_list1
686
+ return ast.Enum(
687
+ semstr=semstr,
688
+ name=name,
689
+ access=access,
690
+ base_classes=inh,
691
+ body=body,
692
+ kid=self.cur_nodes,
659
693
  )
660
- name = (
661
- kid[3]
662
- if (access and semstr)
663
- else kid[2] if (access or semstr) else kid[1]
664
- )
665
- inh = kid[-2] if isinstance(kid[-2], ast.SubNodeList) else None
666
- body = kid[-1] if isinstance(kid[-1], ast.SubNodeList) else None
667
- if isinstance(name, ast.Name):
668
- return self.nu(
669
- ast.Enum(
670
- semstr=semstr,
671
- name=name,
672
- access=access,
673
- base_classes=inh,
674
- body=body,
675
- kid=kid,
676
- )
677
- )
678
- else:
679
- raise self.ice()
680
694
 
681
695
  def enum_def(self, kid: list[ast.AstNode]) -> ast.EnumDef:
682
696
  """Grammar rule.
@@ -686,12 +700,10 @@ class JacParser(Pass):
686
700
  if isinstance(kid[0], ast.ArchRefChain) and isinstance(
687
701
  kid[1], ast.SubNodeList
688
702
  ):
689
- return self.nu(
690
- ast.EnumDef(
691
- target=kid[0],
692
- body=kid[1],
693
- kid=kid,
694
- )
703
+ return ast.EnumDef(
704
+ target=kid[0],
705
+ body=kid[1],
706
+ kid=kid,
695
707
  )
696
708
  else:
697
709
  raise self.ice()
@@ -705,9 +717,9 @@ class JacParser(Pass):
705
717
  """
706
718
  ret = ast.SubNodeList[ast.EnumBlockStmt](items=[], delim=Tok.COMMA, kid=kid)
707
719
  ret.items = [i for i in kid if isinstance(i, ast.EnumBlockStmt)]
708
- return self.nu(ret)
720
+ return ret
709
721
 
710
- def enum_stmt(self, kid: list[ast.AstNode]) -> ast.EnumBlockStmt:
722
+ def enum_stmt(self, _: None) -> ast.EnumBlockStmt:
711
723
  """Grammar rule.
712
724
 
713
725
  enum_stmt: NAME (COLON STRING)? EQ expression
@@ -717,81 +729,43 @@ class JacParser(Pass):
717
729
  | abstract_ability
718
730
  | ability
719
731
  """
720
- if isinstance(kid[0], (ast.PyInlineCode, ast.Ability)):
721
- return self.nu(kid[0])
722
- elif isinstance(kid[0], (ast.Name)):
723
- if (
724
- len(kid) >= 3
725
- and isinstance(kid[-1], ast.Expr)
726
- and not isinstance(kid[-1], ast.String)
727
- ):
728
- semstr = (
729
- kid[2]
730
- if len(kid) > 3 and isinstance(kid[2], ast.String)
731
- else None
732
- )
733
- targ = ast.SubNodeList[ast.Expr](
734
- items=[kid[0]], delim=Tok.COMMA, kid=[kid[0]]
735
- )
736
- kid[0] = targ
737
- return self.nu(
738
- ast.Assignment(
739
- target=targ,
740
- value=kid[-1],
741
- type_tag=None,
742
- kid=kid,
743
- semstr=semstr,
744
- is_enum_stmt=True,
745
- )
746
- )
747
- else:
748
- semstr = (
749
- kid[2]
750
- if len(kid) == 3 and isinstance(kid[2], ast.String)
751
- else None
752
- )
753
- targ = ast.SubNodeList[ast.Expr](
754
- items=[kid[0]], delim=Tok.COMMA, kid=[kid[0]]
755
- )
756
- kid[0] = targ
757
- return self.nu(
758
- ast.Assignment(
759
- target=targ,
760
- value=None,
761
- type_tag=None,
762
- kid=kid,
763
- semstr=semstr,
764
- is_enum_stmt=True,
765
- )
766
- )
767
- elif isinstance(kid[0], (ast.PyInlineCode, ast.ModuleCode)):
768
- return self.nu(kid[0])
769
- raise self.ice()
770
-
771
- def ability(
772
- self, kid: list[ast.AstNode]
773
- ) -> ast.Ability | ast.AbilityDef | ast.FuncCall:
732
+ if stmt := (
733
+ self.match(ast.PyInlineCode)
734
+ or self.match(ast.ModuleCode)
735
+ or self.match(ast.Ability)
736
+ ):
737
+ return stmt
738
+ name = self.consume(ast.Name)
739
+ semstr = self.consume(ast.String) if self.match_token(Tok.COLON) else None
740
+ expr = self.consume(ast.Expr) if self.match_token(Tok.EQ) else None
741
+ targ = ast.SubNodeList[ast.Expr](items=[name], delim=Tok.COMMA, kid=[name])
742
+ self.cur_nodes[0] = targ
743
+ return ast.Assignment(
744
+ target=targ,
745
+ value=expr,
746
+ type_tag=None,
747
+ kid=self.cur_nodes,
748
+ semstr=semstr,
749
+ is_enum_stmt=True,
750
+ )
751
+
752
+ def ability(self, _: None) -> ast.Ability | ast.AbilityDef | ast.FuncCall:
774
753
  """Grammer rule.
775
754
 
776
755
  ability: decorators? KW_ASYNC? ability_decl
777
756
  | decorators? genai_ability
778
757
  | ability_def
779
758
  """
780
- chomp = [*kid]
781
- decorators = chomp[0] if isinstance(chomp[0], ast.SubNodeList) else None
782
- chomp = chomp[1:] if decorators else chomp
783
- is_async = (
784
- chomp[0]
785
- if isinstance(chomp[0], ast.Token) and chomp[0].name == Tok.KW_ASYNC
786
- else None
787
- )
788
- ability = chomp[1] if is_async else chomp[0]
789
- if not isinstance(ability, (ast.Ability, ast.AbilityDef)):
790
- raise self.ice()
791
- if is_async and isinstance(ability, ast.Ability):
759
+ ability: ast.Ability | ast.AbilityDef | None = None
760
+ decorators = self.match(ast.SubNodeList)
761
+ is_async = self.match_token(Tok.KW_ASYNC)
762
+ ability = self.match(ast.Ability)
763
+ if is_async and ability:
792
764
  ability.is_async = True
793
765
  ability.add_kids_left([is_async])
794
- if isinstance(decorators, ast.SubNodeList):
766
+ if ability is None:
767
+ ability = self.consume(ast.AbilityDef)
768
+ if decorators:
795
769
  for dec in decorators.items:
796
770
  if (
797
771
  isinstance(dec, ast.NameAtom)
@@ -801,55 +775,43 @@ class JacParser(Pass):
801
775
  ability.is_static = True
802
776
  decorators.items.remove(dec) # noqa: B038
803
777
  break
804
- if len(decorators.items):
778
+ if decorators.items:
805
779
  ability.decorators = decorators
806
780
  ability.add_kids_left([decorators])
807
- return self.nu(ability)
808
- return self.nu(ability)
781
+ return ability
782
+ return ability
809
783
 
810
- def ability_decl(self, kid: list[ast.AstNode]) -> ast.Ability:
784
+ def ability_decl(self, _: None) -> ast.Ability:
811
785
  """Grammar rule.
812
786
 
813
787
  ability_decl: KW_OVERRIDE? KW_STATIC? KW_CAN access_tag? STRING?
814
788
  named_ref (func_decl | event_clause) (code_block | SEMI)
815
789
  """
816
- chomp = [*kid]
817
- is_override = (
818
- isinstance(chomp[0], ast.Token) and chomp[0].name == Tok.KW_OVERRIDE
819
- )
820
- chomp = chomp[1:] if is_override else chomp
821
- is_static = (
822
- isinstance(chomp[0], ast.Token) and chomp[0].name == Tok.KW_STATIC
790
+ signature: ast.FuncSignature | ast.EventSignature | None = None
791
+ body: ast.SubNodeList | None = None
792
+ is_override = self.match_token(Tok.KW_OVERRIDE) is not None
793
+ is_static = self.match_token(Tok.KW_STATIC) is not None
794
+ self.consume_token(Tok.KW_CAN)
795
+ access = self.match(ast.SubTag)
796
+ semstr = self.match(ast.String)
797
+ name = self.consume(ast.NameAtom)
798
+ signature = self.match(ast.FuncSignature) or self.consume(
799
+ ast.EventSignature
800
+ )
801
+ if (body := self.match(ast.SubNodeList)) is None:
802
+ self.consume_token(Tok.SEMI)
803
+ return ast.Ability(
804
+ name_ref=name,
805
+ is_async=False,
806
+ is_override=is_override,
807
+ is_static=is_static,
808
+ is_abstract=False,
809
+ access=access,
810
+ semstr=semstr,
811
+ signature=signature,
812
+ body=body,
813
+ kid=self.cur_nodes,
823
814
  )
824
- chomp = chomp[2:] if is_static else chomp[1:]
825
- access = chomp[0] if isinstance(chomp[0], ast.SubTag) else None
826
- chomp = chomp[1:] if access else chomp
827
- semstr = chomp[0] if isinstance(chomp[0], ast.String) else None
828
- chomp = chomp[1:] if semstr else chomp
829
- name = chomp[0]
830
- chomp = chomp[1:]
831
- signature = chomp[0]
832
- chomp = chomp[1:]
833
- body = chomp[0] if isinstance(chomp[0], ast.SubNodeList) else None
834
- if isinstance(name, ast.NameAtom) and isinstance(
835
- signature, (ast.FuncSignature, ast.EventSignature)
836
- ):
837
- return self.nu(
838
- ast.Ability(
839
- name_ref=name,
840
- is_async=False,
841
- is_override=is_override,
842
- is_static=is_static,
843
- is_abstract=False,
844
- access=access,
845
- semstr=semstr,
846
- signature=signature,
847
- body=body,
848
- kid=kid,
849
- )
850
- )
851
- else:
852
- raise self.ice()
853
815
 
854
816
  def ability_def(self, kid: list[ast.AstNode]) -> ast.AbilityDef:
855
817
  """Grammar rule.
@@ -861,137 +823,99 @@ class JacParser(Pass):
861
823
  and isinstance(kid[1], (ast.FuncSignature, ast.EventSignature))
862
824
  and isinstance(kid[2], ast.SubNodeList)
863
825
  ):
864
- return self.nu(
865
- ast.AbilityDef(
866
- target=kid[0],
867
- signature=kid[1],
868
- body=kid[2],
869
- kid=kid,
870
- )
826
+ return ast.AbilityDef(
827
+ target=kid[0],
828
+ signature=kid[1],
829
+ body=kid[2],
830
+ kid=kid,
871
831
  )
872
832
  else:
873
833
  raise self.ice()
874
834
 
875
835
  # We need separate production rule for abstract_ability because we don't
876
836
  # want to allow regular abilities outside of classed to be abstract.
877
- def abstract_ability(self, kid: list[ast.AstNode]) -> ast.Ability:
837
+ def abstract_ability(self, _: None) -> ast.Ability:
878
838
  """Grammar rule.
879
839
 
880
840
  abstract_ability: KW_OVERRIDE? KW_STATIC? KW_CAN access_tag? STRING?
881
841
  named_ref (func_decl | event_clause) KW_ABSTRACT SEMI
882
842
  """
883
- chomp = [*kid]
884
- is_override = (
885
- isinstance(chomp[0], ast.Token) and chomp[0].name == Tok.KW_OVERRIDE
886
- )
887
- chomp = chomp[1:] if is_override else chomp
888
- is_static = (
889
- isinstance(chomp[0], ast.Token) and chomp[0].name == Tok.KW_STATIC
890
- )
891
- chomp = chomp[1:] if is_static else chomp
892
- chomp = chomp[1:]
893
- access = chomp[0] if isinstance(chomp[0], ast.SubTag) else None
894
- chomp = chomp[1:] if access else chomp
895
- semstr = chomp[0] if isinstance(chomp[0], ast.String) else None
896
- chomp = chomp[1:] if semstr else chomp
897
- name = chomp[0]
898
- chomp = chomp[1:]
899
- signature = chomp[0]
900
- chomp = chomp[1:]
901
- if isinstance(name, ast.NameAtom) and isinstance(
902
- signature, (ast.FuncSignature, ast.EventSignature)
903
- ):
904
- return self.nu(
905
- ast.Ability(
906
- name_ref=name,
907
- is_async=False,
908
- is_override=is_override,
909
- is_static=is_static,
910
- is_abstract=True,
911
- access=access,
912
- semstr=semstr,
913
- signature=signature,
914
- body=None,
915
- kid=kid,
916
- )
917
- )
918
- else:
919
- raise self.ice()
920
-
921
- def genai_ability(self, kid: list[ast.AstNode]) -> ast.Ability:
843
+ signature: ast.FuncSignature | ast.EventSignature | None = None
844
+ is_override = self.match_token(Tok.KW_OVERRIDE) is not None
845
+ is_static = self.match_token(Tok.KW_STATIC) is not None
846
+ self.consume_token(Tok.KW_CAN)
847
+ access = self.match(ast.SubTag)
848
+ semstr = self.match(ast.String)
849
+ name = self.consume(ast.NameAtom)
850
+ signature = self.match(ast.FuncSignature) or self.consume(
851
+ ast.EventSignature
852
+ )
853
+ self.consume_token(Tok.KW_ABSTRACT)
854
+ self.consume_token(Tok.SEMI)
855
+ return ast.Ability(
856
+ name_ref=name,
857
+ is_async=False,
858
+ is_override=is_override,
859
+ is_static=is_static,
860
+ is_abstract=True,
861
+ access=access,
862
+ semstr=semstr,
863
+ signature=signature,
864
+ body=None,
865
+ kid=self.cur_nodes,
866
+ )
867
+
868
+ def genai_ability(self, _: None) -> ast.Ability:
922
869
  """Grammar rule.
923
870
 
924
871
  genai_ability: KW_OVERRIDE? KW_STATIC? KW_CAN access_tag? STRING?
925
872
  named_ref (func_decl) KW_BY atomic_call SEMI
926
873
  """
927
- chomp = [*kid]
928
- is_override = (
929
- isinstance(chomp[0], ast.Token) and chomp[0].name == Tok.KW_OVERRIDE
930
- )
931
- chomp = chomp[1:] if is_override else chomp
932
- is_static = (
933
- isinstance(chomp[0], ast.Token) and chomp[0].name == Tok.KW_STATIC
874
+ is_override = self.match_token(Tok.KW_OVERRIDE) is not None
875
+ is_static = self.match_token(Tok.KW_STATIC) is not None
876
+ self.consume_token(Tok.KW_CAN)
877
+ access = self.match(ast.SubTag)
878
+ semstr = self.match(ast.String)
879
+ name = self.consume(ast.NameAtom)
880
+ signature = self.match(ast.FuncSignature) or self.consume(
881
+ ast.EventSignature
882
+ )
883
+ self.consume_token(Tok.KW_BY)
884
+ body = self.consume(ast.FuncCall)
885
+ self.consume_token(Tok.SEMI)
886
+ return ast.Ability(
887
+ name_ref=name,
888
+ is_async=False,
889
+ is_override=is_override,
890
+ is_static=is_static,
891
+ is_abstract=False,
892
+ access=access,
893
+ semstr=semstr,
894
+ signature=signature,
895
+ body=body,
896
+ kid=self.cur_nodes,
934
897
  )
935
- chomp = chomp[1:] if is_static else chomp
936
- chomp = chomp[1:]
937
- access = chomp[0] if isinstance(chomp[0], ast.SubTag) else None
938
- chomp = chomp[1:] if access else chomp
939
- semstr = chomp[0] if isinstance(chomp[0], ast.String) else None
940
- chomp = chomp[1:] if semstr else chomp
941
- name = chomp[0]
942
- chomp = chomp[1:]
943
- signature = chomp[0]
944
- chomp = chomp[1:]
945
- has_by = isinstance(chomp[0], ast.Token) and chomp[0].name == Tok.KW_BY
946
- chomp = chomp[1:] if has_by else chomp
947
- if (
948
- isinstance(name, ast.NameAtom)
949
- and isinstance(signature, (ast.FuncSignature, ast.EventSignature))
950
- and isinstance(chomp[0], ast.FuncCall)
951
- and has_by
952
- ):
953
- return self.nu(
954
- ast.Ability(
955
- name_ref=name,
956
- is_async=False,
957
- is_override=is_override,
958
- is_static=is_static,
959
- is_abstract=False,
960
- access=access,
961
- semstr=semstr,
962
- signature=signature,
963
- body=chomp[0],
964
- kid=kid,
965
- )
966
- )
967
- else:
968
- raise self.ice()
969
898
 
970
- def event_clause(self, kid: list[ast.AstNode]) -> ast.EventSignature:
899
+ def event_clause(self, _: None) -> ast.EventSignature:
971
900
  """Grammar rule.
972
901
 
973
902
  event_clause: KW_WITH expression? (KW_EXIT | KW_ENTRY) (STRING? RETURN_HINT expression)?
974
903
  """
975
- type_specs = kid[1] if isinstance(kid[1], ast.Expr) else None
976
- return_spec = kid[-1] if isinstance(kid[-1], ast.Expr) else None
977
- semstr = (
978
- kid[-3] if return_spec and isinstance(kid[-3], ast.String) else None
904
+ return_spec: ast.Expr | None = None
905
+ semstr: ast.String | None = None
906
+ self.consume_token(Tok.KW_WITH)
907
+ type_specs = self.match(ast.Expr)
908
+ event = self.match_token(Tok.KW_EXIT) or self.consume_token(Tok.KW_ENTRY)
909
+ if semstr := self.match(ast.String):
910
+ self.consume_token(Tok.RETURN_HINT)
911
+ return_spec = self.consume(ast.Expr)
912
+ return ast.EventSignature(
913
+ semstr=semstr,
914
+ event=event,
915
+ arch_tag_info=type_specs,
916
+ return_type=return_spec,
917
+ kid=self.cur_nodes,
979
918
  )
980
- event = kid[2] if type_specs else kid[1]
981
- if isinstance(event, ast.Token) and (
982
- isinstance(return_spec, ast.Expr) or return_spec is None
983
- ):
984
- return self.nu(
985
- ast.EventSignature(
986
- semstr=semstr,
987
- event=event,
988
- arch_tag_info=type_specs,
989
- return_type=return_spec,
990
- kid=kid,
991
- )
992
- )
993
- else:
994
- raise self.ice()
995
919
 
996
920
  def func_decl(self, kid: list[ast.AstNode]) -> ast.FuncSignature:
997
921
  """Grammar rule.
@@ -1012,21 +936,17 @@ class JacParser(Pass):
1012
936
  if (isinstance(params, ast.SubNodeList) or params is None) and (
1013
937
  isinstance(return_spec, ast.Expr) or return_spec is None
1014
938
  ):
1015
- return self.nu(
1016
- ast.FuncSignature(
1017
- semstr=semstr,
1018
- params=params,
1019
- return_type=return_spec,
1020
- kid=(
1021
- kid
1022
- if len(kid)
1023
- else [
1024
- ast.EmptyToken(
1025
- ast.JacSource("", self.parse_ref.mod_path)
1026
- )
1027
- ]
1028
- ),
1029
- )
939
+ return ast.FuncSignature(
940
+ semstr=semstr,
941
+ params=params,
942
+ return_type=return_spec,
943
+ kid=(
944
+ kid
945
+ if len(kid)
946
+ else [
947
+ ast.EmptyToken(ast.JacSource("", self.parse_ref.mod_path))
948
+ ]
949
+ ),
1030
950
  )
1031
951
  else:
1032
952
  raise self.ice()
@@ -1043,7 +963,7 @@ class JacParser(Pass):
1043
963
  delim=Tok.COMMA,
1044
964
  kid=kid,
1045
965
  )
1046
- return self.nu(ret)
966
+ return ret
1047
967
 
1048
968
  def param_var(self, kid: list[ast.AstNode]) -> ast.ParamVar:
1049
969
  """Grammar rule.
@@ -1074,15 +994,13 @@ class JacParser(Pass):
1074
994
  )
1075
995
  )
1076
996
  if isinstance(name, ast.Name) and isinstance(type_tag, ast.SubTag):
1077
- return self.nu(
1078
- ast.ParamVar(
1079
- semstr=semstr,
1080
- name=name,
1081
- type_tag=type_tag,
1082
- value=value,
1083
- unpack=star,
1084
- kid=kid,
1085
- )
997
+ return ast.ParamVar(
998
+ semstr=semstr,
999
+ name=name,
1000
+ type_tag=type_tag,
1001
+ value=value,
1002
+ unpack=star,
1003
+ kid=kid,
1086
1004
  )
1087
1005
  else:
1088
1006
  raise self.ice()
@@ -1102,7 +1020,7 @@ class JacParser(Pass):
1102
1020
  ret.items = [i for i in kid if isinstance(i, ast.ArchBlockStmt)]
1103
1021
  ret.left_enc = kid[0] if isinstance(kid[0], ast.Token) else None
1104
1022
  ret.right_enc = kid[-1] if isinstance(kid[-1], ast.Token) else None
1105
- return self.nu(ret)
1023
+ return ret
1106
1024
 
1107
1025
  def member_stmt(self, kid: list[ast.AstNode]) -> ast.ArchBlockStmt:
1108
1026
  """Grammar rule.
@@ -1114,7 +1032,7 @@ class JacParser(Pass):
1114
1032
  | doc_tag? has_stmt
1115
1033
  """
1116
1034
  if isinstance(kid[0], ast.ArchBlockStmt):
1117
- ret = self.nu(kid[0])
1035
+ ret = kid[0]
1118
1036
  elif (
1119
1037
  isinstance(kid[1], ast.ArchBlockStmt)
1120
1038
  and isinstance(kid[1], ast.AstDocNode)
@@ -1122,7 +1040,7 @@ class JacParser(Pass):
1122
1040
  ):
1123
1041
  kid[1].doc = kid[0]
1124
1042
  kid[1].add_kids_left([kid[0]])
1125
- ret = self.nu(kid[1])
1043
+ ret = kid[1]
1126
1044
  else:
1127
1045
  raise self.ice()
1128
1046
  if isinstance(ret, ast.Ability):
@@ -1145,14 +1063,12 @@ class JacParser(Pass):
1145
1063
  chomp = chomp[1:] if access else chomp
1146
1064
  assign = chomp[0]
1147
1065
  if isinstance(assign, ast.SubNodeList):
1148
- return self.nu(
1149
- ast.ArchHas(
1150
- vars=assign,
1151
- is_static=is_static,
1152
- is_frozen=is_freeze,
1153
- access=access,
1154
- kid=kid,
1155
- )
1066
+ return ast.ArchHas(
1067
+ vars=assign,
1068
+ is_static=is_static,
1069
+ is_frozen=is_freeze,
1070
+ access=access,
1071
+ kid=kid,
1156
1072
  )
1157
1073
  else:
1158
1074
  raise self.ice()
@@ -1176,12 +1092,10 @@ class JacParser(Pass):
1176
1092
  assign = kid[0]
1177
1093
  new_kid = [assign]
1178
1094
  valid_kid = [i for i in new_kid if isinstance(i, ast.HasVar)]
1179
- return self.nu(
1180
- ast.SubNodeList[ast.HasVar](
1181
- items=valid_kid,
1182
- delim=Tok.COMMA,
1183
- kid=new_kid,
1184
- )
1095
+ return ast.SubNodeList[ast.HasVar](
1096
+ items=valid_kid,
1097
+ delim=Tok.COMMA,
1098
+ kid=new_kid,
1185
1099
  )
1186
1100
 
1187
1101
  def typed_has_clause(self, kid: list[ast.AstNode]) -> ast.HasVar:
@@ -1195,35 +1109,27 @@ class JacParser(Pass):
1195
1109
  defer = isinstance(kid[-1], ast.Token) and kid[-1].name == Tok.KW_POST_INIT
1196
1110
  value = kid[-1] if not defer and isinstance(kid[-1], ast.Expr) else None
1197
1111
  if isinstance(name, ast.Name) and isinstance(type_tag, ast.SubTag):
1198
- return self.nu(
1199
- ast.HasVar(
1200
- semstr=semstr,
1201
- name=name,
1202
- type_tag=type_tag,
1203
- defer=defer,
1204
- value=value,
1205
- kid=kid,
1206
- )
1112
+ return ast.HasVar(
1113
+ semstr=semstr,
1114
+ name=name,
1115
+ type_tag=type_tag,
1116
+ defer=defer,
1117
+ value=value,
1118
+ kid=kid,
1207
1119
  )
1208
1120
  else:
1209
1121
  raise self.ice()
1210
1122
 
1211
- def type_tag(self, kid: list[ast.AstNode]) -> ast.SubTag[ast.Expr]:
1123
+ def type_tag(self, _: None) -> ast.SubTag[ast.Expr]:
1212
1124
  """Grammar rule.
1213
1125
 
1214
1126
  type_tag: COLON expression
1215
1127
  """
1216
- if isinstance(kid[1], ast.Expr):
1217
- return self.nu(
1218
- ast.SubTag[ast.Expr](
1219
- tag=kid[1],
1220
- kid=kid,
1221
- )
1222
- )
1223
- else:
1224
- raise self.ice()
1128
+ self.consume_token(Tok.COLON)
1129
+ tag = self.consume(ast.Expr)
1130
+ return ast.SubTag[ast.Expr](tag=tag, kid=self.cur_nodes)
1225
1131
 
1226
- def builtin_type(self, kid: list[ast.AstNode]) -> ast.Token:
1132
+ def builtin_type(self, _: None) -> ast.Token:
1227
1133
  """Grammar rule.
1228
1134
 
1229
1135
  builtin_type: TYP_TYPE
@@ -1238,22 +1144,18 @@ class JacParser(Pass):
1238
1144
  | TYP_BYTES
1239
1145
  | TYP_STRING
1240
1146
  """
1241
- if isinstance(kid[0], ast.Token):
1242
- return self.nu(
1243
- ast.BuiltinType(
1244
- name=kid[0].name,
1245
- orig_src=self.parse_ref.source,
1246
- value=kid[0].value,
1247
- line=kid[0].loc.first_line,
1248
- end_line=kid[0].loc.last_line,
1249
- col_start=kid[0].loc.col_start,
1250
- col_end=kid[0].loc.col_end,
1251
- pos_start=kid[0].pos_start,
1252
- pos_end=kid[0].pos_end,
1253
- )
1254
- )
1255
- else:
1256
- raise self.ice()
1147
+ token = self.consume(ast.Token)
1148
+ return ast.BuiltinType(
1149
+ name=token.name,
1150
+ orig_src=self.parse_ref.source,
1151
+ value=token.value,
1152
+ line=token.loc.first_line,
1153
+ end_line=token.loc.last_line,
1154
+ col_start=token.loc.col_start,
1155
+ col_end=token.loc.col_end,
1156
+ pos_start=token.pos_start,
1157
+ pos_end=token.pos_end,
1158
+ )
1257
1159
 
1258
1160
  def code_block(
1259
1161
  self, kid: list[ast.AstNode]
@@ -1266,14 +1168,12 @@ class JacParser(Pass):
1266
1168
  right_enc = kid[-1] if isinstance(kid[-1], ast.Token) else None
1267
1169
  valid_stmt = [i for i in kid if isinstance(i, ast.CodeBlockStmt)]
1268
1170
  if len(valid_stmt) == len(kid) - 2:
1269
- return self.nu(
1270
- ast.SubNodeList[ast.CodeBlockStmt](
1271
- items=valid_stmt,
1272
- delim=Tok.WS,
1273
- left_enc=left_enc,
1274
- right_enc=right_enc,
1275
- kid=kid,
1276
- )
1171
+ return ast.SubNodeList[ast.CodeBlockStmt](
1172
+ items=valid_stmt,
1173
+ delim=Tok.WS,
1174
+ left_enc=left_enc,
1175
+ right_enc=right_enc,
1176
+ kid=kid,
1277
1177
  )
1278
1178
  else:
1279
1179
  raise self.ice()
@@ -1308,7 +1208,7 @@ class JacParser(Pass):
1308
1208
  | SEMI
1309
1209
  """
1310
1210
  if isinstance(kid[0], ast.CodeBlockStmt) and len(kid) < 2:
1311
- return self.nu(kid[0])
1211
+ return kid[0]
1312
1212
  elif isinstance(kid[0], ast.Token) and kid[0].name == Tok.KW_YIELD:
1313
1213
  return ast.ExprStmt(
1314
1214
  expr=(
@@ -1329,7 +1229,7 @@ class JacParser(Pass):
1329
1229
  )
1330
1230
  elif isinstance(kid[0], ast.CodeBlockStmt):
1331
1231
  kid[0].add_kids_right([kid[1]])
1332
- return self.nu(kid[0])
1232
+ return kid[0]
1333
1233
  else:
1334
1234
  raise self.ice()
1335
1235
 
@@ -1339,294 +1239,215 @@ class JacParser(Pass):
1339
1239
  typed_ctx_block: RETURN_HINT expression code_block
1340
1240
  """
1341
1241
  if isinstance(kid[1], ast.Expr) and isinstance(kid[2], ast.SubNodeList):
1342
- return self.nu(
1343
- ast.TypedCtxBlock(
1344
- type_ctx=kid[1],
1345
- body=kid[2],
1346
- kid=kid,
1347
- )
1242
+ return ast.TypedCtxBlock(
1243
+ type_ctx=kid[1],
1244
+ body=kid[2],
1245
+ kid=kid,
1348
1246
  )
1349
1247
  else:
1350
1248
  raise self.ice()
1351
1249
 
1352
- def if_stmt(self, kid: list[ast.AstNode]) -> ast.IfStmt:
1250
+ def if_stmt(self, _: None) -> ast.IfStmt:
1353
1251
  """Grammar rule.
1354
1252
 
1355
1253
  if_stmt: KW_IF expression code_block (elif_stmt | else_stmt)?
1356
1254
  """
1357
- if isinstance(kid[1], ast.Expr) and isinstance(kid[2], ast.SubNodeList):
1358
- return self.nu(
1359
- ast.IfStmt(
1360
- condition=kid[1],
1361
- body=kid[2],
1362
- else_body=(
1363
- kid[3]
1364
- if len(kid) > 3
1365
- and isinstance(kid[3], (ast.ElseStmt, ast.ElseIf))
1366
- else None
1367
- ),
1368
- kid=kid,
1369
- )
1370
- )
1371
- else:
1372
- raise self.ice()
1255
+ self.consume_token(Tok.KW_IF)
1256
+ condition = self.consume(ast.Expr)
1257
+ body = self.consume(ast.SubNodeList)
1258
+ else_body = self.match(ast.ElseStmt) or self.match(ast.ElseIf)
1259
+ return ast.IfStmt(
1260
+ condition=condition,
1261
+ body=body,
1262
+ else_body=else_body,
1263
+ kid=self.cur_nodes,
1264
+ )
1373
1265
 
1374
- def elif_stmt(self, kid: list[ast.AstNode]) -> ast.ElseIf:
1266
+ def elif_stmt(self, _: None) -> ast.ElseIf:
1375
1267
  """Grammar rule.
1376
1268
 
1377
1269
  elif_stmt: KW_ELIF expression code_block (elif_stmt | else_stmt)?
1378
1270
  """
1379
- if isinstance(kid[1], ast.Expr) and isinstance(kid[2], ast.SubNodeList):
1380
- return self.nu(
1381
- ast.ElseIf(
1382
- condition=kid[1],
1383
- body=kid[2],
1384
- else_body=(
1385
- kid[3]
1386
- if len(kid) > 3
1387
- and isinstance(kid[3], (ast.ElseStmt, ast.ElseIf))
1388
- else None
1389
- ),
1390
- kid=kid,
1391
- )
1392
- )
1393
- else:
1394
- raise self.ice()
1271
+ self.consume_token(Tok.KW_ELIF)
1272
+ condition = self.consume(ast.Expr)
1273
+ body = self.consume(ast.SubNodeList)
1274
+ else_body = self.match(ast.ElseStmt) or self.match(ast.ElseIf)
1275
+ return ast.ElseIf(
1276
+ condition=condition,
1277
+ body=body,
1278
+ else_body=else_body,
1279
+ kid=self.cur_nodes,
1280
+ )
1395
1281
 
1396
- def else_stmt(self, kid: list[ast.AstNode]) -> ast.ElseStmt:
1282
+ def else_stmt(self, _: None) -> ast.ElseStmt:
1397
1283
  """Grammar rule.
1398
1284
 
1399
1285
  else_stmt: KW_ELSE code_block
1400
1286
  """
1401
- if isinstance(kid[1], ast.SubNodeList):
1402
- return self.nu(
1403
- ast.ElseStmt(
1404
- body=kid[1],
1405
- kid=kid,
1406
- )
1407
- )
1408
- else:
1409
- raise self.ice()
1287
+ self.consume_token(Tok.KW_ELSE)
1288
+ body = self.consume(ast.SubNodeList)
1289
+ return ast.ElseStmt(
1290
+ body=body,
1291
+ kid=self.cur_nodes,
1292
+ )
1410
1293
 
1411
- def try_stmt(self, kid: list[ast.AstNode]) -> ast.TryStmt:
1294
+ def try_stmt(self, _: None) -> ast.TryStmt:
1412
1295
  """Grammar rule.
1413
1296
 
1414
1297
  try_stmt: KW_TRY code_block except_list? else_stmt? finally_stmt?
1415
1298
  """
1416
- chomp = [*kid][1:]
1417
- block = chomp[0]
1418
- chomp = chomp[1:]
1419
- except_list = (
1420
- chomp[0]
1421
- if len(chomp) and isinstance(chomp[0], ast.SubNodeList)
1422
- else None
1423
- )
1424
- chomp = chomp[1:] if except_list else chomp
1425
- else_stmt = (
1426
- chomp[0] if len(chomp) and isinstance(chomp[0], ast.ElseStmt) else None
1299
+ self.consume_token(Tok.KW_TRY)
1300
+ block = self.consume(ast.SubNodeList)
1301
+ except_list = self.match(ast.SubNodeList)
1302
+ else_stmt = self.match(ast.ElseStmt)
1303
+ finally_stmt = self.match(ast.FinallyStmt)
1304
+ return ast.TryStmt(
1305
+ body=block,
1306
+ excepts=except_list,
1307
+ else_body=else_stmt,
1308
+ finally_body=finally_stmt,
1309
+ kid=self.cur_nodes,
1427
1310
  )
1428
- chomp = chomp[1:] if else_stmt else chomp
1429
- finally_stmt = (
1430
- chomp[0]
1431
- if len(chomp) and isinstance(chomp[0], ast.FinallyStmt)
1432
- else None
1433
- )
1434
- if isinstance(block, ast.SubNodeList):
1435
- return self.nu(
1436
- ast.TryStmt(
1437
- body=block,
1438
- excepts=except_list,
1439
- else_body=else_stmt,
1440
- finally_body=finally_stmt,
1441
- kid=kid,
1442
- )
1443
- )
1444
- else:
1445
- raise self.ice()
1446
1311
 
1447
- def except_list(self, kid: list[ast.AstNode]) -> ast.SubNodeList[ast.Except]:
1312
+ def except_list(self, _: None) -> ast.SubNodeList[ast.Except]:
1448
1313
  """Grammar rule.
1449
1314
 
1450
1315
  except_list: except_def+
1451
1316
  """
1452
- valid_kid = [i for i in kid if isinstance(i, ast.Except)]
1453
- if len(valid_kid) == len(kid):
1454
- return self.nu(
1455
- ast.SubNodeList[ast.Except](
1456
- items=valid_kid,
1457
- delim=Tok.WS,
1458
- kid=kid,
1459
- )
1460
- )
1461
- else:
1462
- raise self.ice()
1317
+ items = [self.consume(ast.Except)]
1318
+ while expt := self.match(ast.Except):
1319
+ items.append(expt)
1320
+ return ast.SubNodeList[ast.Except](
1321
+ items=items,
1322
+ delim=Tok.WS,
1323
+ kid=self.cur_nodes,
1324
+ )
1463
1325
 
1464
- def except_def(self, kid: list[ast.AstNode]) -> ast.Except:
1326
+ def except_def(self, _: None) -> ast.Except:
1465
1327
  """Grammar rule.
1466
1328
 
1467
1329
  except_def: KW_EXCEPT expression (KW_AS NAME)? code_block
1468
1330
  """
1469
- ex_type = kid[1]
1470
- name = kid[3] if len(kid) > 3 and isinstance(kid[3], ast.Name) else None
1471
- body = kid[-1]
1472
- if isinstance(ex_type, ast.Expr) and isinstance(body, ast.SubNodeList):
1473
- return self.nu(
1474
- ast.Except(
1475
- ex_type=ex_type,
1476
- name=name,
1477
- body=body,
1478
- kid=kid,
1479
- )
1480
- )
1481
- else:
1482
- raise self.ice()
1331
+ name: ast.Name | None = None
1332
+ self.consume_token(Tok.KW_EXCEPT)
1333
+ ex_type = self.consume(ast.Expr)
1334
+ if self.match_token(Tok.KW_AS):
1335
+ name = self.consume(ast.Name)
1336
+ body = self.consume(ast.SubNodeList)
1337
+ return ast.Except(
1338
+ ex_type=ex_type,
1339
+ name=name,
1340
+ body=body,
1341
+ kid=self.cur_nodes,
1342
+ )
1483
1343
 
1484
- def finally_stmt(self, kid: list[ast.AstNode]) -> ast.FinallyStmt:
1344
+ def finally_stmt(self, _: None) -> ast.FinallyStmt:
1485
1345
  """Grammar rule.
1486
1346
 
1487
1347
  finally_stmt: KW_FINALLY code_block
1488
1348
  """
1489
- if isinstance(kid[1], ast.SubNodeList):
1490
- return self.nu(
1491
- ast.FinallyStmt(
1492
- body=kid[1],
1493
- kid=kid,
1494
- )
1495
- )
1496
- else:
1497
- raise self.ice()
1349
+ self.consume_token(Tok.KW_FINALLY)
1350
+ body = self.consume(ast.SubNodeList)
1351
+ return ast.FinallyStmt(
1352
+ body=body,
1353
+ kid=self.cur_nodes,
1354
+ )
1498
1355
 
1499
- def for_stmt(self, kid: list[ast.AstNode]) -> ast.IterForStmt | ast.InForStmt:
1356
+ def for_stmt(self, _: None) -> ast.IterForStmt | ast.InForStmt:
1500
1357
  """Grammar rule.
1501
1358
 
1502
1359
  for_stmt: KW_ASYNC? KW_FOR assignment KW_TO expression KW_BY
1503
1360
  expression code_block else_stmt?
1504
1361
  | KW_ASYNC? KW_FOR expression KW_IN expression code_block else_stmt?
1505
1362
  """
1506
- chomp = [*kid]
1507
- is_async = bool(
1508
- isinstance(chomp[0], ast.Token) and chomp[0].name == Tok.KW_ASYNC
1363
+ is_async = bool(self.match_token(Tok.KW_ASYNC))
1364
+ self.consume_token(Tok.KW_FOR)
1365
+ if iter := self.match(ast.Assignment):
1366
+ self.consume_token(Tok.KW_TO)
1367
+ condition = self.consume(ast.Expr)
1368
+ self.consume_token(Tok.KW_BY)
1369
+ count_by = self.consume(ast.Assignment)
1370
+ body = self.consume(ast.SubNodeList)
1371
+ else_body = self.match(ast.ElseStmt)
1372
+ return ast.IterForStmt(
1373
+ is_async=is_async,
1374
+ iter=iter,
1375
+ condition=condition,
1376
+ count_by=count_by,
1377
+ body=body,
1378
+ else_body=else_body,
1379
+ kid=self.cur_nodes,
1380
+ )
1381
+ target = self.consume(ast.Expr)
1382
+ self.consume_token(Tok.KW_IN)
1383
+ collection = self.consume(ast.Expr)
1384
+ body = self.consume(ast.SubNodeList)
1385
+ else_body = self.match(ast.ElseStmt)
1386
+ return ast.InForStmt(
1387
+ is_async=is_async,
1388
+ target=target,
1389
+ collection=collection,
1390
+ body=body,
1391
+ else_body=else_body,
1392
+ kid=self.cur_nodes,
1509
1393
  )
1510
- chomp = chomp[1:] if is_async else chomp
1511
- if isinstance(chomp[1], ast.Assignment):
1512
- if (
1513
- isinstance(chomp[3], ast.Expr)
1514
- and isinstance(chomp[5], ast.Assignment)
1515
- and isinstance(chomp[6], ast.SubNodeList)
1516
- ):
1517
- return self.nu(
1518
- ast.IterForStmt(
1519
- is_async=is_async,
1520
- iter=chomp[1],
1521
- condition=chomp[3],
1522
- count_by=chomp[5],
1523
- body=chomp[6],
1524
- else_body=(
1525
- chomp[-1]
1526
- if isinstance(chomp[-1], ast.ElseStmt)
1527
- else None
1528
- ),
1529
- kid=kid,
1530
- )
1531
- )
1532
- else:
1533
- raise self.ice()
1534
- elif isinstance(chomp[1], ast.Expr):
1535
- if isinstance(chomp[3], ast.Expr) and isinstance(
1536
- chomp[4], ast.SubNodeList
1537
- ):
1538
- return self.nu(
1539
- ast.InForStmt(
1540
- is_async=is_async,
1541
- target=chomp[1],
1542
- collection=chomp[3],
1543
- body=chomp[4],
1544
- else_body=(
1545
- chomp[-1]
1546
- if isinstance(chomp[-1], ast.ElseStmt)
1547
- else None
1548
- ),
1549
- kid=kid,
1550
- )
1551
- )
1552
- else:
1553
- raise self.ice()
1554
- else:
1555
- raise self.ice()
1556
1394
 
1557
- def while_stmt(self, kid: list[ast.AstNode]) -> ast.WhileStmt:
1395
+ def while_stmt(self, _: None) -> ast.WhileStmt:
1558
1396
  """Grammar rule.
1559
1397
 
1560
1398
  while_stmt: KW_WHILE expression code_block
1561
1399
  """
1562
- if isinstance(kid[1], ast.Expr) and isinstance(kid[2], ast.SubNodeList):
1563
- return self.nu(
1564
- ast.WhileStmt(
1565
- condition=kid[1],
1566
- body=kid[2],
1567
- kid=kid,
1568
- )
1569
- )
1570
- else:
1571
- raise self.ice()
1400
+ self.consume_token(Tok.KW_WHILE)
1401
+ condition = self.consume(ast.Expr)
1402
+ body = self.consume(ast.SubNodeList)
1403
+ return ast.WhileStmt(
1404
+ condition=condition,
1405
+ body=body,
1406
+ kid=self.cur_nodes,
1407
+ )
1572
1408
 
1573
- def with_stmt(self, kid: list[ast.AstNode]) -> ast.WithStmt:
1409
+ def with_stmt(self, _: None) -> ast.WithStmt:
1574
1410
  """Grammar rule.
1575
1411
 
1576
- with_stmt: KW_ASYNC? KW_WITH expr_as_list code_block
1577
- """
1578
- chomp = [*kid]
1579
- is_async = bool(
1580
- isinstance(chomp[0], ast.Token) and chomp[0].name == Tok.KW_ASYNC
1581
- )
1582
- chomp = chomp[1:] if is_async else chomp
1583
- if isinstance(chomp[1], ast.SubNodeList) and isinstance(
1584
- chomp[2], ast.SubNodeList
1585
- ):
1586
- return self.nu(
1587
- ast.WithStmt(
1588
- is_async=is_async,
1589
- exprs=chomp[1],
1590
- body=chomp[2],
1591
- kid=kid,
1592
- )
1593
- )
1594
- else:
1595
- raise self.ice()
1412
+ with_stmt: KW_ASYNC? KW_WITH expr_as_list code_block
1413
+ """
1414
+ is_async = bool(self.match_token(Tok.KW_ASYNC))
1415
+ self.consume_token(Tok.KW_WITH)
1416
+ exprs = self.consume(ast.SubNodeList)
1417
+ body = self.consume(ast.SubNodeList)
1418
+ return ast.WithStmt(
1419
+ is_async=is_async,
1420
+ exprs=exprs,
1421
+ body=body,
1422
+ kid=self.cur_nodes,
1423
+ )
1596
1424
 
1597
- def expr_as_list(
1598
- self, kid: list[ast.AstNode]
1599
- ) -> ast.SubNodeList[ast.ExprAsItem]:
1425
+ def expr_as_list(self, _: None) -> ast.SubNodeList[ast.ExprAsItem]:
1600
1426
  """Grammar rule.
1601
1427
 
1602
1428
  expr_as_list: (expr_as COMMA)* expr_as
1603
1429
  """
1604
- ret = ast.SubNodeList[ast.ExprAsItem](
1605
- items=[i for i in kid if isinstance(i, ast.ExprAsItem)],
1430
+ items = [self.consume(ast.ExprAsItem)]
1431
+ while self.match_token(Tok.COMMA):
1432
+ items.append(self.consume(ast.ExprAsItem))
1433
+ return ast.SubNodeList[ast.ExprAsItem](
1434
+ items=items,
1606
1435
  delim=Tok.COMMA,
1607
- kid=kid,
1436
+ kid=self.cur_nodes,
1608
1437
  )
1609
- return self.nu(ret)
1610
1438
 
1611
- def expr_as(self, kid: list[ast.AstNode]) -> ast.ExprAsItem:
1439
+ def expr_as(self, _: None) -> ast.ExprAsItem:
1612
1440
  """Grammar rule.
1613
1441
 
1614
1442
  expr_as: expression (KW_AS expression)?
1615
1443
  """
1616
- expr = kid[0]
1617
- alias = kid[2] if len(kid) > 1 else None
1618
- if isinstance(expr, ast.Expr) and (
1619
- alias is None or isinstance(alias, ast.Expr)
1620
- ):
1621
- return self.nu(
1622
- ast.ExprAsItem(
1623
- expr=expr,
1624
- alias=alias,
1625
- kid=kid,
1626
- )
1627
- )
1628
- else:
1629
- raise self.ice()
1444
+ expr = self.consume(ast.Expr)
1445
+ alias = self.consume(ast.Expr) if self.match_token(Tok.KW_AS) else None
1446
+ return ast.ExprAsItem(
1447
+ expr=expr,
1448
+ alias=alias,
1449
+ kid=self.cur_nodes,
1450
+ )
1630
1451
 
1631
1452
  def raise_stmt(self, kid: list[ast.AstNode]) -> ast.RaiseStmt:
1632
1453
  """Grammar rule.
@@ -1639,113 +1460,90 @@ class JacParser(Pass):
1639
1460
  )
1640
1461
  chomp = chomp[2:] if e_type and len(chomp) > 1 else chomp[1:]
1641
1462
  e = chomp[0] if len(chomp) > 0 and isinstance(chomp[0], ast.Expr) else None
1642
- return self.nu(
1643
- ast.RaiseStmt(
1644
- cause=e_type,
1645
- from_target=e,
1646
- kid=kid,
1647
- )
1463
+ return ast.RaiseStmt(
1464
+ cause=e_type,
1465
+ from_target=e,
1466
+ kid=kid,
1648
1467
  )
1649
1468
 
1650
- def assert_stmt(self, kid: list[ast.AstNode]) -> ast.AssertStmt:
1469
+ def assert_stmt(self, _: None) -> ast.AssertStmt:
1651
1470
  """Grammar rule.
1652
1471
 
1653
1472
  assert_stmt: KW_ASSERT expression (COMMA expression)?
1654
1473
  """
1655
- condition = kid[1]
1656
- error_msg = kid[3] if len(kid) > 3 else None
1657
- if isinstance(condition, ast.Expr):
1658
- return self.nu(
1659
- ast.AssertStmt(
1660
- condition=condition,
1661
- error_msg=(
1662
- error_msg if isinstance(error_msg, ast.Expr) else None
1663
- ),
1664
- kid=kid,
1665
- )
1666
- )
1667
- else:
1668
- raise self.ice()
1474
+ error_msg: ast.Expr | None = None
1475
+ self.consume_token(Tok.KW_ASSERT)
1476
+ condition = self.consume(ast.Expr)
1477
+ if self.match_token(Tok.COMMA):
1478
+ error_msg = self.consume(ast.Expr)
1479
+ return ast.AssertStmt(
1480
+ condition=condition,
1481
+ error_msg=error_msg,
1482
+ kid=self.cur_nodes,
1483
+ )
1669
1484
 
1670
- def check_stmt(self, kid: list[ast.AstNode]) -> ast.CheckStmt:
1485
+ def check_stmt(self, _: None) -> ast.CheckStmt:
1671
1486
  """Grammar rule.
1672
1487
 
1673
1488
  check_stmt: KW_CHECK expression
1674
1489
  """
1675
- if isinstance(kid[1], ast.Expr):
1676
- return self.nu(
1677
- ast.CheckStmt(
1678
- target=kid[1],
1679
- kid=kid,
1680
- )
1681
- )
1682
- else:
1683
- raise self.ice()
1490
+ self.consume_token(Tok.KW_CHECK)
1491
+ target = self.consume(ast.Expr)
1492
+ return ast.CheckStmt(
1493
+ target=target,
1494
+ kid=self.cur_nodes,
1495
+ )
1684
1496
 
1685
- def ctrl_stmt(self, kid: list[ast.AstNode]) -> ast.CtrlStmt:
1497
+ def ctrl_stmt(self, _: None) -> ast.CtrlStmt:
1686
1498
  """Grammar rule.
1687
1499
 
1688
1500
  ctrl_stmt: KW_SKIP | KW_BREAK | KW_CONTINUE
1689
1501
  """
1690
- if isinstance(kid[0], ast.Token):
1691
- return self.nu(
1692
- ast.CtrlStmt(
1693
- ctrl=kid[0],
1694
- kid=kid,
1695
- )
1696
- )
1697
- else:
1698
- raise self.ice()
1502
+ tok = (
1503
+ self.match_token(Tok.KW_SKIP)
1504
+ or self.match_token(Tok.KW_BREAK)
1505
+ or self.consume_token(Tok.KW_CONTINUE)
1506
+ )
1507
+ return ast.CtrlStmt(
1508
+ ctrl=tok,
1509
+ kid=self.cur_nodes,
1510
+ )
1699
1511
 
1700
- def delete_stmt(self, kid: list[ast.AstNode]) -> ast.DeleteStmt:
1512
+ def delete_stmt(self, _: None) -> ast.DeleteStmt:
1701
1513
  """Grammar rule.
1702
1514
 
1703
1515
  delete_stmt: KW_DELETE expression
1704
1516
  """
1705
- if isinstance(kid[1], ast.Expr):
1706
- return self.nu(
1707
- ast.DeleteStmt(
1708
- target=kid[1],
1709
- kid=kid,
1710
- )
1711
- )
1712
- else:
1713
- raise self.ice()
1517
+ self.consume_token(Tok.KW_DELETE)
1518
+ target = self.consume(ast.Expr)
1519
+ return ast.DeleteStmt(
1520
+ target=target,
1521
+ kid=self.cur_nodes,
1522
+ )
1714
1523
 
1715
- def report_stmt(self, kid: list[ast.AstNode]) -> ast.ReportStmt:
1524
+ def report_stmt(self, _: None) -> ast.ReportStmt:
1716
1525
  """Grammar rule.
1717
1526
 
1718
1527
  report_stmt: KW_REPORT expression
1719
1528
  """
1720
- if isinstance(kid[1], ast.Expr):
1721
- return self.nu(
1722
- ast.ReportStmt(
1723
- expr=kid[1],
1724
- kid=kid,
1725
- )
1726
- )
1727
- else:
1728
- raise self.ice()
1529
+ self.consume_token(Tok.KW_REPORT)
1530
+ target = self.consume(ast.Expr)
1531
+ return ast.ReportStmt(
1532
+ expr=target,
1533
+ kid=self.cur_nodes,
1534
+ )
1729
1535
 
1730
- def return_stmt(self, kid: list[ast.AstNode]) -> ast.ReturnStmt:
1536
+ def return_stmt(self, _: None) -> ast.ReturnStmt:
1731
1537
  """Grammar rule.
1732
1538
 
1733
1539
  return_stmt: KW_RETURN expression?
1734
1540
  """
1735
- if len(kid) > 1:
1736
- return self.nu(
1737
- ast.ReturnStmt(
1738
- expr=kid[1] if isinstance(kid[1], ast.Expr) else None,
1739
- kid=kid,
1740
- )
1741
- )
1742
- else:
1743
- return self.nu(
1744
- ast.ReturnStmt(
1745
- expr=None,
1746
- kid=kid,
1747
- )
1748
- )
1541
+ self.consume_token(Tok.KW_RETURN)
1542
+ expr = self.match(ast.Expr)
1543
+ return ast.ReturnStmt(
1544
+ expr=expr,
1545
+ kid=self.cur_nodes,
1546
+ )
1749
1547
 
1750
1548
  def walker_stmt(self, kid: list[ast.AstNode]) -> ast.CodeBlockStmt:
1751
1549
  """Grammar rule.
@@ -1753,90 +1551,91 @@ class JacParser(Pass):
1753
1551
  walker_stmt: disengage_stmt | revisit_stmt | visit_stmt | ignore_stmt
1754
1552
  """
1755
1553
  if isinstance(kid[0], ast.CodeBlockStmt):
1756
- return self.nu(kid[0])
1554
+ return kid[0]
1757
1555
  else:
1758
1556
  raise self.ice()
1759
1557
 
1760
- def ignore_stmt(self, kid: list[ast.AstNode]) -> ast.IgnoreStmt:
1558
+ def ignore_stmt(self, _: None) -> ast.IgnoreStmt:
1761
1559
  """Grammar rule.
1762
1560
 
1763
1561
  ignore_stmt: KW_IGNORE expression SEMI
1764
1562
  """
1765
- if isinstance(kid[1], ast.Expr):
1766
- return self.nu(
1767
- ast.IgnoreStmt(
1768
- target=kid[1],
1769
- kid=kid,
1770
- )
1771
- )
1772
- else:
1773
- raise self.ice()
1563
+ self.consume_token(Tok.KW_IGNORE)
1564
+ target = self.consume(ast.Expr)
1565
+ self.consume_token(Tok.SEMI)
1566
+ return ast.IgnoreStmt(
1567
+ target=target,
1568
+ kid=self.cur_nodes,
1569
+ )
1774
1570
 
1775
- def visit_stmt(self, kid: list[ast.AstNode]) -> ast.VisitStmt:
1571
+ def visit_stmt(self, _: None) -> ast.VisitStmt:
1776
1572
  """Grammar rule.
1777
1573
 
1778
1574
  visit_stmt: KW_VISIT (inherited_archs)? expression (else_stmt | SEMI)
1779
1575
  """
1780
- sub_name = kid[1] if isinstance(kid[1], ast.SubNodeList) else None
1781
- target = kid[2] if sub_name else kid[1]
1782
- else_body = kid[-1] if isinstance(kid[-1], ast.ElseStmt) else None
1783
- if isinstance(target, ast.Expr):
1784
- return self.nu(
1785
- ast.VisitStmt(
1786
- vis_type=sub_name,
1787
- target=target,
1788
- else_body=else_body,
1789
- kid=kid,
1790
- )
1791
- )
1792
- else:
1793
- raise self.ice()
1576
+ self.consume_token(Tok.KW_VISIT)
1577
+ sub_name = self.match(ast.SubNodeList)
1578
+ target = self.consume(ast.Expr)
1579
+ else_body = self.match(ast.ElseStmt)
1580
+ if else_body is None:
1581
+ self.consume_token(Tok.SEMI)
1582
+ return ast.VisitStmt(
1583
+ vis_type=sub_name,
1584
+ target=target,
1585
+ else_body=else_body,
1586
+ kid=self.cur_nodes,
1587
+ )
1794
1588
 
1795
- def revisit_stmt(self, kid: list[ast.AstNode]) -> ast.RevisitStmt:
1589
+ def revisit_stmt(self, _: None) -> ast.RevisitStmt:
1796
1590
  """Grammar rule.
1797
1591
 
1798
1592
  revisit_stmt: KW_REVISIT expression? (else_stmt | SEMI)
1799
1593
  """
1800
- target = kid[1] if isinstance(kid[1], ast.Expr) else None
1801
- else_body = kid[-1] if isinstance(kid[-1], ast.ElseStmt) else None
1802
- return self.nu(
1803
- ast.RevisitStmt(
1804
- hops=target,
1805
- else_body=else_body,
1806
- kid=kid,
1807
- )
1594
+ self.consume_token(Tok.KW_REVISIT)
1595
+ target = self.match(ast.Expr)
1596
+ else_body = self.match(ast.ElseStmt)
1597
+ if else_body is None:
1598
+ self.consume_token(Tok.SEMI)
1599
+ return ast.RevisitStmt(
1600
+ hops=target,
1601
+ else_body=else_body,
1602
+ kid=self.cur_nodes,
1808
1603
  )
1809
1604
 
1810
- def disengage_stmt(self, kid: list[ast.AstNode]) -> ast.DisengageStmt:
1605
+ def disengage_stmt(self, _: None) -> ast.DisengageStmt:
1811
1606
  """Grammar rule.
1812
1607
 
1813
1608
  disengage_stmt: KW_DISENGAGE SEMI
1814
1609
  """
1815
- return self.nu(
1816
- ast.DisengageStmt(
1817
- kid=kid,
1818
- )
1610
+ kw = self.consume_token(Tok.KW_DISENGAGE)
1611
+ semi = self.consume_token(Tok.SEMI)
1612
+ return ast.DisengageStmt(
1613
+ kid=[kw, semi],
1819
1614
  )
1820
1615
 
1821
- def global_ref(self, kid: list[ast.AstNode]) -> ast.GlobalStmt:
1616
+ def global_ref(self, _: None) -> ast.GlobalStmt:
1822
1617
  """Grammar rule.
1823
1618
 
1824
1619
  global_ref: GLOBAL_OP name_list
1825
1620
  """
1826
- if isinstance(kid[0], ast.Token) and isinstance(kid[1], ast.SubNodeList):
1827
- return self.nu(ast.GlobalStmt(target=kid[1], kid=kid))
1828
- else:
1829
- raise self.ice()
1621
+ self.consume_token(Tok.GLOBAL_OP)
1622
+ target = self.consume(ast.SubNodeList)
1623
+ return ast.GlobalStmt(
1624
+ target=target,
1625
+ kid=self.cur_nodes,
1626
+ )
1830
1627
 
1831
- def nonlocal_ref(self, kid: list[ast.AstNode]) -> ast.NonLocalStmt:
1628
+ def nonlocal_ref(self, _: None) -> ast.NonLocalStmt:
1832
1629
  """Grammar rule.
1833
1630
 
1834
1631
  nonlocal_ref: NONLOCAL_OP name_list
1835
1632
  """
1836
- if isinstance(kid[0], ast.Token) and isinstance(kid[1], ast.SubNodeList):
1837
- return self.nu(ast.NonLocalStmt(target=kid[1], kid=kid))
1838
- else:
1839
- raise self.ice()
1633
+ self.consume_token(Tok.NONLOCAL_OP)
1634
+ target = self.consume(ast.SubNodeList)
1635
+ return ast.NonLocalStmt(
1636
+ target=target,
1637
+ kid=self.cur_nodes,
1638
+ )
1840
1639
 
1841
1640
  def assignment(self, kid: list[ast.AstNode]) -> ast.Assignment:
1842
1641
  """Grammar rule.
@@ -1899,88 +1698,49 @@ class JacParser(Pass):
1899
1698
  kid = [x for x in kid if x not in assignees]
1900
1699
  kid.insert(1, new_targ) if is_frozen else kid.insert(0, new_targ)
1901
1700
  if is_aug:
1902
- return self.nu(
1903
- ast.Assignment(
1904
- target=new_targ,
1905
- type_tag=type_tag if isinstance(type_tag, ast.SubTag) else None,
1906
- value=value,
1907
- mutable=is_frozen,
1908
- aug_op=is_aug,
1909
- kid=kid,
1910
- )
1911
- )
1912
- return self.nu(
1913
- ast.Assignment(
1701
+ return ast.Assignment(
1914
1702
  target=new_targ,
1915
1703
  type_tag=type_tag if isinstance(type_tag, ast.SubTag) else None,
1916
1704
  value=value,
1917
1705
  mutable=is_frozen,
1706
+ aug_op=is_aug,
1918
1707
  kid=kid,
1919
- semstr=semstr if isinstance(semstr, ast.String) else None,
1920
1708
  )
1709
+ return ast.Assignment(
1710
+ target=new_targ,
1711
+ type_tag=type_tag if isinstance(type_tag, ast.SubTag) else None,
1712
+ value=value,
1713
+ mutable=is_frozen,
1714
+ kid=kid,
1715
+ semstr=semstr if isinstance(semstr, ast.String) else None,
1921
1716
  )
1922
1717
 
1923
- def expression(self, kid: list[ast.AstNode]) -> ast.Expr:
1718
+ def expression(self, _: None) -> ast.Expr:
1924
1719
  """Grammar rule.
1925
1720
 
1926
1721
  expression: walrus_assign
1927
1722
  | pipe (KW_IF expression KW_ELSE expression)?
1928
1723
  | lambda_expr
1929
1724
  """
1930
- if len(kid) > 1:
1931
- if (
1932
- isinstance(kid[0], ast.Expr)
1933
- and isinstance(kid[2], ast.Expr)
1934
- and isinstance(kid[4], ast.Expr)
1935
- ):
1936
- return self.nu(
1937
- ast.IfElseExpr(
1938
- value=kid[0],
1939
- condition=kid[2],
1940
- else_value=kid[4],
1941
- kid=kid,
1942
- )
1943
- )
1944
- else:
1945
- raise self.ice()
1946
- elif isinstance(kid[0], ast.Expr):
1947
- return self.nu(kid[0])
1948
- else:
1949
- raise self.ice()
1725
+ value = self.consume(ast.Expr)
1726
+ if self.match_token(Tok.KW_IF):
1727
+ condition = self.consume(ast.Expr)
1728
+ self.consume_token(Tok.KW_ELSE)
1729
+ else_value = self.consume(ast.Expr)
1730
+ return ast.IfElseExpr(
1731
+ value=value,
1732
+ condition=condition,
1733
+ else_value=else_value,
1734
+ kid=self.cur_nodes,
1735
+ )
1736
+ return value
1950
1737
 
1951
- def walrus_assign(self, kid: list[ast.AstNode]) -> ast.Expr:
1738
+ def walrus_assign(self, _: None) -> ast.Expr:
1952
1739
  """Grammar rule.
1953
1740
 
1954
1741
  walrus_assign: (walrus_assign WALRUS_EQ)? pipe
1955
1742
  """
1956
- return self.binary_expr_unwind(kid)
1957
-
1958
- def binary_expr_unwind(self, kid: list[ast.AstNode]) -> ast.Expr:
1959
- """Binary expression helper."""
1960
- if len(kid) > 1:
1961
- if (
1962
- isinstance(kid[0], ast.Expr)
1963
- and isinstance(
1964
- kid[1],
1965
- (ast.Token, ast.DisconnectOp, ast.ConnectOp),
1966
- )
1967
- and isinstance(kid[2], ast.Expr)
1968
- ):
1969
- return self.nu(
1970
- ast.BinaryExpr(
1971
- left=kid[0],
1972
- op=kid[1],
1973
- right=kid[2],
1974
- kid=kid,
1975
- )
1976
- )
1977
- else:
1978
- raise self.ice()
1979
- elif isinstance(kid[0], ast.Expr):
1980
- return self.nu(kid[0])
1981
- else:
1982
-
1983
- raise self.ice()
1743
+ return self._binary_expr_unwind(self.cur_nodes)
1984
1744
 
1985
1745
  def lambda_expr(self, kid: list[ast.AstNode]) -> ast.LambdaExpr:
1986
1746
  """Grammar rule.
@@ -2016,156 +1776,134 @@ class JacParser(Pass):
2016
1776
  new_kid = [i for i in kid if i != params and i != return_type]
2017
1777
  new_kid.insert(1, signature) if signature else None
2018
1778
  if isinstance(chomp[0], ast.Expr):
2019
- return self.nu(
2020
- ast.LambdaExpr(
2021
- signature=signature,
2022
- body=chomp[0],
2023
- kid=new_kid,
2024
- )
1779
+ return ast.LambdaExpr(
1780
+ signature=signature,
1781
+ body=chomp[0],
1782
+ kid=new_kid,
2025
1783
  )
2026
1784
  else:
2027
1785
  raise self.ice()
2028
1786
 
2029
- def pipe(self, kid: list[ast.AstNode]) -> ast.Expr:
1787
+ def pipe(self, _: None) -> ast.Expr:
2030
1788
  """Grammar rule.
2031
1789
 
2032
1790
  pipe: pipe_back PIPE_FWD pipe
2033
1791
  | pipe_back
2034
1792
  """
2035
- return self.binary_expr_unwind(kid)
1793
+ return self._binary_expr_unwind(self.cur_nodes)
2036
1794
 
2037
- def pipe_back(self, kid: list[ast.AstNode]) -> ast.Expr:
1795
+ def pipe_back(self, _: None) -> ast.Expr:
2038
1796
  """Grammar rule.
2039
1797
 
2040
1798
  pipe_back: bitwise_or PIPE_BKWD pipe_back
2041
1799
  | bitwise_or
2042
1800
  """
2043
- return self.binary_expr_unwind(kid)
1801
+ return self._binary_expr_unwind(self.cur_nodes)
2044
1802
 
2045
- def bitwise_or(self, kid: list[ast.AstNode]) -> ast.Expr:
1803
+ def bitwise_or(self, _: None) -> ast.Expr:
2046
1804
  """Grammar rule.
2047
1805
 
2048
1806
  bitwise_or: bitwise_xor BW_OR bitwise_or
2049
1807
  | bitwise_xor
2050
1808
  """
2051
- return self.binary_expr_unwind(kid)
1809
+ return self._binary_expr_unwind(self.cur_nodes)
2052
1810
 
2053
- def bitwise_xor(self, kid: list[ast.AstNode]) -> ast.Expr:
1811
+ def bitwise_xor(self, _: None) -> ast.Expr:
2054
1812
  """Grammar rule.
2055
1813
 
2056
1814
  bitwise_xor: bitwise_and BW_XOR bitwise_xor
2057
1815
  | bitwise_and
2058
1816
  """
2059
- return self.binary_expr_unwind(kid)
1817
+ return self._binary_expr_unwind(self.cur_nodes)
2060
1818
 
2061
- def bitwise_and(self, kid: list[ast.AstNode]) -> ast.Expr:
1819
+ def bitwise_and(self, _: None) -> ast.Expr:
2062
1820
  """Grammar rule.
2063
1821
 
2064
1822
  bitwise_and: shift BW_AND bitwise_and
2065
1823
  | shift
2066
1824
  """
2067
- return self.binary_expr_unwind(kid)
1825
+ return self._binary_expr_unwind(self.cur_nodes)
2068
1826
 
2069
- def shift(self, kid: list[ast.AstNode]) -> ast.Expr:
1827
+ def shift(self, _: None) -> ast.Expr:
2070
1828
  """Grammar rule.
2071
1829
 
2072
1830
  shift: (shift (RSHIFT | LSHIFT))? logical_or
2073
1831
  """
2074
- return self.binary_expr_unwind(kid)
1832
+ return self._binary_expr_unwind(self.cur_nodes)
2075
1833
 
2076
- def logical_or(self, kid: list[ast.AstNode]) -> ast.Expr:
1834
+ def logical_or(self, _: None) -> ast.Expr:
2077
1835
  """Grammar rule.
2078
1836
 
2079
1837
  logical_or: logical_and (KW_OR logical_and)*
2080
1838
  """
2081
- if len(kid) > 1:
2082
- values = [i for i in kid if isinstance(i, ast.Expr)]
2083
- ops = kid[1] if isinstance(kid[1], ast.Token) else None
2084
- if not ops:
2085
- raise self.ice()
2086
- return self.nu(
2087
- ast.BoolExpr(
2088
- op=ops,
2089
- values=values,
2090
- kid=kid,
2091
- )
2092
- )
2093
- elif isinstance(kid[0], ast.Expr):
2094
- return self.nu(kid[0])
2095
- else:
2096
-
2097
- raise self.ice()
1839
+ value = self.consume(ast.Expr)
1840
+ if not (ops := self.match_token(Tok.KW_OR)):
1841
+ return value
1842
+ values: list = [value]
1843
+ while value := self.consume(ast.Expr):
1844
+ values.append(value)
1845
+ if not self.match_token(Tok.KW_OR):
1846
+ break
1847
+ return ast.BoolExpr(
1848
+ op=ops,
1849
+ values=values,
1850
+ kid=self.cur_nodes,
1851
+ )
2098
1852
 
2099
- def logical_and(self, kid: list[ast.AstNode]) -> ast.Expr:
1853
+ def logical_and(self, _: None) -> ast.Expr:
2100
1854
  """Grammar rule.
2101
1855
 
2102
1856
  logical_and: logical_not (KW_AND logical_not)*
2103
1857
  """
2104
- if len(kid) > 1:
2105
- values = [i for i in kid if isinstance(i, ast.Expr)]
2106
- ops = kid[1] if isinstance(kid[1], ast.Token) else None
2107
- if not ops:
2108
- raise self.ice()
2109
- return self.nu(
2110
- ast.BoolExpr(
2111
- op=ops,
2112
- values=values,
2113
- kid=kid,
2114
- )
2115
- )
2116
- elif isinstance(kid[0], ast.Expr):
2117
- return self.nu(kid[0])
2118
- else:
2119
-
2120
- raise self.ice()
1858
+ value = self.consume(ast.Expr)
1859
+ if not (ops := self.match_token(Tok.KW_AND)):
1860
+ return value
1861
+ values: list = [value]
1862
+ while value := self.consume(ast.Expr):
1863
+ values.append(value)
1864
+ if not self.match_token(Tok.KW_AND):
1865
+ break
1866
+ return ast.BoolExpr(
1867
+ op=ops,
1868
+ values=values,
1869
+ kid=self.cur_nodes,
1870
+ )
2121
1871
 
2122
- def logical_not(self, kid: list[ast.AstNode]) -> ast.Expr:
1872
+ def logical_not(self, _: None) -> ast.Expr:
2123
1873
  """Grammar rule.
2124
1874
 
2125
- logical_or: (logical_or KW_OR)? logical_and
1875
+ logical_not: NOT logical_not | compare
2126
1876
  """
2127
- if len(kid) == 2:
2128
- if isinstance(kid[0], ast.Token) and isinstance(kid[1], ast.Expr):
2129
- return self.nu(
2130
- ast.UnaryExpr(
2131
- op=kid[0],
2132
- operand=kid[1],
2133
- kid=kid,
2134
- )
2135
- )
2136
- else:
2137
- raise self.ice()
2138
- if isinstance(kid[0], ast.Expr):
2139
- return self.nu(kid[0])
2140
- else:
2141
- raise self.ice()
1877
+ if op := self.match_token(Tok.NOT):
1878
+ operand = self.consume(ast.Expr)
1879
+ return ast.UnaryExpr(
1880
+ op=op,
1881
+ operand=operand,
1882
+ kid=self.cur_nodes,
1883
+ )
1884
+ return self.consume(ast.Expr)
2142
1885
 
2143
- def compare(self, kid: list[ast.AstNode]) -> ast.Expr:
1886
+ def compare(self, _: list[ast.AstNode]) -> ast.Expr:
2144
1887
  """Grammar rule.
2145
1888
 
2146
1889
  compare: (arithmetic cmp_op)* arithmetic
2147
1890
  """
2148
- if len(kid) > 1:
2149
- ops = [i for i in kid[1::2] if isinstance(i, ast.Token)]
2150
- left = kid[0]
2151
- rights = [i for i in kid[1:][1::2] if isinstance(i, ast.Expr)]
2152
- if isinstance(left, ast.Expr) and len(ops) == len(rights):
2153
- return self.nu(
2154
- ast.CompareExpr(
2155
- left=left,
2156
- ops=ops,
2157
- rights=rights,
2158
- kid=kid,
2159
- )
2160
- )
2161
- else:
2162
- raise self.ice()
2163
- elif isinstance(kid[0], ast.Expr):
2164
- return self.nu(kid[0])
2165
- else:
2166
- raise self.ice()
1891
+ ops: list = []
1892
+ rights: list = []
1893
+ left = self.consume(ast.Expr)
1894
+ while op := self.match(ast.Token):
1895
+ ops.append(op)
1896
+ rights.append(self.consume(ast.Expr))
1897
+ if not ops:
1898
+ return left
1899
+ return ast.CompareExpr(
1900
+ left=left,
1901
+ ops=ops,
1902
+ rights=rights,
1903
+ kid=self.cur_nodes,
1904
+ )
2167
1905
 
2168
- def cmp_op(self, kid: list[ast.AstNode]) -> ast.Token:
1906
+ def cmp_op(self, _: None) -> ast.Token:
2169
1907
  """Grammar rule.
2170
1908
 
2171
1909
  cmp_op: KW_ISN
@@ -2179,116 +1917,105 @@ class JacParser(Pass):
2179
1917
  | LT
2180
1918
  | EE
2181
1919
  """
2182
- if isinstance(kid[0], ast.Token):
2183
- return self.nu(kid[0])
2184
- else:
2185
- raise self.ice()
1920
+ return self.consume(ast.Token)
2186
1921
 
2187
- def arithmetic(self, kid: list[ast.AstNode]) -> ast.Expr:
1922
+ def arithmetic(self, _: None) -> ast.Expr:
2188
1923
  """Grammar rule.
2189
1924
 
2190
1925
  arithmetic: (arithmetic (MINUS | PLUS))? term
2191
1926
  """
2192
- return self.binary_expr_unwind(kid)
1927
+ return self._binary_expr_unwind(self.cur_nodes)
2193
1928
 
2194
- def term(self, kid: list[ast.AstNode]) -> ast.Expr:
1929
+ def term(self, _: None) -> ast.Expr:
2195
1930
  """Grammar rule.
2196
1931
 
2197
1932
  term: (term (MOD | DIV | FLOOR_DIV | STAR_MUL | DECOR_OP))? power
2198
1933
  """
2199
- return self.binary_expr_unwind(kid)
1934
+ return self._binary_expr_unwind(self.cur_nodes)
2200
1935
 
2201
- def factor(self, kid: list[ast.AstNode]) -> ast.Expr:
1936
+ def factor(self, _: None) -> ast.Expr:
2202
1937
  """Grammar rule.
2203
1938
 
2204
1939
  factor: (BW_NOT | MINUS | PLUS) factor | connect
2205
1940
  """
2206
- if len(kid) == 2:
2207
- if isinstance(kid[0], ast.Token) and isinstance(kid[1], ast.Expr):
2208
- return self.nu(
2209
- ast.UnaryExpr(
2210
- op=kid[0],
2211
- operand=kid[1],
2212
- kid=kid,
2213
- )
2214
- )
2215
- else:
2216
- raise self.ice()
2217
- return self.binary_expr_unwind(kid)
1941
+ if (
1942
+ op := self.match_token(Tok.BW_NOT)
1943
+ or self.match_token(Tok.MINUS)
1944
+ or self.match_token(Tok.PLUS)
1945
+ ):
1946
+ operand = self.consume(ast.Expr)
1947
+ return ast.UnaryExpr(
1948
+ op=op,
1949
+ operand=operand,
1950
+ kid=self.cur_nodes,
1951
+ )
1952
+ return self._binary_expr_unwind(self.cur_nodes)
2218
1953
 
2219
- def power(self, kid: list[ast.AstNode]) -> ast.Expr:
1954
+ def power(self, _: None) -> ast.Expr:
2220
1955
  """Grammar rule.
2221
1956
 
2222
1957
  power: (power STAR_POW)? factor
2223
1958
  """
2224
- return self.binary_expr_unwind(kid)
1959
+ return self._binary_expr_unwind(self.cur_nodes)
2225
1960
 
2226
- def connect(self, kid: list[ast.AstNode]) -> ast.Expr:
1961
+ def connect(self, _: None) -> ast.Expr:
2227
1962
  """Grammar rule.
2228
1963
 
2229
1964
  connect: (connect (connect_op | disconnect_op))? atomic_pipe
2230
1965
  """
2231
- return self.binary_expr_unwind(kid)
1966
+ return self._binary_expr_unwind(self.cur_nodes)
2232
1967
 
2233
- def atomic_pipe(self, kid: list[ast.AstNode]) -> ast.Expr:
1968
+ def atomic_pipe(self, _: None) -> ast.Expr:
2234
1969
  """Grammar rule.
2235
1970
 
2236
1971
  atomic_pipe: (atomic_pipe A_PIPE_FWD)? atomic_pipe_back
2237
1972
  """
2238
- return self.binary_expr_unwind(kid)
1973
+ return self._binary_expr_unwind(self.cur_nodes)
2239
1974
 
2240
- def atomic_pipe_back(self, kid: list[ast.AstNode]) -> ast.Expr:
1975
+ def atomic_pipe_back(self, _: None) -> ast.Expr:
2241
1976
  """Grammar rule.
2242
1977
 
2243
1978
  atomic_pipe_back: (atomic_pipe_back A_PIPE_BKWD)? ds_spawn
2244
1979
  """
2245
- return self.binary_expr_unwind(kid)
1980
+ return self._binary_expr_unwind(self.cur_nodes)
2246
1981
 
2247
- def ds_spawn(self, kid: list[ast.AstNode]) -> ast.Expr:
1982
+ def ds_spawn(self, _: None) -> ast.Expr:
2248
1983
  """Grammar rule.
2249
1984
 
2250
1985
  ds_spawn: (ds_spawn KW_SPAWN)? unpack
2251
1986
  """
2252
- return self.binary_expr_unwind(kid)
1987
+ return self._binary_expr_unwind(self.cur_nodes)
2253
1988
 
2254
- def unpack(self, kid: list[ast.AstNode]) -> ast.Expr:
1989
+ def unpack(self, _: None) -> ast.Expr:
2255
1990
  """Grammar rule.
2256
1991
 
2257
1992
  unpack: STAR_MUL? ref
2258
1993
  """
2259
- if len(kid) == 2:
2260
- if isinstance(kid[0], ast.Token) and isinstance(kid[1], ast.Expr):
2261
- return self.nu(
2262
- ast.UnaryExpr(
2263
- op=kid[0],
2264
- operand=kid[1],
2265
- kid=kid,
2266
- )
2267
- )
2268
- else:
2269
- raise self.ice()
2270
- return self.binary_expr_unwind(kid)
1994
+ if op := self.match_token(Tok.STAR_MUL):
1995
+ operand = self.consume(ast.Expr)
1996
+ return ast.UnaryExpr(
1997
+ op=op,
1998
+ operand=operand,
1999
+ kid=self.cur_nodes,
2000
+ )
2001
+ return self._binary_expr_unwind(self.cur_nodes)
2271
2002
 
2272
- def ref(self, kid: list[ast.AstNode]) -> ast.Expr:
2003
+ def ref(self, _: None) -> ast.Expr:
2273
2004
  """Grammar rule.
2274
2005
 
2275
2006
  ref: walrus_assign
2276
2007
  | BW_AND walrus_assign
2277
2008
  """
2278
- if len(kid) == 2:
2279
- if isinstance(kid[0], ast.Token) and isinstance(kid[1], ast.Expr):
2280
- return self.nu(
2281
- ast.UnaryExpr(
2282
- op=kid[0],
2283
- operand=kid[1],
2284
- kid=kid,
2285
- )
2286
- )
2287
- else:
2288
- raise self.ice()
2289
- return self.binary_expr_unwind(kid)
2009
+ if op := self.match_token(Tok.BW_AND):
2010
+ operand = self.consume(ast.Expr)
2011
+ return ast.UnaryExpr(
2012
+ op=op,
2013
+ operand=operand,
2014
+ kid=self.cur_nodes,
2015
+ )
2016
+ return self._binary_expr_unwind(self.cur_nodes)
2290
2017
 
2291
- def pipe_call(self, kid: list[ast.AstNode]) -> ast.Expr:
2018
+ def pipe_call(self, _: None) -> ast.Expr:
2292
2019
  """Grammar rule.
2293
2020
 
2294
2021
  pipe_call: atomic_chain
@@ -2297,29 +2024,21 @@ class JacParser(Pass):
2297
2024
  | KW_SPAWN atomic_chain
2298
2025
  | KW_AWAIT atomic_chain
2299
2026
  """
2300
- if len(kid) == 2:
2301
- if (
2302
- isinstance(kid[0], ast.Token)
2303
- and kid[0].name == Tok.KW_AWAIT
2304
- and isinstance(kid[1], ast.Expr)
2305
- ):
2306
- return self.nu(
2307
- ast.AwaitExpr(
2308
- target=kid[1],
2309
- kid=kid,
2310
- )
2027
+ if len(self.cur_nodes) == 2:
2028
+ if self.match_token(Tok.KW_AWAIT):
2029
+ target = self.consume(ast.Expr)
2030
+ return ast.AwaitExpr(
2031
+ target=target,
2032
+ kid=self.cur_nodes,
2311
2033
  )
2312
- elif isinstance(kid[0], ast.Token) and isinstance(kid[1], ast.Expr):
2313
- return self.nu(
2314
- ast.UnaryExpr(
2315
- op=kid[0],
2316
- operand=kid[1],
2317
- kid=kid,
2318
- )
2034
+ elif op := self.match(ast.Token):
2035
+ operand = self.consume(ast.Expr)
2036
+ return ast.UnaryExpr(
2037
+ op=op,
2038
+ operand=operand,
2039
+ kid=self.cur_nodes,
2319
2040
  )
2320
- else:
2321
- raise self.ice()
2322
- return self.binary_expr_unwind(kid)
2041
+ return self._binary_expr_unwind(self.cur_nodes)
2323
2042
 
2324
2043
  def aug_op(self, kid: list[ast.AstNode]) -> ast.Token:
2325
2044
  """Grammar rule.
@@ -2339,7 +2058,7 @@ class JacParser(Pass):
2339
2058
  | WALRUS_EQ
2340
2059
  """
2341
2060
  if isinstance(kid[0], ast.Token):
2342
- return self.nu(kid[0])
2061
+ return kid[0]
2343
2062
  else:
2344
2063
  raise self.ice()
2345
2064
 
@@ -2351,7 +2070,7 @@ class JacParser(Pass):
2351
2070
  | (atomic_call | atom | edge_ref_chain)
2352
2071
  """
2353
2072
  if len(kid) < 2 and isinstance(kid[0], ast.Expr):
2354
- return self.nu(kid[0])
2073
+ return kid[0]
2355
2074
  chomp = [*kid]
2356
2075
  target = chomp[0]
2357
2076
  chomp = chomp[1:]
@@ -2364,14 +2083,12 @@ class JacParser(Pass):
2364
2083
  and isinstance(chomp[0], ast.AtomExpr)
2365
2084
  and isinstance(target, ast.Expr)
2366
2085
  ):
2367
- return self.nu(
2368
- ast.AtomTrailer(
2369
- target=target,
2370
- right=chomp[0],
2371
- is_null_ok=is_null_ok,
2372
- is_attr=False,
2373
- kid=kid,
2374
- )
2086
+ return ast.AtomTrailer(
2087
+ target=target,
2088
+ right=chomp[0],
2089
+ is_null_ok=is_null_ok,
2090
+ is_attr=False,
2091
+ kid=kid,
2375
2092
  )
2376
2093
  elif (
2377
2094
  len(chomp) > 1
@@ -2379,14 +2096,12 @@ class JacParser(Pass):
2379
2096
  and isinstance(chomp[1], (ast.AtomExpr, ast.AtomTrailer))
2380
2097
  and isinstance(target, ast.Expr)
2381
2098
  ):
2382
- return self.nu(
2383
- ast.AtomTrailer(
2384
- target=(target if chomp[0].name != Tok.DOT_BKWD else chomp[1]),
2385
- right=(chomp[1] if chomp[0].name != Tok.DOT_BKWD else target),
2386
- is_null_ok=is_null_ok,
2387
- is_attr=True,
2388
- kid=kid,
2389
- )
2099
+ return ast.AtomTrailer(
2100
+ target=(target if chomp[0].name != Tok.DOT_BKWD else chomp[1]),
2101
+ right=(chomp[1] if chomp[0].name != Tok.DOT_BKWD else target),
2102
+ is_null_ok=is_null_ok,
2103
+ is_attr=True,
2104
+ kid=kid,
2390
2105
  )
2391
2106
  else:
2392
2107
  raise self.ice()
@@ -2402,25 +2117,23 @@ class JacParser(Pass):
2402
2117
  and kid[-2]
2403
2118
  and isinstance(kid[-2], ast.FuncCall)
2404
2119
  ):
2405
- return self.nu(
2406
- ast.FuncCall(
2407
- target=kid[0],
2408
- params=kid[2] if isinstance(kid[2], ast.SubNodeList) else None,
2409
- genai_call=kid[-2],
2410
- kid=kid,
2411
- )
2120
+ return ast.FuncCall(
2121
+ target=kid[0],
2122
+ params=kid[2] if isinstance(kid[2], ast.SubNodeList) else None,
2123
+ genai_call=kid[-2],
2124
+ kid=kid,
2412
2125
  )
2413
2126
  if (
2414
2127
  len(kid) == 4
2415
2128
  and isinstance(kid[0], ast.Expr)
2416
2129
  and isinstance(kid[2], ast.SubNodeList)
2417
2130
  ):
2418
- return self.nu(
2419
- ast.FuncCall(target=kid[0], params=kid[2], genai_call=None, kid=kid)
2131
+ return ast.FuncCall(
2132
+ target=kid[0], params=kid[2], genai_call=None, kid=kid
2420
2133
  )
2421
2134
  elif len(kid) == 3 and isinstance(kid[0], ast.Expr):
2422
- return self.nu(
2423
- ast.FuncCall(target=kid[0], params=None, genai_call=None, kid=kid)
2135
+ return ast.FuncCall(
2136
+ target=kid[0], params=None, genai_call=None, kid=kid
2424
2137
  )
2425
2138
  else:
2426
2139
  raise self.ice()
@@ -2447,14 +2160,10 @@ class JacParser(Pass):
2447
2160
  )
2448
2161
  expr = ast.TupleVal(values=sublist, kid=[sublist])
2449
2162
  kid = [expr]
2450
- return self.nu(
2451
- ast.IndexSlice(
2452
- slices=[
2453
- ast.IndexSlice.Slice(start=expr, stop=None, step=None)
2454
- ],
2455
- is_range=False,
2456
- kid=kid,
2457
- )
2163
+ return ast.IndexSlice(
2164
+ slices=[ast.IndexSlice.Slice(start=expr, stop=None, step=None)],
2165
+ is_range=False,
2166
+ kid=kid,
2458
2167
  )
2459
2168
  else:
2460
2169
  raise self.ice()
@@ -2489,15 +2198,13 @@ class JacParser(Pass):
2489
2198
  ast.IndexSlice.Slice(start=expr1, stop=expr2, step=expr3)
2490
2199
  )
2491
2200
 
2492
- return self.nu(
2493
- ast.IndexSlice(
2494
- slices=slices,
2495
- is_range=True,
2496
- kid=kid,
2497
- )
2201
+ return ast.IndexSlice(
2202
+ slices=slices,
2203
+ is_range=True,
2204
+ kid=kid,
2498
2205
  )
2499
2206
 
2500
- def atom(self, kid: list[ast.AstNode]) -> ast.Expr:
2207
+ def atom(self, _: None) -> ast.Expr:
2501
2208
  """Grammar rule.
2502
2209
 
2503
2210
  atom: named_ref
@@ -2506,41 +2213,27 @@ class JacParser(Pass):
2506
2213
  | atom_literal
2507
2214
  | type_ref
2508
2215
  """
2509
- if len(kid) == 1:
2510
- if isinstance(kid[0], ast.AtomExpr):
2511
- return self.nu(kid[0])
2512
- else:
2513
- raise self.ice()
2514
- elif len(kid) == 3:
2515
- if (
2516
- isinstance(kid[0], ast.Token)
2517
- and isinstance(kid[1], (ast.Expr, ast.YieldExpr))
2518
- and isinstance(kid[2], ast.Token)
2519
- ):
2520
- ret = ast.AtomUnit(value=kid[1], kid=kid)
2521
- return self.nu(ret)
2522
- else:
2523
- raise self.ice()
2524
- else:
2525
- raise self.ice()
2216
+ if self.match_token(Tok.LPAREN):
2217
+ value = self.match(ast.Expr) or self.consume(ast.YieldExpr)
2218
+ self.consume_token(Tok.RPAREN)
2219
+ return ast.AtomUnit(value=value, kid=self.cur_nodes)
2220
+ return self.consume(ast.AtomExpr)
2526
2221
 
2527
- def yield_expr(self, kid: list[ast.AstNode]) -> ast.YieldExpr:
2222
+ def yield_expr(self, _: None) -> ast.YieldExpr:
2528
2223
  """Grammar rule.
2529
2224
 
2530
2225
  yield_expr: KW_YIELD KW_FROM? expression
2531
2226
  """
2532
- if isinstance(kid[-1], ast.Expr):
2533
- return self.nu(
2534
- ast.YieldExpr(
2535
- expr=kid[-1],
2536
- with_from=len(kid) > 2,
2537
- kid=kid,
2538
- )
2539
- )
2540
- else:
2541
- raise self.ice()
2227
+ self.consume_token(Tok.KW_YIELD)
2228
+ is_with_from = bool(self.match_token(Tok.KW_FROM))
2229
+ expr = self.consume(ast.Expr)
2230
+ return ast.YieldExpr(
2231
+ expr=expr,
2232
+ with_from=is_with_from,
2233
+ kid=self.cur_nodes,
2234
+ )
2542
2235
 
2543
- def atom_literal(self, kid: list[ast.AstNode]) -> ast.AtomExpr:
2236
+ def atom_literal(self, _: None) -> ast.AtomExpr:
2544
2237
  """Grammar rule.
2545
2238
 
2546
2239
  atom_literal: builtin_type
@@ -2553,10 +2246,7 @@ class JacParser(Pass):
2553
2246
  | HEX
2554
2247
  | INT
2555
2248
  """
2556
- if isinstance(kid[0], ast.AtomExpr):
2557
- return self.nu(kid[0])
2558
- else:
2559
- raise self.ice()
2249
+ return self.consume(ast.AtomExpr)
2560
2250
 
2561
2251
  def atom_collection(self, kid: list[ast.AstNode]) -> ast.AtomExpr:
2562
2252
  """Grammar rule.
@@ -2570,23 +2260,18 @@ class JacParser(Pass):
2570
2260
  | tuple_val
2571
2261
  | list_val
2572
2262
  """
2573
- if isinstance(kid[0], ast.AtomExpr):
2574
- return self.nu(kid[0])
2575
- else:
2576
- raise self.ice()
2263
+ return self.consume(ast.AtomExpr)
2577
2264
 
2578
2265
  def multistring(self, kid: list[ast.AstNode]) -> ast.AtomExpr:
2579
2266
  """Grammar rule.
2580
2267
 
2581
- multistring: (fstring | STRING | DOC_STRING)+
2268
+ multistring: (fstring | STRING)+
2582
2269
  """
2583
2270
  valid_strs = [i for i in kid if isinstance(i, (ast.String, ast.FString))]
2584
2271
  if len(valid_strs) == len(kid):
2585
- return self.nu(
2586
- ast.MultiString(
2587
- strings=valid_strs,
2588
- kid=kid,
2589
- )
2272
+ return ast.MultiString(
2273
+ strings=valid_strs,
2274
+ kid=kid,
2590
2275
  )
2591
2276
  else:
2592
2277
  raise self.ice()
@@ -2598,18 +2283,14 @@ class JacParser(Pass):
2598
2283
  | FSTR_SQ_START fstr_sq_parts FSTR_SQ_END
2599
2284
  """
2600
2285
  if len(kid) == 2:
2601
- return self.nu(
2602
- ast.FString(
2603
- parts=None,
2604
- kid=kid,
2605
- )
2286
+ return ast.FString(
2287
+ parts=None,
2288
+ kid=kid,
2606
2289
  )
2607
2290
  elif isinstance(kid[1], ast.SubNodeList):
2608
- return self.nu(
2609
- ast.FString(
2610
- parts=kid[1],
2611
- kid=kid,
2612
- )
2291
+ return ast.FString(
2292
+ parts=kid[1],
2293
+ kid=kid,
2613
2294
  )
2614
2295
  else:
2615
2296
  raise self.ice()
@@ -2630,12 +2311,10 @@ class JacParser(Pass):
2630
2311
  for i in kid
2631
2312
  if isinstance(i, ast.Expr)
2632
2313
  ]
2633
- return self.nu(
2634
- ast.SubNodeList[ast.String | ast.ExprStmt](
2635
- items=valid_parts,
2636
- delim=None,
2637
- kid=valid_parts,
2638
- )
2314
+ return ast.SubNodeList[ast.String | ast.ExprStmt](
2315
+ items=valid_parts,
2316
+ delim=None,
2317
+ kid=valid_parts,
2639
2318
  )
2640
2319
 
2641
2320
  def fstr_sq_parts(
@@ -2654,12 +2333,10 @@ class JacParser(Pass):
2654
2333
  for i in kid
2655
2334
  if isinstance(i, ast.Expr)
2656
2335
  ]
2657
- return self.nu(
2658
- ast.SubNodeList[ast.String | ast.ExprStmt](
2659
- items=valid_parts,
2660
- delim=None,
2661
- kid=valid_parts,
2662
- )
2336
+ return ast.SubNodeList[ast.String | ast.ExprStmt](
2337
+ items=valid_parts,
2338
+ delim=None,
2339
+ kid=valid_parts,
2663
2340
  )
2664
2341
 
2665
2342
  def list_val(self, kid: list[ast.AstNode]) -> ast.ListVal:
@@ -2668,18 +2345,14 @@ class JacParser(Pass):
2668
2345
  list_val: LSQUARE (expr_list COMMA?)? RSQUARE
2669
2346
  """
2670
2347
  if len(kid) == 2:
2671
- return self.nu(
2672
- ast.ListVal(
2673
- values=None,
2674
- kid=kid,
2675
- )
2348
+ return ast.ListVal(
2349
+ values=None,
2350
+ kid=kid,
2676
2351
  )
2677
- elif isinstance(kid[1], ast.SubNodeList):
2678
- return self.nu(
2679
- ast.ListVal(
2680
- values=kid[1],
2681
- kid=kid,
2682
- )
2352
+ elif isinstance(kid[1], ast.SubNodeList):
2353
+ return ast.ListVal(
2354
+ values=kid[1],
2355
+ kid=kid,
2683
2356
  )
2684
2357
  else:
2685
2358
  raise self.ice()
@@ -2690,18 +2363,14 @@ class JacParser(Pass):
2690
2363
  tuple_val: LPAREN tuple_list? RPAREN
2691
2364
  """
2692
2365
  if len(kid) == 2:
2693
- return self.nu(
2694
- ast.TupleVal(
2695
- values=None,
2696
- kid=kid,
2697
- )
2366
+ return ast.TupleVal(
2367
+ values=None,
2368
+ kid=kid,
2698
2369
  )
2699
2370
  elif isinstance(kid[1], ast.SubNodeList):
2700
- return self.nu(
2701
- ast.TupleVal(
2702
- values=kid[1],
2703
- kid=kid,
2704
- )
2371
+ return ast.TupleVal(
2372
+ values=kid[1],
2373
+ kid=kid,
2705
2374
  )
2706
2375
  else:
2707
2376
  raise self.ice()
@@ -2712,18 +2381,14 @@ class JacParser(Pass):
2712
2381
  set_val: LBRACE expr_list COMMA? RBRACE
2713
2382
  """
2714
2383
  if len(kid) == 2:
2715
- return self.nu(
2716
- ast.SetVal(
2717
- values=None,
2718
- kid=kid,
2719
- )
2384
+ return ast.SetVal(
2385
+ values=None,
2386
+ kid=kid,
2720
2387
  )
2721
2388
  elif isinstance(kid[1], ast.SubNodeList):
2722
- return self.nu(
2723
- ast.SetVal(
2724
- values=kid[1],
2725
- kid=kid,
2726
- )
2389
+ return ast.SetVal(
2390
+ values=kid[1],
2391
+ kid=kid,
2727
2392
  )
2728
2393
  else:
2729
2394
  raise self.ice()
@@ -2745,12 +2410,10 @@ class JacParser(Pass):
2745
2410
  expr = kid[0]
2746
2411
  new_kid = [expr]
2747
2412
  valid_kid = [i for i in new_kid if isinstance(i, ast.Expr)]
2748
- return self.nu(
2749
- ast.SubNodeList[ast.Expr](
2750
- items=valid_kid,
2751
- delim=Tok.COMMA,
2752
- kid=new_kid,
2753
- )
2413
+ return ast.SubNodeList[ast.Expr](
2414
+ items=valid_kid,
2415
+ delim=Tok.COMMA,
2416
+ kid=new_kid,
2754
2417
  )
2755
2418
 
2756
2419
  def kw_expr_list(self, kid: list[ast.AstNode]) -> ast.SubNodeList[ast.KWPair]:
@@ -2770,12 +2433,10 @@ class JacParser(Pass):
2770
2433
  expr = kid[0]
2771
2434
  new_kid = [expr]
2772
2435
  valid_kid = [i for i in new_kid if isinstance(i, ast.KWPair)]
2773
- return self.nu(
2774
- ast.SubNodeList[ast.KWPair](
2775
- items=valid_kid,
2776
- delim=Tok.COMMA,
2777
- kid=new_kid,
2778
- )
2436
+ return ast.SubNodeList[ast.KWPair](
2437
+ items=valid_kid,
2438
+ delim=Tok.COMMA,
2439
+ kid=new_kid,
2779
2440
  )
2780
2441
 
2781
2442
  def kw_expr(self, kid: list[ast.AstNode]) -> ast.KWPair:
@@ -2788,20 +2449,16 @@ class JacParser(Pass):
2788
2449
  and isinstance(kid[0], ast.NameAtom)
2789
2450
  and isinstance(kid[2], ast.Expr)
2790
2451
  ):
2791
- return self.nu(
2792
- ast.KWPair(
2793
- key=kid[0],
2794
- value=kid[2],
2795
- kid=kid,
2796
- )
2452
+ return ast.KWPair(
2453
+ key=kid[0],
2454
+ value=kid[2],
2455
+ kid=kid,
2797
2456
  )
2798
2457
  elif len(kid) == 2 and isinstance(kid[1], ast.Expr):
2799
- return self.nu(
2800
- ast.KWPair(
2801
- key=None,
2802
- value=kid[1],
2803
- kid=kid,
2804
- )
2458
+ return ast.KWPair(
2459
+ key=None,
2460
+ value=kid[1],
2461
+ kid=kid,
2805
2462
  )
2806
2463
  else:
2807
2464
  raise self.ice()
@@ -2812,12 +2469,10 @@ class JacParser(Pass):
2812
2469
  name_list: (named_ref COMMA)* named_ref
2813
2470
  """
2814
2471
  valid_kid = [i for i in kid if isinstance(i, ast.Name)]
2815
- return self.nu(
2816
- ast.SubNodeList[ast.Name](
2817
- items=valid_kid,
2818
- delim=Tok.COMMA,
2819
- kid=kid,
2820
- )
2472
+ return ast.SubNodeList[ast.Name](
2473
+ items=valid_kid,
2474
+ delim=Tok.COMMA,
2475
+ kid=kid,
2821
2476
  )
2822
2477
 
2823
2478
  def tuple_list(
@@ -2840,7 +2495,7 @@ class JacParser(Pass):
2840
2495
  # Add the comma to the subnode list if it exists, otherwise the last comma will not be a part of
2841
2496
  # the ast, we need it for formatting.
2842
2497
  chomp[0].kid.append(chomp[1])
2843
- return self.nu(chomp[0])
2498
+ return chomp[0]
2844
2499
  else:
2845
2500
  # The chomp will be like this:
2846
2501
  # expression, COMMA, [subnode_list, [COMMA, [kw_expr_list, [COMMA]]]]
@@ -2859,12 +2514,10 @@ class JacParser(Pass):
2859
2514
  expr_list = [*expr_list, *chomp[0].kid]
2860
2515
  expr_list = [first_expr, *expr_list]
2861
2516
  valid_kid = [i for i in expr_list if isinstance(i, (ast.Expr, ast.KWPair))]
2862
- return self.nu(
2863
- ast.SubNodeList[ast.Expr | ast.KWPair](
2864
- items=valid_kid,
2865
- delim=Tok.COMMA,
2866
- kid=kid,
2867
- )
2517
+ return ast.SubNodeList[ast.Expr | ast.KWPair](
2518
+ items=valid_kid,
2519
+ delim=Tok.COMMA,
2520
+ kid=kid,
2868
2521
  )
2869
2522
 
2870
2523
  def dict_val(self, kid: list[ast.AstNode]) -> ast.DictVal:
@@ -2877,7 +2530,7 @@ class JacParser(Pass):
2877
2530
  kid=kid,
2878
2531
  )
2879
2532
  ret.kv_pairs = [i for i in kid if isinstance(i, ast.KVPair)]
2880
- return self.nu(ret)
2533
+ return ret
2881
2534
 
2882
2535
  def kv_pair(self, kid: list[ast.AstNode]) -> ast.KVPair:
2883
2536
  """Grammar rule.
@@ -2889,20 +2542,16 @@ class JacParser(Pass):
2889
2542
  and isinstance(kid[0], ast.Expr)
2890
2543
  and isinstance(kid[2], ast.Expr)
2891
2544
  ):
2892
- return self.nu(
2893
- ast.KVPair(
2894
- key=kid[0],
2895
- value=kid[2],
2896
- kid=kid,
2897
- )
2545
+ return ast.KVPair(
2546
+ key=kid[0],
2547
+ value=kid[2],
2548
+ kid=kid,
2898
2549
  )
2899
2550
  elif len(kid) == 2 and isinstance(kid[1], ast.Expr):
2900
- return self.nu(
2901
- ast.KVPair(
2902
- key=None,
2903
- value=kid[1],
2904
- kid=kid,
2905
- )
2551
+ return ast.KVPair(
2552
+ key=None,
2553
+ value=kid[1],
2554
+ kid=kid,
2906
2555
  )
2907
2556
  else:
2908
2557
  raise self.ice()
@@ -2914,12 +2563,10 @@ class JacParser(Pass):
2914
2563
  """
2915
2564
  comprs = [i for i in kid if isinstance(i, ast.InnerCompr)]
2916
2565
  if isinstance(kid[1], ast.Expr):
2917
- return self.nu(
2918
- ast.ListCompr(
2919
- out_expr=kid[1],
2920
- compr=comprs,
2921
- kid=kid,
2922
- )
2566
+ return ast.ListCompr(
2567
+ out_expr=kid[1],
2568
+ compr=comprs,
2569
+ kid=kid,
2923
2570
  )
2924
2571
  else:
2925
2572
  raise self.ice()
@@ -2931,12 +2578,10 @@ class JacParser(Pass):
2931
2578
  """
2932
2579
  comprs = [i for i in kid if isinstance(i, ast.InnerCompr)]
2933
2580
  if isinstance(kid[1], ast.Expr):
2934
- return self.nu(
2935
- ast.GenCompr(
2936
- out_expr=kid[1],
2937
- compr=comprs,
2938
- kid=kid,
2939
- )
2581
+ return ast.GenCompr(
2582
+ out_expr=kid[1],
2583
+ compr=comprs,
2584
+ kid=kid,
2940
2585
  )
2941
2586
  else:
2942
2587
  raise self.ice()
@@ -2948,12 +2593,10 @@ class JacParser(Pass):
2948
2593
  """
2949
2594
  comprs = [i for i in kid if isinstance(i, ast.InnerCompr)]
2950
2595
  if isinstance(kid[1], ast.Expr) and isinstance(kid[2], ast.InnerCompr):
2951
- return self.nu(
2952
- ast.SetCompr(
2953
- out_expr=kid[1],
2954
- compr=comprs,
2955
- kid=kid,
2956
- )
2596
+ return ast.SetCompr(
2597
+ out_expr=kid[1],
2598
+ compr=comprs,
2599
+ kid=kid,
2957
2600
  )
2958
2601
  else:
2959
2602
  raise self.ice()
@@ -2965,12 +2608,10 @@ class JacParser(Pass):
2965
2608
  """
2966
2609
  comprs = [i for i in kid if isinstance(i, ast.InnerCompr)]
2967
2610
  if isinstance(kid[1], ast.KVPair) and isinstance(kid[2], ast.InnerCompr):
2968
- return self.nu(
2969
- ast.DictCompr(
2970
- kv_pair=kid[1],
2971
- compr=comprs,
2972
- kid=kid,
2973
- )
2611
+ return ast.DictCompr(
2612
+ kv_pair=kid[1],
2613
+ compr=comprs,
2614
+ kid=kid,
2974
2615
  )
2975
2616
  else:
2976
2617
  raise self.ice()
@@ -2987,18 +2628,16 @@ class JacParser(Pass):
2987
2628
  chomp = chomp[1:] if is_async else chomp
2988
2629
  chomp = chomp[1:]
2989
2630
  if isinstance(chomp[0], ast.Expr) and isinstance(chomp[2], ast.Expr):
2990
- return self.nu(
2991
- ast.InnerCompr(
2992
- is_async=is_async,
2993
- target=chomp[0],
2994
- collection=chomp[2],
2995
- conditional=(
2996
- [i for i in chomp[4:] if isinstance(i, ast.Expr)]
2997
- if len(chomp) > 4 and isinstance(chomp[4], ast.Expr)
2998
- else None
2999
- ),
3000
- kid=chomp,
3001
- )
2631
+ return ast.InnerCompr(
2632
+ is_async=is_async,
2633
+ target=chomp[0],
2634
+ collection=chomp[2],
2635
+ conditional=(
2636
+ [i for i in chomp[4:] if isinstance(i, ast.Expr)]
2637
+ if len(chomp) > 4 and isinstance(chomp[4], ast.Expr)
2638
+ else None
2639
+ ),
2640
+ kid=chomp,
3002
2641
  )
3003
2642
  else:
3004
2643
  raise self.ice()
@@ -3023,7 +2662,7 @@ class JacParser(Pass):
3023
2662
  ends_with_comma
3024
2663
  ): # Append the trailing comma to the subnode list.
3025
2664
  kid[0].kid.append(kid[1])
3026
- return self.nu(kid[0])
2665
+ return kid[0]
3027
2666
  else:
3028
2667
  raise self.ice()
3029
2668
  elif isinstance(kid[0], ast.SubNodeList) and isinstance(
@@ -3035,12 +2674,10 @@ class JacParser(Pass):
3035
2674
  if isinstance(i, (ast.Expr, ast.KWPair))
3036
2675
  ]
3037
2676
  if len(valid_kid) == len(kid[0].items) + len(kid[2].items):
3038
- return self.nu(
3039
- ast.SubNodeList[ast.Expr | ast.KWPair](
3040
- items=valid_kid,
3041
- delim=Tok.COMMA,
3042
- kid=kid,
3043
- )
2677
+ return ast.SubNodeList[ast.Expr | ast.KWPair](
2678
+ items=valid_kid,
2679
+ delim=Tok.COMMA,
2680
+ kid=kid,
3044
2681
  )
3045
2682
  else:
3046
2683
  raise self.ice()
@@ -3065,12 +2702,10 @@ class JacParser(Pass):
3065
2702
  assign = kid[0]
3066
2703
  new_kid = [assign]
3067
2704
  valid_kid = [i for i in new_kid if isinstance(i, ast.Assignment)]
3068
- return self.nu(
3069
- ast.SubNodeList[ast.Assignment](
3070
- items=valid_kid,
3071
- delim=Tok.COMMA,
3072
- kid=new_kid,
3073
- )
2705
+ return ast.SubNodeList[ast.Assignment](
2706
+ items=valid_kid,
2707
+ delim=Tok.COMMA,
2708
+ kid=new_kid,
3074
2709
  )
3075
2710
 
3076
2711
  def arch_ref(self, kid: list[ast.AstNode]) -> ast.ArchRef:
@@ -3082,159 +2717,125 @@ class JacParser(Pass):
3082
2717
  | node_ref
3083
2718
  | type_ref
3084
2719
  """
3085
- if isinstance(kid[0], ast.ArchRef):
3086
- return self.nu(kid[0])
3087
- else:
3088
- raise self.ice()
2720
+ return self.consume(ast.ArchRef)
3089
2721
 
3090
2722
  def node_ref(self, kid: list[ast.AstNode]) -> ast.ArchRef:
3091
2723
  """Grammar rule.
3092
2724
 
3093
2725
  node_ref: NODE_OP NAME
3094
2726
  """
3095
- if isinstance(kid[0], ast.Token) and isinstance(kid[1], ast.NameAtom):
3096
- return self.nu(
3097
- ast.ArchRef(
3098
- arch_type=kid[0],
3099
- arch_name=kid[1],
3100
- kid=kid,
3101
- )
3102
- )
3103
- else:
3104
- raise self.ice()
2727
+ arch_type = self.consume(ast.Token)
2728
+ arch_name = self.consume(ast.NameAtom)
2729
+ return ast.ArchRef(
2730
+ arch_type=arch_type,
2731
+ arch_name=arch_name,
2732
+ kid=self.cur_nodes,
2733
+ )
3105
2734
 
3106
2735
  def edge_ref(self, kid: list[ast.AstNode]) -> ast.ArchRef:
3107
2736
  """Grammar rule.
3108
2737
 
3109
2738
  edge_ref: EDGE_OP NAME
3110
2739
  """
3111
- if isinstance(kid[0], ast.Token) and isinstance(kid[1], ast.NameAtom):
3112
- return self.nu(
3113
- ast.ArchRef(
3114
- arch_type=kid[0],
3115
- arch_name=kid[1],
3116
- kid=kid,
3117
- )
3118
- )
3119
- else:
3120
- raise self.ice()
2740
+ arch_type = self.consume(ast.Token)
2741
+ arch_name = self.consume(ast.NameAtom)
2742
+ return ast.ArchRef(
2743
+ arch_type=arch_type,
2744
+ arch_name=arch_name,
2745
+ kid=self.cur_nodes,
2746
+ )
3121
2747
 
3122
2748
  def walker_ref(self, kid: list[ast.AstNode]) -> ast.ArchRef:
3123
2749
  """Grammar rule.
3124
2750
 
3125
2751
  walker_ref: WALKER_OP NAME
3126
2752
  """
3127
- if isinstance(kid[0], ast.Token) and isinstance(kid[1], ast.NameAtom):
3128
- return self.nu(
3129
- ast.ArchRef(
3130
- arch_type=kid[0],
3131
- arch_name=kid[1],
3132
- kid=kid,
3133
- )
3134
- )
3135
- else:
3136
- raise self.ice()
2753
+ arch_type = self.consume(ast.Token)
2754
+ arch_name = self.consume(ast.NameAtom)
2755
+ return ast.ArchRef(
2756
+ arch_type=arch_type,
2757
+ arch_name=arch_name,
2758
+ kid=self.cur_nodes,
2759
+ )
3137
2760
 
3138
2761
  def class_ref(self, kid: list[ast.AstNode]) -> ast.ArchRef:
3139
2762
  """Grammar rule.
3140
2763
 
3141
2764
  class_ref: CLASS_OP name_ref
3142
2765
  """
3143
- if isinstance(kid[0], ast.Token) and isinstance(kid[1], ast.NameAtom):
3144
- return self.nu(
3145
- ast.ArchRef(
3146
- arch_type=kid[0],
3147
- arch_name=kid[1],
3148
- kid=kid,
3149
- )
3150
- )
3151
- else:
3152
- raise self.ice()
2766
+ arch_type = self.consume(ast.Token)
2767
+ arch_name = self.consume(ast.NameAtom)
2768
+ return ast.ArchRef(
2769
+ arch_type=arch_type,
2770
+ arch_name=arch_name,
2771
+ kid=self.cur_nodes,
2772
+ )
3153
2773
 
3154
2774
  def object_ref(self, kid: list[ast.AstNode]) -> ast.ArchRef:
3155
2775
  """Grammar rule.
3156
2776
 
3157
2777
  object_ref: OBJECT_OP name_ref
3158
2778
  """
3159
- if isinstance(kid[0], ast.Token) and isinstance(kid[1], ast.NameAtom):
3160
- return self.nu(
3161
- ast.ArchRef(
3162
- arch_type=kid[0],
3163
- arch_name=kid[1],
3164
- kid=kid,
3165
- )
3166
- )
3167
- else:
3168
- raise self.ice()
2779
+ arch_type = self.consume(ast.Token)
2780
+ arch_name = self.consume(ast.NameAtom)
2781
+ return ast.ArchRef(
2782
+ arch_type=arch_type,
2783
+ arch_name=arch_name,
2784
+ kid=self.cur_nodes,
2785
+ )
3169
2786
 
3170
2787
  def type_ref(self, kid: list[ast.AstNode]) -> ast.ArchRef:
3171
2788
  """Grammar rule.
3172
2789
 
3173
2790
  type_ref: TYPE_OP (named_ref | builtin_type)
3174
2791
  """
3175
- if isinstance(kid[0], ast.Token) and isinstance(kid[1], ast.NameAtom):
3176
- return self.nu(
3177
- ast.ArchRef(
3178
- arch_type=kid[0],
3179
- arch_name=kid[1],
3180
- kid=kid,
3181
- )
3182
- )
3183
- else:
3184
- raise self.ice()
2792
+ arch_type = self.consume(ast.Token)
2793
+ arch_name = self.consume(ast.NameAtom)
2794
+ return ast.ArchRef(
2795
+ arch_type=arch_type,
2796
+ arch_name=arch_name,
2797
+ kid=self.cur_nodes,
2798
+ )
3185
2799
 
3186
2800
  def enum_ref(self, kid: list[ast.AstNode]) -> ast.ArchRef:
3187
2801
  """Grammar rule.
3188
2802
 
3189
2803
  enum_ref: ENUM_OP NAME
3190
2804
  """
3191
- if isinstance(kid[0], ast.Token) and isinstance(kid[1], ast.NameAtom):
3192
- return self.nu(
3193
- ast.ArchRef(
3194
- arch_type=kid[0],
3195
- arch_name=kid[1],
3196
- kid=kid,
3197
- )
3198
- )
3199
- else:
3200
- raise self.ice()
2805
+ arch_type = self.consume(ast.Token)
2806
+ arch_name = self.consume(ast.NameAtom)
2807
+ return ast.ArchRef(
2808
+ arch_type=arch_type,
2809
+ arch_name=arch_name,
2810
+ kid=self.cur_nodes,
2811
+ )
3201
2812
 
3202
- def ability_ref(self, kid: list[ast.AstNode]) -> ast.ArchRef:
2813
+ def ability_ref(self, _: None) -> ast.ArchRef:
3203
2814
  """Grammar rule.
3204
2815
 
3205
2816
  ability_ref: ABILITY_OP (special_ref | name_ref)
3206
2817
  """
3207
- if isinstance(kid[0], ast.Token) and isinstance(kid[1], ast.NameAtom):
3208
- return self.nu(
3209
- ast.ArchRef(
3210
- arch_type=kid[0],
3211
- arch_name=kid[1],
3212
- kid=kid,
3213
- )
3214
- )
3215
- else:
3216
- raise self.ice()
2818
+ arch_type = self.consume_token(Tok.ABILITY_OP)
2819
+ arch_name = self.consume(ast.NameAtom)
2820
+ return ast.ArchRef(
2821
+ arch_type=arch_type,
2822
+ arch_name=arch_name,
2823
+ kid=self.cur_nodes,
2824
+ )
3217
2825
 
3218
2826
  def arch_or_ability_chain(self, kid: list[ast.AstNode]) -> ast.ArchRefChain:
3219
2827
  """Grammar rule.
3220
2828
 
3221
2829
  arch_or_ability_chain: arch_or_ability_chain? (ability_ref | arch_ref)
3222
2830
  """
3223
- consume = None
3224
- name = None
3225
- if isinstance(kid[0], ast.SubNodeList):
3226
- consume = kid[0]
3227
- name = kid[1]
3228
- else:
3229
- name = kid[0]
2831
+ consume = self.match(ast.ArchRefChain)
2832
+ name = self.consume(ast.ArchRef)
3230
2833
  new_kid = [*consume.kid, name] if consume else [name]
3231
2834
  valid_kid = [i for i in new_kid if isinstance(i, ast.ArchRef)]
3232
2835
  if len(valid_kid) == len(new_kid):
3233
- return self.nu(
3234
- ast.ArchRefChain(
3235
- archs=valid_kid,
3236
- kid=new_kid,
3237
- )
2836
+ return ast.ArchRefChain(
2837
+ archs=valid_kid,
2838
+ kid=new_kid,
3238
2839
  )
3239
2840
  else:
3240
2841
  raise self.ice()
@@ -3248,20 +2849,16 @@ class JacParser(Pass):
3248
2849
  if isinstance(kid[1], ast.ArchRef) and isinstance(
3249
2850
  kid[0], ast.ArchRefChain
3250
2851
  ):
3251
- return self.nu(
3252
- ast.ArchRefChain(
3253
- archs=[*(kid[0].archs), kid[1]],
3254
- kid=[*(kid[0].kid), kid[1]],
3255
- )
2852
+ return ast.ArchRefChain(
2853
+ archs=[*(kid[0].archs), kid[1]],
2854
+ kid=[*(kid[0].kid), kid[1]],
3256
2855
  )
3257
2856
  else:
3258
2857
  raise self.ice()
3259
2858
  elif isinstance(kid[0], ast.ArchRef):
3260
- return self.nu(
3261
- ast.ArchRefChain(
3262
- archs=[kid[0]],
3263
- kid=kid,
3264
- )
2859
+ return ast.ArchRefChain(
2860
+ archs=[kid[0]],
2861
+ kid=kid,
3265
2862
  )
3266
2863
  else:
3267
2864
  raise self.ice()
@@ -3275,20 +2872,16 @@ class JacParser(Pass):
3275
2872
  if isinstance(kid[1], ast.ArchRef) and isinstance(
3276
2873
  kid[0], ast.ArchRefChain
3277
2874
  ):
3278
- return self.nu(
3279
- ast.ArchRefChain(
3280
- archs=[*(kid[0].archs), kid[1]],
3281
- kid=[*(kid[0].kid), kid[1]],
3282
- )
2875
+ return ast.ArchRefChain(
2876
+ archs=[*(kid[0].archs), kid[1]],
2877
+ kid=[*(kid[0].kid), kid[1]],
3283
2878
  )
3284
2879
  else:
3285
2880
  raise self.ice()
3286
2881
  elif isinstance(kid[0], ast.ArchRef):
3287
- return self.nu(
3288
- ast.ArchRefChain(
3289
- archs=[kid[0]],
3290
- kid=kid,
3291
- )
2882
+ return ast.ArchRefChain(
2883
+ archs=[kid[0]],
2884
+ kid=kid,
3292
2885
  )
3293
2886
  else:
3294
2887
  raise self.ice()
@@ -3302,20 +2895,16 @@ class JacParser(Pass):
3302
2895
  if isinstance(kid[1], ast.ArchRef) and isinstance(
3303
2896
  kid[0], ast.ArchRefChain
3304
2897
  ):
3305
- return self.nu(
3306
- ast.ArchRefChain(
3307
- archs=[*(kid[0].archs), kid[1]],
3308
- kid=[*(kid[0].kid), kid[1]],
3309
- )
2898
+ return ast.ArchRefChain(
2899
+ archs=[*(kid[0].archs), kid[1]],
2900
+ kid=[*(kid[0].kid), kid[1]],
3310
2901
  )
3311
2902
  else:
3312
2903
  raise self.ice()
3313
2904
  elif isinstance(kid[0], ast.ArchRef):
3314
- return self.nu(
3315
- ast.ArchRefChain(
3316
- archs=[kid[0]],
3317
- kid=kid,
3318
- )
2905
+ return ast.ArchRefChain(
2906
+ archs=[kid[0]],
2907
+ kid=kid,
3319
2908
  )
3320
2909
  else:
3321
2910
  raise self.ice()
@@ -3326,13 +2915,10 @@ class JacParser(Pass):
3326
2915
  (EDGE_OP|NODE_OP)? LSQUARE expression? (edge_op_ref (filter_compr | expression)?)+ RSQUARE
3327
2916
  """
3328
2917
  valid_chain = [i for i in kid if isinstance(i, (ast.Expr, ast.FilterCompr))]
3329
- return self.nu(
3330
- ast.EdgeRefTrailer(
3331
- chain=valid_chain,
3332
- edges_only=isinstance(kid[0], ast.Token)
3333
- and kid[0].name == Tok.EDGE_OP,
3334
- kid=kid,
3335
- )
2918
+ return ast.EdgeRefTrailer(
2919
+ chain=valid_chain,
2920
+ edges_only=isinstance(kid[0], ast.Token) and kid[0].name == Tok.EDGE_OP,
2921
+ kid=kid,
3336
2922
  )
3337
2923
 
3338
2924
  def edge_op_ref(self, kid: list[ast.AstNode]) -> ast.EdgeOpRef:
@@ -3340,10 +2926,7 @@ class JacParser(Pass):
3340
2926
 
3341
2927
  edge_op_ref: (edge_any | edge_from | edge_to)
3342
2928
  """
3343
- if isinstance(kid[0], ast.EdgeOpRef):
3344
- return self.nu(kid[0])
3345
- else:
3346
- raise self.ice()
2929
+ return self.consume(ast.EdgeOpRef)
3347
2930
 
3348
2931
  def edge_to(self, kid: list[ast.AstNode]) -> ast.EdgeOpRef:
3349
2932
  """Grammar rule.
@@ -3353,9 +2936,7 @@ class JacParser(Pass):
3353
2936
  """
3354
2937
  fcond = kid[1] if len(kid) > 1 else None
3355
2938
  if isinstance(fcond, ast.FilterCompr) or fcond is None:
3356
- return self.nu(
3357
- ast.EdgeOpRef(filter_cond=fcond, edge_dir=EdgeDir.OUT, kid=kid)
3358
- )
2939
+ return ast.EdgeOpRef(filter_cond=fcond, edge_dir=EdgeDir.OUT, kid=kid)
3359
2940
  else:
3360
2941
  raise self.ice()
3361
2942
 
@@ -3367,9 +2948,7 @@ class JacParser(Pass):
3367
2948
  """
3368
2949
  fcond = kid[1] if len(kid) > 1 else None
3369
2950
  if isinstance(fcond, ast.FilterCompr) or fcond is None:
3370
- return self.nu(
3371
- ast.EdgeOpRef(filter_cond=fcond, edge_dir=EdgeDir.IN, kid=kid)
3372
- )
2951
+ return ast.EdgeOpRef(filter_cond=fcond, edge_dir=EdgeDir.IN, kid=kid)
3373
2952
  else:
3374
2953
  raise self.ice()
3375
2954
 
@@ -3381,9 +2960,7 @@ class JacParser(Pass):
3381
2960
  """
3382
2961
  fcond = kid[1] if len(kid) > 1 else None
3383
2962
  if isinstance(fcond, ast.FilterCompr) or fcond is None:
3384
- return self.nu(
3385
- ast.EdgeOpRef(filter_cond=fcond, edge_dir=EdgeDir.ANY, kid=kid)
3386
- )
2963
+ return ast.EdgeOpRef(filter_cond=fcond, edge_dir=EdgeDir.ANY, kid=kid)
3387
2964
  else:
3388
2965
  raise self.ice()
3389
2966
 
@@ -3393,7 +2970,7 @@ class JacParser(Pass):
3393
2970
  connect_op: connect_from | connect_to | connect_any
3394
2971
  """
3395
2972
  if len(kid) < 2 and isinstance(kid[0], ast.ConnectOp):
3396
- return self.nu(kid[0])
2973
+ return kid[0]
3397
2974
  else:
3398
2975
  raise self.ice()
3399
2976
 
@@ -3403,11 +2980,9 @@ class JacParser(Pass):
3403
2980
  disconnect_op: NOT edge_op_ref
3404
2981
  """
3405
2982
  if isinstance(kid[1], ast.EdgeOpRef):
3406
- return self.nu(
3407
- ast.DisconnectOp(
3408
- edge_spec=kid[1],
3409
- kid=kid,
3410
- )
2983
+ return ast.DisconnectOp(
2984
+ edge_spec=kid[1],
2985
+ kid=kid,
3411
2986
  )
3412
2987
  else:
3413
2988
  raise self.ice()
@@ -3430,13 +3005,11 @@ class JacParser(Pass):
3430
3005
  )
3431
3006
  if conn_assign:
3432
3007
  kid[3] = conn_assign
3433
- return self.nu(
3434
- ast.ConnectOp(
3435
- conn_type=conn_type,
3436
- conn_assign=conn_assign,
3437
- edge_dir=EdgeDir.OUT,
3438
- kid=kid,
3439
- )
3008
+ return ast.ConnectOp(
3009
+ conn_type=conn_type,
3010
+ conn_assign=conn_assign,
3011
+ edge_dir=EdgeDir.OUT,
3012
+ kid=kid,
3440
3013
  )
3441
3014
  else:
3442
3015
  raise self.ice()
@@ -3459,13 +3032,11 @@ class JacParser(Pass):
3459
3032
  )
3460
3033
  if conn_assign:
3461
3034
  kid[3] = conn_assign
3462
- return self.nu(
3463
- ast.ConnectOp(
3464
- conn_type=conn_type,
3465
- conn_assign=conn_assign,
3466
- edge_dir=EdgeDir.IN,
3467
- kid=kid,
3468
- )
3035
+ return ast.ConnectOp(
3036
+ conn_type=conn_type,
3037
+ conn_assign=conn_assign,
3038
+ edge_dir=EdgeDir.IN,
3039
+ kid=kid,
3469
3040
  )
3470
3041
  else:
3471
3042
  raise self.ice()
@@ -3487,13 +3058,11 @@ class JacParser(Pass):
3487
3058
  )
3488
3059
  if conn_assign:
3489
3060
  kid[3] = conn_assign
3490
- return self.nu(
3491
- ast.ConnectOp(
3492
- conn_type=conn_type,
3493
- conn_assign=conn_assign,
3494
- edge_dir=EdgeDir.ANY,
3495
- kid=kid,
3496
- )
3061
+ return ast.ConnectOp(
3062
+ conn_type=conn_type,
3063
+ conn_assign=conn_assign,
3064
+ edge_dir=EdgeDir.ANY,
3065
+ kid=kid,
3497
3066
  )
3498
3067
  else:
3499
3068
  raise self.ice()
@@ -3505,11 +3074,11 @@ class JacParser(Pass):
3505
3074
  | LPAREN TYPE_OP NULL_OK typed_filter_compare_list RPAREN
3506
3075
  """
3507
3076
  if isinstance(kid[2], ast.SubNodeList):
3508
- return self.nu(ast.FilterCompr(compares=kid[2], f_type=None, kid=kid))
3077
+ return ast.FilterCompr(compares=kid[2], f_type=None, kid=kid)
3509
3078
  elif isinstance(kid[3], ast.FilterCompr):
3510
3079
  kid[3].add_kids_left(kid[:3])
3511
3080
  kid[3].add_kids_right(kid[4:])
3512
- return self.nu(kid[3])
3081
+ return kid[3]
3513
3082
  else:
3514
3083
  raise self.ice()
3515
3084
 
@@ -3532,12 +3101,10 @@ class JacParser(Pass):
3532
3101
  expr = kid[0]
3533
3102
  new_kid = [expr]
3534
3103
  valid_kid = [i for i in new_kid if isinstance(i, ast.CompareExpr)]
3535
- return self.nu(
3536
- ast.SubNodeList[ast.CompareExpr](
3537
- items=valid_kid,
3538
- delim=Tok.COMMA,
3539
- kid=new_kid,
3540
- )
3104
+ return ast.SubNodeList[ast.CompareExpr](
3105
+ items=valid_kid,
3106
+ delim=Tok.COMMA,
3107
+ kid=new_kid,
3541
3108
  )
3542
3109
 
3543
3110
  def typed_filter_compare_list(self, kid: list[ast.AstNode]) -> ast.FilterCompr:
@@ -3558,7 +3125,7 @@ class JacParser(Pass):
3558
3125
  if isinstance(expr, ast.Expr) and (
3559
3126
  (isinstance(compares, ast.SubNodeList)) or compares is None
3560
3127
  ):
3561
- return self.nu(ast.FilterCompr(compares=compares, f_type=expr, kid=kid))
3128
+ return ast.FilterCompr(compares=compares, f_type=expr, kid=kid)
3562
3129
  else:
3563
3130
  raise self.ice()
3564
3131
 
@@ -3569,110 +3136,95 @@ class JacParser(Pass):
3569
3136
  """
3570
3137
  ret = self.compare(kid)
3571
3138
  if isinstance(ret, ast.CompareExpr):
3572
- return self.nu(ret)
3139
+ return ret
3573
3140
  else:
3574
3141
  raise self.ice()
3575
3142
 
3576
- def assign_compr(self, kid: list[ast.AstNode]) -> ast.AssignCompr:
3143
+ def assign_compr(self, _: None) -> ast.AssignCompr:
3577
3144
  """Grammar rule.
3578
3145
 
3579
3146
  filter_compr: LPAREN EQ kw_expr_list RPAREN
3580
3147
  """
3581
- if isinstance(kid[2], ast.SubNodeList):
3582
- return self.nu(
3583
- ast.AssignCompr(
3584
- assigns=kid[2],
3585
- kid=kid,
3586
- )
3587
- )
3588
- else:
3589
- raise self.ice()
3148
+ self.consume_token(Tok.LPAREN)
3149
+ self.consume_token(Tok.EQ)
3150
+ assigns = self.consume(ast.SubNodeList)
3151
+ self.consume_token(Tok.RPAREN)
3152
+ return ast.AssignCompr(assigns=assigns, kid=self.cur_nodes)
3590
3153
 
3591
- def match_stmt(self, kid: list[ast.AstNode]) -> ast.MatchStmt:
3154
+ def match_stmt(self, _: None) -> ast.MatchStmt:
3592
3155
  """Grammar rule.
3593
3156
 
3594
3157
  match_stmt: KW_MATCH expr_list LBRACE match_case_block+ RBRACE
3595
3158
  """
3596
- cases = [i for i in kid if isinstance(i, ast.MatchCase)]
3597
- if isinstance(kid[1], ast.Expr):
3598
- return self.nu(
3599
- ast.MatchStmt(
3600
- target=kid[1],
3601
- cases=cases,
3602
- kid=kid,
3603
- )
3604
- )
3605
- else:
3606
- raise self.ice()
3159
+ self.consume_token(Tok.KW_MATCH)
3160
+ target = self.consume(ast.Expr)
3161
+ self.consume_token(Tok.LBRACE)
3162
+ cases = [self.consume(ast.MatchCase)]
3163
+ while case := self.match(ast.MatchCase):
3164
+ cases.append(case)
3165
+ self.consume_token(Tok.RBRACE)
3166
+ return ast.MatchStmt(
3167
+ target=target,
3168
+ cases=cases,
3169
+ kid=self.cur_nodes,
3170
+ )
3607
3171
 
3608
- def match_case_block(self, kid: list[ast.AstNode]) -> ast.MatchCase:
3172
+ def match_case_block(self, _: None) -> ast.MatchCase:
3609
3173
  """Grammar rule.
3610
3174
 
3611
3175
  match_case_block: KW_CASE pattern_seq (KW_IF expression)? COLON statement_list
3612
3176
  """
3613
- pattern = kid[1]
3614
- guard = kid[3] if isinstance(kid[3], ast.Expr) else None
3615
- stmts = [i for i in kid if isinstance(i, ast.CodeBlockStmt)]
3616
- if isinstance(pattern, ast.MatchPattern) and isinstance(
3617
- guard, (ast.Expr, type(None))
3618
- ):
3619
- return self.nu(
3620
- ast.MatchCase(
3621
- pattern=pattern,
3622
- guard=guard,
3623
- body=stmts,
3624
- kid=kid,
3625
- )
3626
- )
3627
- else:
3628
- raise self.ice()
3177
+ guard: ast.Expr | None = None
3178
+ self.consume_token(Tok.KW_CASE)
3179
+ pattern = self.consume(ast.MatchPattern)
3180
+ if self.match_token(Tok.KW_IF):
3181
+ guard = self.consume(ast.Expr)
3182
+ self.consume_token(Tok.COLON)
3183
+ stmts = [self.consume(ast.CodeBlockStmt)]
3184
+ while stmt := self.match(ast.CodeBlockStmt):
3185
+ stmts.append(stmt)
3186
+ return ast.MatchCase(
3187
+ pattern=pattern,
3188
+ guard=guard,
3189
+ body=stmts,
3190
+ kid=self.cur_nodes,
3191
+ )
3629
3192
 
3630
- def pattern_seq(self, kid: list[ast.AstNode]) -> ast.MatchPattern:
3193
+ def pattern_seq(self, _: None) -> ast.MatchPattern:
3631
3194
  """Grammar rule.
3632
3195
 
3633
3196
  pattern_seq: (or_pattern | as_pattern)
3634
3197
  """
3635
- if isinstance(kid[0], ast.MatchPattern):
3636
- return self.nu(kid[0])
3637
- else:
3638
- raise self.ice()
3198
+ return self.consume(ast.MatchPattern)
3639
3199
 
3640
- def or_pattern(self, kid: list[ast.AstNode]) -> ast.MatchPattern:
3200
+ def or_pattern(self, _: None) -> ast.MatchPattern:
3641
3201
  """Grammar rule.
3642
3202
 
3643
3203
  or_pattern: (pattern BW_OR)* pattern
3644
3204
  """
3645
- if len(kid) == 1:
3646
- if isinstance(kid[0], ast.MatchPattern):
3647
- return self.nu(kid[0])
3648
- else:
3649
- raise self.ice()
3650
- else:
3651
- patterns = [i for i in kid if isinstance(i, ast.MatchPattern)]
3652
- return self.nu(
3653
- ast.MatchOr(
3654
- patterns=patterns,
3655
- kid=kid,
3656
- )
3657
- )
3205
+ patterns: list = [self.consume(ast.MatchPattern)]
3206
+ while self.match_token(Tok.BW_OR):
3207
+ patterns.append(self.consume(ast.MatchPattern))
3208
+ if len(patterns) == 1:
3209
+ return patterns[0]
3210
+ return ast.MatchOr(
3211
+ patterns=patterns,
3212
+ kid=self.cur_nodes,
3213
+ )
3658
3214
 
3659
- def as_pattern(self, kid: list[ast.AstNode]) -> ast.MatchPattern:
3215
+ def as_pattern(self, _: None) -> ast.MatchPattern:
3660
3216
  """Grammar rule.
3661
3217
 
3662
3218
  as_pattern: pattern KW_AS NAME
3663
3219
  """
3664
- if isinstance(kid[0], ast.MatchPattern) and isinstance(
3665
- kid[2], ast.NameAtom
3666
- ):
3667
- return self.nu(
3668
- ast.MatchAs(
3669
- pattern=kid[0],
3670
- name=kid[2],
3671
- kid=kid,
3672
- )
3673
- )
3674
- else:
3675
- raise self.ice()
3220
+ pattern = self.consume(ast.MatchPattern)
3221
+ self.consume_token(Tok.KW_AS)
3222
+ name = self.consume(ast.NameAtom)
3223
+ return ast.MatchAs(
3224
+ pattern=pattern,
3225
+ name=name,
3226
+ kid=self.cur_nodes,
3227
+ )
3676
3228
 
3677
3229
  def pattern(self, kid: list[ast.AstNode]) -> ast.MatchPattern:
3678
3230
  """Grammar rule.
@@ -3683,141 +3235,109 @@ class JacParser(Pass):
3683
3235
  | mapping_pattern
3684
3236
  | class_pattern
3685
3237
  """
3686
- if isinstance(kid[0], ast.MatchPattern):
3687
- return self.nu(kid[0])
3688
- else:
3689
- raise self.ice()
3238
+ return self.consume(ast.MatchPattern)
3690
3239
 
3691
- def literal_pattern(self, kid: list[ast.AstNode]) -> ast.MatchPattern:
3240
+ def literal_pattern(self, _: None) -> ast.MatchPattern:
3692
3241
  """Grammar rule.
3693
3242
 
3694
3243
  literal_pattern: (INT | FLOAT | multistring)
3695
3244
  """
3696
- if isinstance(kid[0], ast.Expr):
3697
- return self.nu(
3698
- ast.MatchValue(
3699
- value=kid[0],
3700
- kid=kid,
3701
- )
3702
- )
3703
- else:
3704
- raise self.ice()
3245
+ value = self.consume(ast.Expr)
3246
+ return ast.MatchValue(
3247
+ value=value,
3248
+ kid=self.cur_nodes,
3249
+ )
3705
3250
 
3706
- def singleton_pattern(self, kid: list[ast.AstNode]) -> ast.MatchPattern:
3251
+ def singleton_pattern(self, _: None) -> ast.MatchPattern:
3707
3252
  """Grammar rule.
3708
3253
 
3709
3254
  singleton_pattern: (NULL | BOOL)
3710
3255
  """
3711
- if isinstance(kid[0], (ast.Bool, ast.Null)):
3712
- return self.nu(
3713
- ast.MatchSingleton(
3714
- value=kid[0],
3715
- kid=kid,
3716
- )
3717
- )
3718
- else:
3719
- raise self.ice()
3256
+ value = self.match(ast.Null) or self.consume(ast.Bool)
3257
+ return ast.MatchSingleton(
3258
+ value=value,
3259
+ kid=self.cur_nodes,
3260
+ )
3720
3261
 
3721
- def capture_pattern(self, kid: list[ast.AstNode]) -> ast.MatchPattern:
3262
+ def capture_pattern(self, _: None) -> ast.MatchPattern:
3722
3263
  """Grammar rule.
3723
3264
 
3724
3265
  capture_pattern: NAME
3725
3266
  """
3726
- if (
3727
- len(kid) == 1
3728
- and isinstance(kid[0], ast.Name)
3729
- and kid[0].sym_name == "_"
3730
- ):
3731
- return self.nu(
3732
- ast.MatchWild(
3733
- kid=kid,
3734
- )
3735
- )
3736
- if isinstance(kid[0], ast.NameAtom):
3737
- return self.nu(
3738
- ast.MatchAs(
3739
- name=kid[0],
3740
- pattern=None,
3741
- kid=kid,
3742
- )
3267
+ name = self.consume(ast.Name)
3268
+ if name.sym_name == "_":
3269
+ return ast.MatchWild(
3270
+ kid=self.cur_nodes,
3743
3271
  )
3744
- else:
3745
- raise self.ice()
3272
+ return ast.MatchAs(
3273
+ name=name,
3274
+ pattern=None,
3275
+ kid=self.cur_nodes,
3276
+ )
3746
3277
 
3747
- def sequence_pattern(self, kid: list[ast.AstNode]) -> ast.MatchPattern:
3278
+ def sequence_pattern(self, _: None) -> ast.MatchPattern:
3748
3279
  """Grammar rule.
3749
3280
 
3750
3281
  sequence_pattern: LSQUARE list_inner_pattern (COMMA list_inner_pattern)* RSQUARE
3751
3282
  | LPAREN list_inner_pattern (COMMA list_inner_pattern)* RPAREN
3752
3283
  """
3753
- patterns = [i for i in kid if isinstance(i, ast.MatchPattern)]
3754
- return self.nu(
3755
- ast.MatchSequence(
3756
- values=patterns,
3757
- kid=kid,
3758
- )
3284
+ self.consume_token(Tok.LSQUARE) or self.consume_token(Tok.LPAREN)
3285
+ patterns = [self.consume(ast.MatchPattern)]
3286
+ while self.match_token(Tok.COMMA):
3287
+ patterns.append(self.consume(ast.MatchPattern))
3288
+ self.consume_token(Tok.RSQUARE) or self.consume_token(Tok.RPAREN)
3289
+ return ast.MatchSequence(
3290
+ values=patterns,
3291
+ kid=self.cur_nodes,
3759
3292
  )
3760
3293
 
3761
- def mapping_pattern(self, kid: list[ast.AstNode]) -> ast.MatchMapping:
3294
+ def mapping_pattern(self, _: None) -> ast.MatchMapping:
3762
3295
  """Grammar rule.
3763
3296
 
3764
3297
  mapping_pattern: LBRACE (dict_inner_pattern (COMMA dict_inner_pattern)*)? RBRACE
3765
3298
  """
3766
- patterns = [
3767
- i for i in kid if isinstance(i, (ast.MatchKVPair, ast.MatchStar))
3768
- ]
3769
- return self.nu(
3770
- ast.MatchMapping(
3771
- values=patterns,
3772
- kid=kid,
3299
+ self.consume_token(Tok.LBRACE)
3300
+ patterns = [self.match(ast.MatchKVPair) or self.consume(ast.MatchStar)]
3301
+ while self.match_token(Tok.COMMA):
3302
+ patterns.append(
3303
+ self.match(ast.MatchKVPair) or self.consume(ast.MatchStar)
3773
3304
  )
3305
+ self.consume_token(Tok.RBRACE)
3306
+ return ast.MatchMapping(
3307
+ values=patterns,
3308
+ kid=self.cur_nodes,
3774
3309
  )
3775
3310
 
3776
- def list_inner_pattern(self, kid: list[ast.AstNode]) -> ast.MatchPattern:
3311
+ def list_inner_pattern(self, _: None) -> ast.MatchPattern:
3777
3312
  """Grammar rule.
3778
3313
 
3779
3314
  list_inner_pattern: (pattern_seq | STAR_MUL NAME)
3780
3315
  """
3781
- if isinstance(kid[0], ast.MatchPattern):
3782
- return self.nu(kid[0])
3783
- elif isinstance(kid[-1], ast.Name):
3784
- return self.nu(
3785
- ast.MatchStar(
3786
- is_list=True,
3787
- name=kid[-1],
3788
- kid=kid,
3789
- )
3316
+ if self.match_token(Tok.STAR_MUL):
3317
+ name = self.consume(ast.Name)
3318
+ return ast.MatchStar(
3319
+ is_list=True,
3320
+ name=name,
3321
+ kid=self.cur_nodes,
3790
3322
  )
3791
- else:
3792
- raise self.ice()
3323
+ return self.consume(ast.MatchPattern)
3793
3324
 
3794
- def dict_inner_pattern(
3795
- self, kid: list[ast.AstNode]
3796
- ) -> ast.MatchKVPair | ast.MatchStar:
3325
+ def dict_inner_pattern(self, _: None) -> ast.MatchKVPair | ast.MatchStar:
3797
3326
  """Grammar rule.
3798
3327
 
3799
3328
  dict_inner_pattern: (pattern_seq COLON pattern_seq | STAR_POW NAME)
3800
3329
  """
3801
- if isinstance(kid[0], ast.MatchPattern) and isinstance(
3802
- kid[2], ast.MatchPattern
3803
- ):
3804
- return self.nu(
3805
- ast.MatchKVPair(
3806
- key=kid[0],
3807
- value=kid[2],
3808
- kid=kid,
3809
- )
3810
- )
3811
- elif isinstance(kid[-1], ast.Name):
3812
- return self.nu(
3813
- ast.MatchStar(
3814
- is_list=False,
3815
- name=kid[-1],
3816
- kid=kid,
3817
- )
3330
+ if self.match_token(Tok.STAR_POW):
3331
+ name = self.consume(ast.Name)
3332
+ return ast.MatchStar(
3333
+ is_list=False,
3334
+ name=name,
3335
+ kid=self.cur_nodes,
3818
3336
  )
3819
- else:
3820
- raise self.ice()
3337
+ pattern = self.consume(ast.MatchPattern)
3338
+ self.consume_token(Tok.COLON)
3339
+ value = self.consume(ast.MatchPattern)
3340
+ return ast.MatchKVPair(key=pattern, value=value, kid=self.cur_nodes)
3821
3341
 
3822
3342
  def class_pattern(self, kid: list[ast.AstNode]) -> ast.MatchArch:
3823
3343
  """Grammar rule.
@@ -3886,13 +3406,11 @@ class JacParser(Pass):
3886
3406
  kid_nodes.append(kw)
3887
3407
  kid_nodes.append(rapren)
3888
3408
 
3889
- return self.nu(
3890
- ast.MatchArch(
3891
- name=name,
3892
- arg_patterns=arg,
3893
- kw_patterns=kw,
3894
- kid=kid_nodes,
3895
- )
3409
+ return ast.MatchArch(
3410
+ name=name,
3411
+ arg_patterns=arg,
3412
+ kw_patterns=kw,
3413
+ kid=kid_nodes,
3896
3414
  )
3897
3415
  else:
3898
3416
  raise self.ice()
@@ -3998,7 +3516,6 @@ class JacParser(Pass):
3998
3516
  Tok.FSTR_BESC,
3999
3517
  Tok.FSTR_PIECE,
4000
3518
  Tok.FSTR_SQ_PIECE,
4001
- Tok.DOC_STRING,
4002
3519
  ]:
4003
3520
  ret_type = ast.String
4004
3521
  if token.type == Tok.FSTR_BESC:
@@ -4027,4 +3544,4 @@ class JacParser(Pass):
4027
3544
  err.column = ret.loc.col_start
4028
3545
  raise err
4029
3546
  self.terminals.append(ret)
4030
- return self.nu(ret)
3547
+ return ret