@@ -83,10 +83,10 @@ def make_grammar_snippet(
8383
8484 def production_definitions (
8585 self , lines : Iterable [str ], /
86- ) -> Iterator [tuple [str , list [dict [str , str ]]]]:
86+ ) -> Iterator [tuple [str , list [tuple [str , str ]]]]:
8787 """Yield pairs of rawsource and production content dicts."""
8888 production_lines : list [str ] = []
89- production_content : list [dict [str , str ]] = []
89+ production_content : list [tuple [str , str ]] = []
9090 for line in lines :
9191 # If this line is the start of a new rule (text in the column 1),
9292 # emit the current production and start a new one.
@@ -106,17 +106,19 @@ def production_definitions(
106106 # Handle text between matches
107107 if match .start () > last_pos :
108108 unmatched_text = line [last_pos : match .start ()]
109- production_content .append ({ 'text' : unmatched_text } )
109+ production_content .append (( 'text' , unmatched_text ) )
110110 last_pos = match .end ()
111111
112- # Handle matches
113- group_dict = {
114- name : content
115- for name , content in match .groupdict ().items ()
112+ # Handle matches.
113+ # After filtering None (non-matches), exactly one groupdict()
114+ # entry should remain.
115+ [(re_group_name , content )] = (
116+ (re_group_name , content )
117+ for re_group_name , content in match .groupdict ().items ()
116118 if content is not None
117- }
118- production_content .append (group_dict )
119- production_content .append ({ 'text' : line [last_pos :] + '\n ' } )
119+ )
120+ production_content .append (( re_group_name , content ) )
121+ production_content .append (( 'text' , line [last_pos :] + '\n ' ) )
120122
121123 # Emit the final production
122124 if production_content :
@@ -126,27 +128,27 @@ def production_definitions(
126128 def make_production (
127129 self ,
128130 rawsource : str ,
129- production_defs : list [dict [str , str ]],
131+ production_defs : list [tuple [str , str ]],
130132 * ,
131133 group_name : str ,
132134 location : str ,
133135 ) -> addnodes .production :
134136 """Create a production node from a list of parts."""
135137 production_node = addnodes .production (rawsource )
136- for group_dict in production_defs :
137- match group_dict :
138- case { 'rule_name' : name } :
138+ for re_group_name , content in production_defs :
139+ match re_group_name :
140+ case 'rule_name' :
139141 production_node += self .make_name_target (
140- name = name ,
142+ name = content ,
141143 production_group = group_name ,
142144 location = location ,
143145 )
144- case { 'rule_ref' : ref_text } :
145- production_node += token_xrefs (ref_text , group_name )
146- case { 'single_quoted' : name } | { 'double_quoted' : name } :
147- production_node += snippet_string_node ('' , name )
148- case { 'text' : text } :
149- production_node += nodes .Text (text )
146+ case 'rule_ref' :
147+ production_node += token_xrefs (content , group_name )
148+ case 'single_quoted' | 'double_quoted' :
149+ production_node += snippet_string_node ('' , content )
150+ case 'text' :
151+ production_node += nodes .Text (content )
150152 case _:
151153 raise ValueError ('unhandled match' )
152154 return production_node
0 commit comments