Пример #1
0
    def testSimple(self):
        grammar = parse_esgrammar(
            """
            expr :
                SYMBOL  => $0
                `(` tail

            tail :
                `)`  => $0
                expr tail
            """,
            terminal_names=["SYMBOL"]
        )
        self.compile(LispTokenizer, grammar)

        self.assertParse(
            "(lambda (x) (* x x))",
            ('expr_1',
                '(',
                ('tail_1',
                    'lambda',
                    ('tail_1',
                        ('expr_1', '(', ('tail_1', 'x', ')')),
                        ('tail_1',
                            ('expr_1',
                                '(',
                                ('tail_1',
                                    '*',
                                    ('tail_1',
                                        'x',
                                        ('tail_1', 'x', ')')))),
                            ')')))))
Пример #2
0
    def compile_as_js(
        self,
        grammar_source: str,
        goals: typing.Optional[typing.Iterable[str]] = None,
        verbose: bool = False,
    ) -> None:
        """Like self.compile(), but generate a parser from ESGrammar,
        with ASI support, using the JS lexer.
        """
        from js_parser.lexer import JSLexer
        from js_parser import load_es_grammar
        from js_parser import generate_js_parser_tables

        grammar = parse_esgrammar(
            grammar_source,
            filename="es-simplified.esgrammar",
            extensions=[],
            goals=goals,
            synthetic_terminals=load_es_grammar.ECMASCRIPT_SYNTHETIC_TERMINALS,
            terminal_names=load_es_grammar.TERMINAL_NAMES_FOR_SYNTACTIC_GRAMMAR
        )
        grammar = generate_js_parser_tables.hack_grammar(grammar)
        base_parser_class = gen.compile(grammar, verbose=verbose)

        # "type: ignore" because poor mypy can't cope with the runtime codegen
        # we're doing here.
        class JSParser(base_parser_class):  # type: ignore
            def __init__(self, goal='Script', builder=None):
                super().__init__(goal, builder)
                self._goal = goal
                # self.debug = True

            def clone(self):
                return JSParser(self._goal, self.methods)

            def on_recover(self, error_code, lexer, stv):
                """Check that ASI error recovery is really acceptable."""
                if error_code == 'asi':
                    if not self.closed and stv.term != '}' and not lexer.saw_line_terminator(
                    ):
                        lexer.throw("missing semicolon")
                else:
                    assert error_code == 'do_while_asi'

        self.tokenize = JSLexer
        self.parser_class = JSParser