Esempio n. 1
0
def test_start_leader():
    grammar = """
    start: attr | NAME
    attr: start '.' NAME
    """
    # Would assert False without a special case in compute_left_recursives().
    make_parser(grammar)
Esempio n. 2
0
 def test_opt_sequence(self) -> None:
     grammar = """
     start: [NAME*]
     """
     # This case was failing because of a double trailing comma at the end
     # of a line in the generated source. See bpo-41044
     make_parser(grammar)
Esempio n. 3
0
 def test_left_recursion_too_complex(self) -> None:
     grammar = """
     start: foo
     foo: bar '+' | baz '+' | '+'
     bar: baz '-' | foo '-' | '-'
     baz: foo '*' | bar '*' | '*'
     """
     with self.assertRaises(ValueError) as errinfo:
         make_parser(grammar)
         self.assertTrue("no leader" in str(errinfo.exception.value))
Esempio n. 4
0
def test_left_recursion_too_complex():
    grammar = """
    start: foo
    foo: bar '+' | baz '+' | '+'
    bar: baz '-' | foo '-' | '-'
    baz: foo '*' | bar '*' | '*'
    """
    with pytest.raises(ValueError) as errinfo:
        make_parser(grammar)
    assert "no leader" in str(errinfo.value)
Esempio n. 5
0
 def test_repeat_1_complex(self) -> None:
     grammar = """
     start: term ('+' term)+ NEWLINE
     term: NUMBER
     """
     parser_class = make_parser(grammar)
     node = parse_string("1 + 2 + 3\n", parser_class)
     self.assertEqual(node, [
         [TokenInfo(NUMBER, string="1", start=(1, 0), end=(1, 1), line="1 + 2 + 3\n")],
         [
             [
                 [
                     TokenInfo(OP, string="+", start=(1, 2), end=(1, 3), line="1 + 2 + 3\n"),
                     [TokenInfo(NUMBER, string="2", start=(1, 4), end=(1, 5), line="1 + 2 + 3\n")],
                 ]
             ],
             [
                 [
                     TokenInfo(OP, string="+", start=(1, 6), end=(1, 7), line="1 + 2 + 3\n"),
                     [TokenInfo(NUMBER, string="3", start=(1, 8), end=(1, 9), line="1 + 2 + 3\n")],
                 ]
             ],
         ],
         TokenInfo(NEWLINE, string="\n", start=(1, 9), end=(1, 10), line="1 + 2 + 3\n"),
     ])
     with self.assertRaises(SyntaxError):
         parse_string("1\n", parser_class)
Esempio n. 6
0
def test_bad_token_reference():
    grammar = """
    start: foo
    foo: NAMEE
    """
    with pytest.raises(GrammarError):
        parser_class = make_parser(grammar)
Esempio n. 7
0
 def test_dangling_reference(self) -> None:
     grammar = """
     start: foo ENDMARKER
     foo: bar NAME
     """
     with self.assertRaises(GrammarError):
         parser_class = make_parser(grammar)
Esempio n. 8
0
def test_repeat_1_simple():
    grammar = """
    start: thing thing+ NEWLINE
    thing: NUMBER
    """
    parser_class = make_parser(grammar)
    node = parse_string("1 2 3\n", parser_class)
    assert node == [[
        TokenInfo(NUMBER, string='1', start=(1, 0), end=(1, 1), line='1 2 3\n')
    ],
                    [[[
                        TokenInfo(NUMBER,
                                  string='2',
                                  start=(1, 2),
                                  end=(1, 3),
                                  line='1 2 3\n')
                    ]],
                     [[
                         TokenInfo(NUMBER,
                                   string='3',
                                   start=(1, 4),
                                   end=(1, 5),
                                   line='1 2 3\n')
                     ]]],
                    TokenInfo(NEWLINE,
                              string='\n',
                              start=(1, 5),
                              end=(1, 6),
                              line='1 2 3\n')]
    with pytest.raises(SyntaxError):
        parse_string("1\n", parser_class)
Esempio n. 9
0
def test_optional_literal():
    grammar = """
    start: sum NEWLINE
    sum: term '+' ?
    term: NUMBER
    """
    parser_class = make_parser(grammar)
    node = parse_string("1+\n", parser_class)
    assert node == [
        [
            [
                TokenInfo(NUMBER,
                          string="1",
                          start=(1, 0),
                          end=(1, 1),
                          line="1+\n")
            ],
            TokenInfo(OP, string="+", start=(1, 1), end=(1, 2), line="1+\n"),
        ],
        TokenInfo(NEWLINE, string="\n", start=(1, 2), end=(1, 3), line="1+\n"),
    ]
    node = parse_string("1\n", parser_class)
    assert node == [
        [[TokenInfo(NUMBER, string="1", start=(1, 0), end=(1, 1), line="1\n")],
         None],
        TokenInfo(NEWLINE, string="\n", start=(1, 1), end=(1, 2), line="1\n"),
    ]
