9090 Terminal ,
9191)
9292from .grammar_utils import is_epsilon , rhs_elements
93- from .proto_ast import ProtoField , ProtoMessage
93+ from .proto_ast import ProtoMessage
9494from .target import (
9595 Assign ,
9696 BaseType ,
101101 ListExpr ,
102102 ListType ,
103103 Lit ,
104- NewMessage ,
105- OneOf ,
106104 ParseNonterminal ,
107105 ParseNonterminalDef ,
108106 Seq ,
@@ -134,105 +132,6 @@ class AmbiguousGrammarError(Exception):
134132 pass
135133
136134
137- def _proto_fields_by_name (
138- proto_messages : dict [tuple [str , str ], ProtoMessage ] | None ,
139- module : str ,
140- name : str ,
141- ) -> dict [str , ProtoField ]:
142- """Return a name->ProtoField map for a proto message, or {} if not found."""
143- if proto_messages is None :
144- return {}
145- proto_msg = proto_messages .get ((module , name ))
146- if proto_msg is None :
147- return {}
148- result : dict [str , ProtoField ] = {}
149- for f in proto_msg .fields :
150- result [f .name ] = f
151- for oneof in proto_msg .oneofs :
152- for f in oneof .fields :
153- result [f .name ] = f
154- return result
155-
156-
157- def _build_param_proto_fields (
158- action : Lambda ,
159- proto_messages : dict [tuple [str , str ], ProtoMessage ] | None ,
160- ) -> dict [int , ProtoField ]:
161- """Map lambda parameter indices to protobuf ProtoField descriptors.
162-
163- Inspects the semantic action's body. When it is a NewMessage, cross-references
164- field names with proto_messages to find proto fields.
165-
166- As a fallback, when the action's return type is a known proto message,
167- matches parameter names to proto field names.
168-
169- Returns dict mapping parameter index to ProtoField.
170- """
171- if proto_messages is None :
172- return {}
173- body = action .body
174- if isinstance (body , NewMessage ):
175- fields_by_name = _proto_fields_by_name (proto_messages , body .module , body .name )
176- if not fields_by_name :
177- return {}
178- param_names = [p .name for p in action .params ]
179- result : dict [int , ProtoField ] = {}
180- for field_name , field_expr in body .fields :
181- pf = fields_by_name .get (field_name )
182- if pf is None :
183- continue
184- param_name = _extract_param_name (field_expr , param_names )
185- if param_name is not None and param_name in param_names :
186- param_idx = param_names .index (param_name )
187- result .setdefault (param_idx , pf )
188- return result
189- # Fallback: match parameter names against the return type's proto fields.
190- return _build_param_proto_fields_by_return_type (action , proto_messages )
191-
192-
193- def _build_param_proto_fields_by_return_type (
194- action : Lambda ,
195- proto_messages : dict [tuple [str , str ], ProtoMessage ] | None ,
196- ) -> dict [int , ProtoField ]:
197- """Fallback: match parameter names to proto fields via the return type."""
198- from .target import MessageType
199-
200- if proto_messages is None :
201- return {}
202- rt = action .return_type
203- if not isinstance (rt , MessageType ):
204- return {}
205- fields_by_name = _proto_fields_by_name (proto_messages , rt .module , rt .name )
206- if not fields_by_name :
207- return {}
208- result : dict [int , ProtoField ] = {}
209- for i , param in enumerate (action .params ):
210- pf = fields_by_name .get (param .name )
211- if pf is not None :
212- result [i ] = pf
213- return result
214-
215-
216- def _extract_param_name (expr : TargetExpr , param_names : list [str ]) -> str | None :
217- """Extract the parameter name from a field expression.
218-
219- Handles:
220- - Direct Var reference
221- - Call(OneOf(...), [Var(...)]) wrapper
222- - Call(Builtin(...), [Var(...), ...]) e.g. unwrap_option_or
223- """
224- from .target import Builtin
225-
226- if isinstance (expr , Var ) and expr .name in param_names :
227- return expr .name
228- if isinstance (expr , Call ):
229- if isinstance (expr .func , OneOf ) and expr .args :
230- return _extract_param_name (expr .args [0 ], param_names )
231- if isinstance (expr .func , Builtin ) and expr .args :
232- return _extract_param_name (expr .args [0 ], param_names )
233- return None
234-
235-
236135def generate_parse_functions (
237136 grammar : Grammar ,
238137 indent : str = "" ,
@@ -544,15 +443,6 @@ def _generate_parse_rhs_ir(
544443 return Seq ([parse_expr , apply_lambda (action , [])])
545444 var_name = gensym (action .params [0 ].name )
546445 var = Var (var_name , rhs .target_type ())
547- # Wrap with push_path when the action maps this param to a proto
548- # field (e.g., oneof dispatch: formula -> atom pushes the atom
549- # field number onto the provenance path).
550- if proto_messages is not None :
551- pf = _build_param_proto_fields (action , proto_messages ).get (0 )
552- if pf is not None :
553- stmts = _wrap_with_path (pf .number , var , parse_expr )
554- stmts .append (apply_lambda (action , [var ]))
555- return Seq (stmts )
556446 return Let (var , parse_expr , apply_lambda (action , [var ]))
557447 return parse_expr
558448 elif isinstance (rhs , Option ):
@@ -587,15 +477,6 @@ def _generate_parse_rhs_ir(
587477 raise NotImplementedError (f"Unsupported Rhs type: { type (rhs )} " )
588478
589479
590- def _wrap_with_path (field_num : int , var : Var , inner : TargetExpr ) -> list [TargetExpr ]:
591- """Return statements that push path, assign inner to var, then pop path."""
592- return [
593- Call (make_builtin ("push_path" ), [Lit (field_num )]),
594- Assign (var , inner ),
595- Call (make_builtin ("pop_path" ), []),
596- ]
597-
598-
599480def _generate_parse_rhs_ir_sequence (
600481 rhs : Sequence ,
601482 grammar : Grammar ,
@@ -607,11 +488,6 @@ def _generate_parse_rhs_ir_sequence(
607488 if is_epsilon (rhs ):
608489 return Lit (None )
609490
610- # Compute param->proto field mapping for provenance
611- param_proto_fields : dict [int , ProtoField ] = {}
612- if action is not None and proto_messages is not None :
613- param_proto_fields = _build_param_proto_fields (action , proto_messages )
614-
615491 exprs = []
616492 arg_vars = []
617493 elems = list (rhs_elements (rhs ))
@@ -639,25 +515,7 @@ def _generate_parse_rhs_ir_sequence(
639515 )
640516 var_name = gensym ("arg" )
641517 var = Var (var_name , elem .target_type ())
642- pf = param_proto_fields .get (non_literal_count )
643- if pf is not None and pf .is_repeated and isinstance (elem , Star ):
644- # Repeated proto field parsed as a Star: push field number
645- # around the whole loop and push/pop an index per element.
646- stmts = _wrap_star_with_index_path (
647- elem , var , grammar , follow_set_i , pf .number , proto_messages
648- )
649- exprs .extend (stmts )
650- elif isinstance (elem , Star ) and proto_messages is not None :
651- # Star without a repeated proto field (helper rule): still
652- # push/pop an index per element for provenance.
653- stmts = _wrap_star_with_index_path (
654- elem , var , grammar , follow_set_i , None , proto_messages
655- )
656- exprs .extend (stmts )
657- elif pf is not None :
658- exprs .extend (_wrap_with_path (pf .number , var , elem_ir ))
659- else :
660- exprs .append (Assign (var , elem_ir ))
518+ exprs .append (Assign (var , elem_ir ))
661519 arg_vars .append (var )
662520 non_literal_count += 1
663521 if apply_action and action :
@@ -674,55 +532,3 @@ def _generate_parse_rhs_ir_sequence(
674532 return exprs [0 ]
675533 else :
676534 return Seq (exprs )
677-
678-
679- def _wrap_star_with_index_path (
680- star : Star ,
681- result_var : Var ,
682- grammar : Grammar ,
683- follow_set : TerminalSequenceSet ,
684- field_num : int | None ,
685- proto_messages : dict [tuple [str , str ], ProtoMessage ] | None = None ,
686- ) -> list [TargetExpr ]:
687- """Return statements for a Star loop with push_path(index)/pop_path()
688- around each element. When field_num is provided, the entire loop is
689- also wrapped with push_path(field_num)/pop_path().
690- Assigns the resulting list to result_var."""
691- xs = Var (gensym ("xs" ), ListType (star .rhs .target_type ()))
692- cond = Var (gensym ("cond" ), BaseType ("Boolean" ))
693- idx = Var (gensym ("idx" ), BaseType ("Int64" ))
694- predictor = _build_option_predictor (grammar , star .rhs , follow_set )
695- parse_item = _generate_parse_rhs_ir (
696- star .rhs , grammar , follow_set , False , None , proto_messages
697- )
698- item = Var (gensym ("item" ), star .rhs .target_type ())
699- loop_body = Seq (
700- [
701- Call (make_builtin ("push_path" ), [idx ]),
702- Assign (item , parse_item ),
703- Call (make_builtin ("pop_path" ), []),
704- Call (make_builtin ("list_push" ), [xs , item ]),
705- Assign (idx , Call (make_builtin ("add" ), [idx , Lit (1 )])),
706- Assign (cond , predictor ),
707- ]
708- )
709- inner = Let (
710- xs ,
711- ListExpr ([], star .rhs .target_type ()),
712- Let (
713- cond ,
714- predictor ,
715- Let (
716- idx ,
717- Lit (0 ),
718- Seq ([While (cond , loop_body ), xs ]),
719- ),
720- ),
721- )
722- if field_num is not None :
723- return [
724- Call (make_builtin ("push_path" ), [Lit (field_num )]),
725- Assign (result_var , inner ),
726- Call (make_builtin ("pop_path" ), []),
727- ]
728- return [Assign (result_var , inner )]
0 commit comments