11import ast
2- from dataclasses import dataclass
2+ from dataclasses import field , dataclass
33import re
44from typing import Any , Dict , IO , Optional , List , Text , Tuple , Set
55from enum import Enum
2525)
2626from pegen .parser_generator import ParserGenerator
2727
28+
2829EXTENSION_PREFIX = """\
2930 #include "pegen.h"
3031
@@ -63,7 +64,7 @@ class NodeTypes(Enum):
6364@dataclass
6465class FunctionCall :
6566 function : str
66- arguments : Optional [ List [Any ]] = None
67+ arguments : List [Any ] = field ( default_factory = list )
6768 assigned_variable : Optional [str ] = None
6869 return_type : Optional [str ] = None
6970 nodetype : Optional [NodeTypes ] = None
@@ -94,7 +95,7 @@ def __init__(
9495 self .gen = parser_generator
9596 self .exact_tokens = exact_tokens
9697 self .non_exact_tokens = non_exact_tokens
97- self .cache : Dict [Any , Any ] = {}
98+ self .cache : Dict [Any , FunctionCall ] = {}
9899 self .keyword_cache : Dict [str , int ] = {}
99100
100101 def keyword_helper (self , keyword : str ) -> FunctionCall :
@@ -171,7 +172,7 @@ def can_we_inline(node: Rhs) -> int:
171172 if node in self .cache :
172173 return self .cache [node ]
173174 if can_we_inline (node ):
174- self .cache [node ] = self .visit (node .alts [0 ].items [0 ])
175+ self .cache [node ] = self .generate_call (node .alts [0 ].items [0 ])
175176 else :
176177 name = self .gen .name_node (node )
177178 self .cache [node ] = FunctionCall (
@@ -183,13 +184,13 @@ def can_we_inline(node: Rhs) -> int:
183184 return self .cache [node ]
184185
185186 def visit_NamedItem (self , node : NamedItem ) -> FunctionCall :
186- call = self .visit (node .item )
187+ call = self .generate_call (node .item )
187188 if node .name :
188189 call .assigned_variable = node .name
189190 return call
190191
191192 def lookahead_call_helper (self , node : Lookahead , positive : int ) -> FunctionCall :
192- call = self .visit (node .node )
193+ call = self .generate_call (node .node )
193194 if call .nodetype == NodeTypes .NAME_TOKEN :
194195 return FunctionCall (
195196 function = f"_PyPegen_lookahead_with_name" ,
@@ -217,7 +218,7 @@ def visit_NegativeLookahead(self, node: NegativeLookahead) -> FunctionCall:
217218 return self .lookahead_call_helper (node , 0 )
218219
219220 def visit_Opt (self , node : Opt ) -> FunctionCall :
220- call = self .visit (node .node )
221+ call = self .generate_call (node .node )
221222 return FunctionCall (
222223 assigned_variable = "_opt_var" ,
223224 function = call .function ,
@@ -266,7 +267,7 @@ def visit_Gather(self, node: Gather) -> FunctionCall:
266267 return self .cache [node ]
267268
268269 def visit_Group (self , node : Group ) -> FunctionCall :
269- return self .visit (node .rhs )
270+ return self .generate_call (node .rhs )
270271
271272 def visit_Cut (self , node : Cut ) -> FunctionCall :
272273 return FunctionCall (
@@ -276,6 +277,9 @@ def visit_Cut(self, node: Cut) -> FunctionCall:
276277 nodetype = NodeTypes .CUT_OPERATOR ,
277278 )
278279
280+ def generate_call (self , node : Any ) -> FunctionCall :
281+ return super ().visit (node )
282+
279283
280284class CParserGenerator (ParserGenerator , GrammarVisitor ):
281285 def __init__ (
@@ -317,17 +321,13 @@ def call_with_errorcheck_goto(self, call_text: str, goto_target: str) -> None:
317321 self .print (f"goto { goto_target } ;" )
318322 self .print (f"}}" )
319323
320- def out_of_memory_return (
321- self ,
322- expr : str ,
323- cleanup_code : Optional [str ] = None ,
324- ) -> None :
324+ def out_of_memory_return (self , expr : str , cleanup_code : Optional [str ] = None ,) -> None :
325325 self .print (f"if ({ expr } ) {{" )
326326 with self .indent ():
327327 if cleanup_code is not None :
328328 self .print (cleanup_code )
329329 self .print ("p->error_indicator = 1;" )
330- self .print ("PyErr_NoMemory();" );
330+ self .print ("PyErr_NoMemory();" )
331331 self .print ("return NULL;" )
332332 self .print (f"}}" )
333333
@@ -484,10 +484,7 @@ def _handle_default_rule_body(self, node: Rule, rhs: Rhs, result_type: str) -> N
484484 if any (alt .action and "EXTRA" in alt .action for alt in rhs .alts ):
485485 self ._set_up_token_start_metadata_extraction ()
486486 self .visit (
487- rhs ,
488- is_loop = False ,
489- is_gather = node .is_gather (),
490- rulename = node .name ,
487+ rhs , is_loop = False , is_gather = node .is_gather (), rulename = node .name ,
491488 )
492489 if self .debug :
493490 self .print ('fprintf(stderr, "Fail at %d: {node.name}\\ n", p->mark);' )
@@ -518,10 +515,7 @@ def _handle_loop_rule_body(self, node: Rule, rhs: Rhs) -> None:
518515 if any (alt .action and "EXTRA" in alt .action for alt in rhs .alts ):
519516 self ._set_up_token_start_metadata_extraction ()
520517 self .visit (
521- rhs ,
522- is_loop = True ,
523- is_gather = node .is_gather (),
524- rulename = node .name ,
518+ rhs , is_loop = True , is_gather = node .is_gather (), rulename = node .name ,
525519 )
526520 if is_repeat1 :
527521 self .print ("if (_n == 0 || p->error_indicator) {" )
@@ -567,7 +561,7 @@ def visit_Rule(self, node: Rule) -> None:
567561 self .print ("}" )
568562
569563 def visit_NamedItem (self , node : NamedItem ) -> None :
570- call = self .callmakervisitor .visit (node )
564+ call = self .callmakervisitor .generate_call (node )
571565 if call .assigned_variable :
572566 call .assigned_variable = self .dedupe (call .assigned_variable )
573567 self .print (call )
@@ -674,7 +668,9 @@ def handle_alt_loop(self, node: Alt, is_gather: bool, rulename: Optional[str]) -
674668 self .print ("if (_n == _children_capacity) {" )
675669 with self .indent ():
676670 self .print ("_children_capacity *= 2;" )
677- self .print ("void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));" )
671+ self .print (
672+ "void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));"
673+ )
678674 self .out_of_memory_return (f"!_new_children" )
679675 self .print ("_children = _new_children;" )
680676 self .print ("}" )
@@ -721,7 +717,7 @@ def collect_vars(self, node: Alt) -> Dict[Optional[str], Optional[str]]:
721717 return types
722718
723719 def add_var (self , node : NamedItem ) -> Tuple [Optional [str ], Optional [str ]]:
724- call = self .callmakervisitor .visit (node .item )
720+ call = self .callmakervisitor .generate_call (node .item )
725721 name = node .name if node .name else call .assigned_variable
726722 if name is not None :
727723 name = self .dedupe (name )
0 commit comments