Esempio n. 10
0
 def test_repeat_with_sep_simple(self) -> None:
     grammar = """
     start: ','.thing+ NEWLINE
     thing: NUMBER
     """
     parser_class = make_parser(grammar)
     node = parse_string("1, 2, 3\n", parser_class)
     self.assertEqual(
         node,
         [
             [
                 TokenInfo(NUMBER,
                           string="1",
                           start=(1, 0),
                           end=(1, 1),
                           line="1, 2, 3\n"),
                 TokenInfo(NUMBER,
                           string="2",
                           start=(1, 3),
                           end=(1, 4),
                           line="1, 2, 3\n"),
                 TokenInfo(NUMBER,
                           string="3",
                           start=(1, 6),
                           end=(1, 7),
                           line="1, 2, 3\n"),
             ],
             TokenInfo(NEWLINE,
                       string="\n",
                       start=(1, 7),
                       end=(1, 8),
                       line="1, 2, 3\n"),
         ],
     )
Esempio n. 11
0
def test_dangling_reference():
    grammar = """
    start: foo ENDMARKER
    foo: bar NAME
    """
    with pytest.raises(GrammarError):
        parser_class = make_parser(grammar)
Esempio n. 12
0
 def test_bad_token_reference(self) -> None:
     grammar = """
     start: foo
     foo: NAMEE
     """
     with self.assertRaises(GrammarError):
         parser_class = make_parser(grammar)
Esempio n. 13
0
 def test_invalid_rule_name(self) -> None:
     grammar = """
     start: _a b
     _a: 'a'
     b: 'b'
     """
     with self.assertRaisesRegex(GrammarError, "cannot start with underscore: '_a'"):
         parser_class = make_parser(grammar)
Esempio n. 14
0
 def test_invalid_variable_name_in_temporal_rule(self) -> None:
     grammar = """
     start: a b
     a: (_x='a' | 'b') | 'c'
     b: 'b'
     """
     with self.assertRaisesRegex(GrammarError, "cannot start with underscore: '_x'"):
         parser_class = make_parser(grammar)
Esempio n. 15
0
 def test_forced_with_group(self) -> None:
     grammar = """
     start: NAME &&(':' | ';') | NAME
     """
     parser_class = make_parser(grammar)
     self.assertTrue(parse_string("number :", parser_class, verbose=True))
     self.assertTrue(parse_string("number ;", parser_class, verbose=True))
     with self.assertRaises(SyntaxError) as e:
         parse_string("a", parser_class, verbose=True)
     self.assertIn("expected (':' | ';')", e.exception.args[0])
Esempio n. 16
0
    def test_forced(self) -> None:
        grammar = """
        start: NAME &&':' | NAME
        """
        parser_class = make_parser(grammar)
        self.assertTrue(parse_string("number :", parser_class, verbose=True))
        with self.assertRaises(SyntaxError) as e:
            parse_string("a", parser_class, verbose=True)

        self.assertIn("expected ':'", str(e.exception))
Esempio n. 17
0
 def test_alt_optional_operator(self) -> None:
     grammar = """
     start: sum NEWLINE
     sum: term ['+' term]
     term: NUMBER
     """
     parser_class = make_parser(grammar)
     node = parse_string("1 + 2\n", parser_class)
     self.assertEqual(
         node,
         [
             [
                 TokenInfo(NUMBER,
                           string="1",
                           start=(1, 0),
                           end=(1, 1),
                           line="1 + 2\n"),
                 [
                     TokenInfo(OP,
                               string="+",
                               start=(1, 2),
                               end=(1, 3),
                               line="1 + 2\n"),
                     TokenInfo(NUMBER,
                               string="2",
                               start=(1, 4),
                               end=(1, 5),
                               line="1 + 2\n"),
                 ],
             ],
             TokenInfo(NEWLINE,
                       string="\n",
                       start=(1, 5),
                       end=(1, 6),
                       line="1 + 2\n"),
         ],
     )
     node = parse_string("1\n", parser_class)
     self.assertEqual(
         node,
         [
             [
                 TokenInfo(NUMBER,
                           string="1",
                           start=(1, 0),
                           end=(1, 1),
                           line="1\n"),
                 None,
             ],
             TokenInfo(
                 NEWLINE, string="\n", start=(1, 1), end=(1, 2),
                 line="1\n"),
         ],
     )
