def generate_code(self, pos_name="pos"): pos, res = gen_names('or_pos', 'or_res') t_env = TemplateEnvironment( parser=self, # List of ParserCodeContext instances for the sub-parsers, # encapsulating their results. results=[m.gen_code_or_fncall(pos_name) for m in self.parsers], # Generate a name for the exit label (when one of the sub-parsers # has matched). exit_label=gen_name("Exit_Or"), pos=pos, res=res) code = render('parsers/or_code_ada', t_env) return ParserCodeContext( pos_var_name=t_env.pos, res_var_name=t_env.res, code=code, # For var defs, we create a new list that is the concatenation of # all the sub parsers variable definitions, adding the Or parser's # own pos and res variables. var_defs=list( chain([(pos, Token), (res, self.get_type())], *[sr.var_defs for sr in t_env.results])))
def generate_code(self, pos_name="pos"): pos, res = gen_names('or_pos', 'or_res') t_env = TemplateEnvironment( _self=self, # List of ParserCodeContext instances for the sub-parsers, # encapsulating their results. results=[ m.gen_code_or_fncall(pos_name) for m in self.parsers ], # Generate a name for the exit label (when one of the sub-parsers # has matched). exit_label=gen_name("Exit_Or"), pos=pos, res=res ) code = render('parsers/or_code_ada', t_env) return ParserCodeContext( pos_var_name=t_env.pos, res_var_name=t_env.res, code=code, # For var defs, we create a new list that is the concatenation of # all the sub parsers variable definitions, adding the Or parser's # own pos and res variables. var_defs=list(chain( [(pos, Token), (res, self.get_type())], *[sr.var_defs for sr in t_env.results] )) )
def generate_code(self, pos_name="pos"): t_env = TemplateEnvironment(pos_name=pos_name) t_env.parser = self t_env.pos, t_env.res = gen_names("row_pos", "row_res") decls = [(t_env.pos, Token)] t_env.subresults = list( gen_names( * ["row_subres_{0}".format(i) for i in range(len(self.parsers))])) t_env.exit_label = gen_name("row_exit_label") self.args = [ r for r, m in zip(t_env.subresults, self.parsers) if not m.discard() ] self.allargs = [r for r, m in zip(t_env.subresults, self.parsers)] bodies = [] for i, (parser, subresult) in enumerate(zip(self.parsers, t_env.subresults)): t_subenv = TemplateEnvironment( t_env, parser=parser, subresult=subresult, i=i, parser_context=parser.gen_code_or_fncall(t_env.pos)) decls += t_subenv.parser_context.var_defs if not parser.discard(): decls.append((subresult, parser.get_type())) bodies.append(render('parsers/row_submatch_ada', t_subenv)) code = render('parsers/row_code_ada', t_env, body='\n'.join(bodies)) return ParserCodeContext(pos_var_name=t_env.pos, res_var_name=t_env.res, code=code, var_defs=decls)
def generate_code(self, pos_name="pos"): t_env = TemplateEnvironment(pos_name=pos_name) t_env._self = self t_env.pos, t_env.res = gen_names("row_pos", "row_res") decls = [(t_env.pos, Token)] t_env.subresults = list(gen_names(*[ "row_subres_{0}".format(i) for i in range(len(self.parsers)) ])) t_env.exit_label = gen_name("row_exit_label") self.args = [r for r, m in zip(t_env.subresults, self.parsers) if not m.discard()] self.allargs = [r for r, m in zip(t_env.subresults, self.parsers)] bodies = [] for i, (parser, subresult) in enumerate(zip(self.parsers, t_env.subresults)): t_subenv = TemplateEnvironment( t_env, parser=parser, subresult=subresult, i=i, parser_context=parser.gen_code_or_fncall(t_env.pos) ) decls += t_subenv.parser_context.var_defs if not parser.discard(): decls.append((subresult, parser.get_type())) bodies.append(render('parsers/row_submatch_ada', t_subenv)) code = render('parsers/row_code_ada', t_env, body='\n'.join(bodies)) return ParserCodeContext( pos_var_name=t_env.pos, res_var_name=t_env.res, code=code, var_defs=decls )
def gen_code_or_fncall(self, pos_name="pos"): """ Return generated code for this parser into the global context. `pos_name` is the name of a variable that contains the position of the next token in the lexer. Either the "parsing code" is returned, either it is emitted in a dedicated function and a call to it is returned instead. This method relies on the subclasses-defined `generated_code` for "parsing code" generation. :param str|names.Name pos_name: The name of the position variable. :rtype: ParserCodeContext """ if self.name and get_context().verbosity.debug: print "Compiling rule: {0}".format( col(self.gen_fn_name, Colors.HEADER) ) # Users must be able to run parsers that implement a named rule, so # generate dedicated functions for them. if self.is_root: # The call to compile will add the declaration and the definition # (body) of the function to the compile context. self.compile() # Generate a call to the previously compiled function, and return # the context corresponding to this call. pos, res = gen_names("fncall_pos", "fncall_res") fncall_block = render( 'parsers/fn_call_ada', _self=self, pos_name=pos_name, pos=pos, res=res ) return ParserCodeContext( pos_var_name=pos, res_var_name=res, code=fncall_block, var_defs=[ (pos, Token), (res, self.get_type()) ] ) else: return self.generate_code(pos_name)
def generate_code(self, pos_name="pos"): # Generate the code to match the token of kind 'token_kind', and return # the corresponding context. pos, res = gen_names("tk_pos", "tk_res") code = render('parsers/tok_code_ada', parser=self, pos_name=pos_name, pos=pos, res=res, match_text=self.match_text, token_kind=get_context().lexer.ada_token_name(self.val)) return ParserCodeContext(pos_var_name=pos, res_var_name=res, code=code, var_defs=[(pos, Token), (res, Token)])
def gen_code_or_fncall(self, pos_name="pos"): """ Return generated code for this parser into the global context. `pos_name` is the name of a variable that contains the position of the next token in the lexer. Either the "parsing code" is returned, either it is emitted in a dedicated function and a call to it is returned instead. This method relies on the subclasses-defined `generated_code` for "parsing code" generation. :param str|names.Name pos_name: The name of the position variable. :rtype: ParserCodeContext """ if self.name and get_context().verbosity.debug: print "Compiling rule: {0}".format( col(self.gen_fn_name, Colors.HEADER)) # Users must be able to run parsers that implement a named rule, so # generate dedicated functions for them. if self.is_root: # The call to compile will add the declaration and the definition # (body) of the function to the compile context. self.compile() # Generate a call to the previously compiled function, and return # the context corresponding to this call. pos, res = gen_names("fncall_pos", "fncall_res") fncall_block = render('parsers/fn_call_ada', parser=self, pos_name=pos_name, pos=pos, res=res) return ParserCodeContext(pos_var_name=pos, res_var_name=res, code=fncall_block, var_defs=[(pos, Token), (res, self.get_type())]) else: return self.generate_code(pos_name)
def generate_code(self, pos_name="pos"): # Generate the code to match the token of kind 'token_kind', and return # the corresponding context. pos, res = gen_names("tk_pos", "tk_res") code = render( 'parsers/tok_code_ada', _self=self, pos_name=pos_name, pos=pos, res=res, token_kind=get_context().lexer.ada_token_name(self.val) ) return ParserCodeContext( pos_var_name=pos, res_var_name=res, code=code, var_defs=[(pos, Token), (res, Token)] )