Exemplo n.º 1
0
    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])))
Exemplo n.º 2
0
    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]
            ))
        )
Exemplo n.º 3
0
    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)
Exemplo n.º 4
0
    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
        )
Exemplo n.º 5
0
    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)
Exemplo n.º 6
0
    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)])
Exemplo n.º 7
0
    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)
Exemplo n.º 8
0
    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)]
        )