Esempio n. 18
0
def test_cut():
    grammar = """
    start: '(' ~ expr ')'
    expr: NUMBER
    """
    parser_class = make_parser(grammar)
    node = parse_string("(1)", parser_class, verbose=True)
    assert node == [
        TokenInfo(OP, string="(", start=(1, 0), end=(1, 1), line="(1)"),
        [TokenInfo(NUMBER, string="1", start=(1, 1), end=(1, 2), line="(1)")],
        TokenInfo(OP, string=")", start=(1, 2), end=(1, 3), line="(1)"),
    ]
Esempio n. 19
0
 def test_expr_grammar(self) -> None:
     grammar = """
     start: sum NEWLINE
     sum: term '+' term | term
     term: NUMBER
     """
     parser_class = make_parser(grammar)
     node = parse_string("42\n", parser_class)
     self.assertEqual(node, [
         [[TokenInfo(NUMBER, string="42", start=(1, 0), end=(1, 2), line="42\n")]],
         TokenInfo(NEWLINE, string="\n", start=(1, 2), end=(1, 3), line="42\n"),
     ])
Esempio n. 20
0
 def test_cut(self) -> None:
     grammar = """
     start: '(' ~ expr ')'
     expr: NUMBER
     """
     parser_class = make_parser(grammar)
     node = parse_string("(1)", parser_class)
     self.assertEqual(node, [
         TokenInfo(OP, string="(", start=(1, 0), end=(1, 1), line="(1)"),
         [TokenInfo(NUMBER, string="1", start=(1, 1), end=(1, 2), line="(1)")],
         TokenInfo(OP, string=")", start=(1, 2), end=(1, 3), line="(1)"),
     ])
Esempio n. 21
0
 def test_gather(self) -> None:
     grammar = """
     start: ','.thing+ NEWLINE
     thing: NUMBER
     """
     rules = parse_string(grammar, GrammarParser).rules
     self.assertEqual(str(rules["start"]), "start: ','.thing+ NEWLINE")
     self.assertTrue(
         repr(rules["start"]).startswith(
             "Rule('start', None, Rhs([Alt([NamedItem(None, Gather(StringLeaf(\"','\"), NameLeaf('thing'"
         ))
     self.assertEqual(str(rules["thing"]), "thing: NUMBER")
     parser_class = make_parser(grammar)
     node = parse_string("42\n", parser_class)
     assert node == [
         [[
             TokenInfo(NUMBER,
                       string="42",
                       start=(1, 0),
                       end=(1, 2),
                       line="42\n")
         ]],
         TokenInfo(NEWLINE,
                   string="\n",
                   start=(1, 2),
                   end=(1, 3),
                   line="42\n"),
     ]
     node = parse_string("1, 2\n", parser_class)
     assert node == [
         [
             [
                 TokenInfo(NUMBER,
                           string="1",
                           start=(1, 0),
                           end=(1, 1),
                           line="1, 2\n")
             ],
             [
                 TokenInfo(NUMBER,
                           string="2",
                           start=(1, 3),
                           end=(1, 4),
                           line="1, 2\n")
             ],
         ],
         TokenInfo(NEWLINE,
                   string="\n",
                   start=(1, 4),
                   end=(1, 5),
                   line="1, 2\n"),
     ]
Esempio n. 22
0
def test_lookahead():
    grammar = """
    start: (expr_stmt | assign_stmt) &'.'
    expr_stmt: !(target '=') expr
    assign_stmt: target '=' expr
    expr: term ('+' term)*
    target: NAME
    term: NUMBER
    """
    parser_class = make_parser(grammar)
    node = parse_string("foo = 12 + 12 .", parser_class)
    assert node == [[[
        [
            TokenInfo(NAME,
                      string="foo",
                      start=(1, 0),
                      end=(1, 3),
                      line="foo = 12 + 12 .")
        ],
        TokenInfo(OP,
                  string="=",
                  start=(1, 4),
                  end=(1, 5),
                  line="foo = 12 + 12 ."),
        [
            [
                TokenInfo(NUMBER,
                          string="12",
                          start=(1, 6),
                          end=(1, 8),
                          line="foo = 12 + 12 .")
            ],
            [[[
                TokenInfo(
                    OP,
                    string="+",
                    start=(1, 9),
                    end=(1, 10),
                    line="foo = 12 + 12 .",
                ),
                [
                    TokenInfo(
                        NUMBER,
                        string="12",
                        start=(1, 11),
                        end=(1, 13),
                        line="foo = 12 + 12 .",
                    )
                ],
            ]]],
        ],
    ]]]
Esempio n. 23
0
def test_repeat_0_complex():
    grammar = """
    start: term ('+' term)* NEWLINE
    term: NUMBER
    """
    parser_class = make_parser(grammar)
    node = parse_string("1 + 2 + 3\n", parser_class)
    assert node == [
        [
            TokenInfo(NUMBER,
                      string="1",
                      start=(1, 0),
                      end=(1, 1),
                      line="1 + 2 + 3\n")
        ],
        [
            [[
                TokenInfo(OP,
                          string="+",
                          start=(1, 2),
                          end=(1, 3),
                          line="1 + 2 + 3\n"),
                [
                    TokenInfo(NUMBER,
                              string="2",
                              start=(1, 4),
                              end=(1, 5),
                              line="1 + 2 + 3\n")
                ],
            ]],
            [[
                TokenInfo(OP,
                          string="+",
                          start=(1, 6),
                          end=(1, 7),
                          line="1 + 2 + 3\n"),
                [
                    TokenInfo(NUMBER,
                              string="3",
                              start=(1, 8),
                              end=(1, 9),
                              line="1 + 2 + 3\n")
                ],
            ]],
        ],
        TokenInfo(NEWLINE,
                  string="\n",
                  start=(1, 9),
                  end=(1, 10),
                  line="1 + 2 + 3\n"),
    ]
Esempio n. 24
0
def test_repeat_1_complex():
    grammar = """
    start: term ('+' term)+ NEWLINE
    term: NUMBER
    """
    parser_class = make_parser(grammar)
    node = parse_string("1 + 2 + 3\n", parser_class)
    assert node == [[
        TokenInfo(NUMBER,
                  string='1',
                  start=(1, 0),
                  end=(1, 1),
                  line='1 + 2 + 3\n')
    ],
                    [[[
                        TokenInfo(OP,
                                  string='+',
                                  start=(1, 2),
                                  end=(1, 3),
                                  line='1 + 2 + 3\n'),
                        [
                            TokenInfo(NUMBER,
                                      string='2',
                                      start=(1, 4),
                                      end=(1, 5),
                                      line='1 + 2 + 3\n')
                        ]
                    ]],
                     [[
                         TokenInfo(OP,
                                   string='+',
                                   start=(1, 6),
                                   end=(1, 7),
                                   line='1 + 2 + 3\n'),
                         [
                             TokenInfo(NUMBER,
                                       string='3',
                                       start=(1, 8),
                                       end=(1, 9),
                                       line='1 + 2 + 3\n')
                         ]
                     ]]],
                    TokenInfo(NEWLINE,
                              string='\n',
                              start=(1, 9),
                              end=(1, 10),
                              line='1 + 2 + 3\n')]
    with pytest.raises(SyntaxError):
        parse_string("1\n", parser_class)
Esempio n. 25
0
 def test_soft_keyword(self) -> None:
     grammar = """
     start:
         | "number" n=NUMBER { eval(n.string) }
         | "string" n=STRING { n.string }
         | SOFT_KEYWORD l=NAME n=(NUMBER | NAME | STRING) { f"{l.string} = {n.string}"}
     """
     parser_class = make_parser(grammar)
     self.assertEqual(parse_string("number 1", parser_class), 1)
     self.assertEqual(parse_string("string 'b'", parser_class), "'b'")
     self.assertEqual(parse_string("number test 1", parser_class),
                      "test = 1")
     assert (parse_string("string test 'b'", parser_class) == "test = 'b'")
     with self.assertRaises(SyntaxError):
         parse_string("test 1", parser_class)
Esempio n. 26
0
def test_expr_grammar():
    grammar = """
    start: sum NEWLINE
    sum: term '+' term | term
    term: NUMBER
    """
    parser_class = make_parser(grammar)
    node = parse_string("42\n", parser_class)
    assert node == [[[
        TokenInfo(NUMBER, string='42', start=(1, 0), end=(1, 2), line='42\n')
    ]],
                    TokenInfo(NEWLINE,
                              string='\n',
                              start=(1, 2),
                              end=(1, 3),
                              line='42\n')]
Esempio n. 27
0
 def test_repeat_1_simple(self) -> None:
     grammar = """
     start: thing thing+ NEWLINE
     thing: NUMBER
     """
     parser_class = make_parser(grammar)
     node = parse_string("1 2 3\n", parser_class)
     self.assertEqual(node, [
         [TokenInfo(NUMBER, string="1", start=(1, 0), end=(1, 1), line="1 2 3\n")],
         [
             [[TokenInfo(NUMBER, string="2", start=(1, 2), end=(1, 3), line="1 2 3\n")]],
             [[TokenInfo(NUMBER, string="3", start=(1, 4), end=(1, 5), line="1 2 3\n")]],
         ],
         TokenInfo(NEWLINE, string="\n", start=(1, 5), end=(1, 6), line="1 2 3\n"),
     ])
     with self.assertRaises(SyntaxError):
         parse_string("1\n", parser_class)
Esempio n. 28
0
 def test_repeat_0_simple(self) -> None:
     grammar = """
     start: thing thing* NEWLINE
     thing: NUMBER
     """
     parser_class = make_parser(grammar)
     node = parse_string("1 2 3\n", parser_class)
     self.assertEqual(
         node,
         [
             TokenInfo(NUMBER,
                       string="1",
                       start=(1, 0),
                       end=(1, 1),
                       line="1 2 3\n"),
             [
                 TokenInfo(NUMBER,
                           string="2",
                           start=(1, 2),
                           end=(1, 3),
                           line="1 2 3\n"),
                 TokenInfo(NUMBER,
                           string="3",
                           start=(1, 4),
                           end=(1, 5),
                           line="1 2 3\n"),
             ],
             TokenInfo(NEWLINE,
                       string="\n",
                       start=(1, 5),
                       end=(1, 6),
                       line="1 2 3\n"),
         ],
     )
     node = parse_string("1\n", parser_class)
     self.assertEqual(
         node,
         [
             TokenInfo(
                 NUMBER, string="1", start=(1, 0), end=(1, 1), line="1\n"),
             [],
             TokenInfo(
                 NEWLINE, string="\n", start=(1, 1), end=(1, 2),
                 line="1\n"),
         ],
     )
Esempio n. 29
0
def test_repeat_0_simple():
    grammar = """
    start: thing thing* NEWLINE
    thing: NUMBER
    """
    parser_class = make_parser(grammar)
    node = parse_string("1 2 3\n", parser_class)
    assert node == [
        [
            TokenInfo(NUMBER,
                      string="1",
                      start=(1, 0),
                      end=(1, 1),
                      line="1 2 3\n")
        ],
        [
            [[
                TokenInfo(NUMBER,
                          string="2",
                          start=(1, 2),
                          end=(1, 3),
                          line="1 2 3\n")
            ]],
            [[
                TokenInfo(NUMBER,
                          string="3",
                          start=(1, 4),
                          end=(1, 5),
                          line="1 2 3\n")
            ]],
        ],
        TokenInfo(NEWLINE,
                  string="\n",
                  start=(1, 5),
                  end=(1, 6),
                  line="1 2 3\n"),
    ]
    node = parse_string("1\n", parser_class)
    assert node == [
        [TokenInfo(NUMBER, string="1", start=(1, 0), end=(1, 1), line="1\n")],
        [],
        TokenInfo(NEWLINE, string="\n", start=(1, 1), end=(1, 2), line="1\n"),
    ]
Esempio n. 30
0
def part1(fname: str) -> int:
    """Part 1.

    BAsically we'll just treat + and * the same. It will evaluate left-to-right.

    >>> part1("./data/day18_test.txt")
    585
    """
    grammar = make_parser("""
    start: expr NEWLINE $ { ast.Expression(expr, lineno=1, col_offset=0) }
    expr: ( e=expr '+' t=term { ast.BinOp(e, ast.Add(), t, lineno=e.lineno, col_offset=e.col_offset, end_lineno=t.end_lineno, end_col_offset=t.end_col_offset) }
          | e=expr '*' t=term { ast.BinOp(e, ast.Mult(), t, lineno=e.lineno, col_offset=e.col_offset, end_lineno=t.end_lineno, end_col_offset=t.end_col_offset) }
          | term { term }
          )
    term: '(' expr ')' { expr } | atom { atom }
    atom: n=NUMBER { ast.Constant(value=ast.literal_eval(n.string), lineno=n.start[0], col_offset=n.start[1], end_lineno=n.end[0], end_col_offset=n.end[1]) }"""
                          )
    return sum(
        eval(compile(parse_string(expr, grammar), "", "eval"))
        for expr in get_data(fname))