Exemplo n.º 1
0
def test_associativity_conflicts_resolving():
    """
    Test that using associativity will resolve conflicts.
    """
    grammar = r"""
    E: E '+' E | number;

    terminals
    number: /d+/;
    """

    g = Grammar.from_string(grammar)
    table = create_table(g)

    assert len(table.sr_conflicts) == 1

    grammar = r"""
    E: E '+' E {left} | number;

    terminals
    number: /d+/;
    """

    g = Grammar.from_string(grammar)
    table = create_table(g)

    assert len(table.sr_conflicts) == 0
Exemplo n.º 2
0
def test_prefer_shifts_no_sr_conflicts():
    """
    Test that grammar with S/R conflict will be resolved to SHIFT actions
    if prefer_shift option is used.
    """
    # This grammar has S/R conflict as B+ may consume multiple single "a" A
    # because "b" is optional. Thus, parser can't decide if it should shift "a"
    # or reduce by 'B: "b"? A+' and later by 'S: B+'; Most of the time we want
    # gready behavior so in case of doubt parser will choose shift if
    # prefer_shift is set to `True`. This means that the parser will first
    # consume all "a" using A+ and that reduce B at the end.
    grammar = r"""
    S: B+;
    B: "b"? A+;

    terminals
    A: "a";
    """
    g = Grammar.from_string(grammar)

    # There is a shift reduce conflict so we can't use LR parser.
    table = create_table(g)
    assert len(table.sr_conflicts) == 1

    # But we can eliminate conflict by prefer_shifts strategy.
    table = create_table(g, prefer_shifts=True)
    assert len(table.sr_conflicts) == 0

    # With prefer_shifts we get a greedy behavior
    input_str = 'b a a a b a a'
    output = [['b', ['a', 'a', 'a']], ['b', ['a', 'a']]]
    parser = Parser(g, prefer_shifts=True)
    result = parser.parse(input_str)
    assert result == output

    # GLR parser can parse without prefer_shifts strategy. This grammar is
    # ambiguous and yields 11 solutions for the given input.
    parser = GLRParser(g)
    results = parser.parse(input_str)
    expected = [
        [['b', ['a']], [None, ['a']], [None, ['a']], ['b', ['a', 'a']]],
        [['b', ['a', 'a']], [None, ['a']], ['b', ['a', 'a']]],
        [['b', ['a', 'a', 'a']], ['b', ['a', 'a']]],
        [['b', ['a']], [None, ['a', 'a']], ['b', ['a', 'a']]],
        [['b', ['a']], [None, ['a', 'a']], ['b', ['a']], [None, ['a']]],
        [['b', ['a', 'a', 'a']], ['b', ['a']], [None, ['a']]],
        [['b', ['a', 'a']], [None, ['a']], ['b', ['a']], [None, ['a']]],
        [['b', ['a']], [None, ['a', 'a']], ['b', ['a']], [None, ['a']]],
        [['b', ['a', 'a', 'a']], ['b', ['a']], [None, ['a']]],
        [['b', ['a', 'a']], [None, ['a']], ['b', ['a']], [None, ['a']]],
        [['b', ['a']], [None, ['a']], [None, ['a']], ['b', ['a']], [None, ['a']]]  # noqa
    ]
    assert results == expected

    # But if `prefer_shift` is used we get only one solution
    parser = GLRParser(g, prefer_shifts=True)
    result = parser.parse(input_str)
    assert len(result) == 1
    assert result[0] == output
Exemplo n.º 3
0
def check_get_grammar_table(grammar_file, debug, colors):
    try:
        g = Grammar.from_file(grammar_file,
                              _no_check_recognizers=True,
                              debug_colors=colors)
        if debug:
            g.print_debug()
        table = create_table(g)
        if debug:
            table.print_debug()

        h_print("Grammar OK.")
        if table.sr_conflicts:
            a_print("There are {} Shift/Reduce conflicts.".format(
                len(table.sr_conflicts)))
            prints("Either use 'prefer_shifts' parser mode, try to resolve "
                   "manually or use GLR parsing.".format(
                       len(table.sr_conflicts)))
        if table.rr_conflicts:
            a_print("There are {} Reduce/Reduce conflicts.".format(
                len(table.rr_conflicts)))
            prints("Try to resolve manually or use GLR parsing.")

        if (table.sr_conflicts or table.rr_conflicts) and not debug:
            prints("Run in debug mode to print all the states.")

    except (GrammarError, ParseError) as e:
        print("Error in the grammar file.")
        print(e)
        sys.exit(1)

    return g, table
Exemplo n.º 4
0
def test_precomputed_table():
    """If parser is initialized with a `table` parameter then this table
    should be used, and no call to create_table should be made."""
    grammar = get_grammar()
    table = create_table(grammar)
    if HAS_MOCK:
        with patch('parglare.tables.create_table') as mocked_create_table:
            parser = GLRParser(grammar, table=table)
            assert not mocked_create_table.called
    else:
        parser = GLRParser(grammar, table=table)
    parser.parse('id+id')
Exemplo n.º 5
0
def test_dot_export():
    grammar = 'S: S S | S S S | "b";'
    g = Grammar.from_string(grammar)

    table = create_table(g)

    f, file_name = mkstemp()
    grammar_pda_export(table, file_name)

    assert os.path.exists(file_name)
    with open(file_name) as f:
        assert 'label' in f.read()

    os.remove(file_name)
Exemplo n.º 6
0
def test_dot_export():
    grammar = 'S: S S | S S S | "b";'
    g = Grammar.from_string(grammar)

    table = create_table(g)

    tmp_dir = tempfile.mkdtemp()
    file_name = os.path.join(tmp_dir, 'testexport.dot')

    grammar_pda_export(table, file_name)

    with open(file_name) as f:
        assert 'label' in f.read()

    os.remove(file_name)
    os.rmdir(tmp_dir)
Exemplo n.º 7
0
def bnf2parglare(productions, terminals, original_start):
    grammar, start = to_parglare_grammar(productions, terminals,
                                         original_start)

    with timeit('computing parse table'):
        table = create_table(
            grammar,
            start_production=grammar.get_production_id(start),
            itemset_type=LALR,
            prefer_shifts=False,
            prefer_shifts_over_empty=False,
            lexical_disambiguation=False,
        )

    serializable_table = table_to_serializable(table)

    return productions, terminals, original_start, start, serializable_table
Exemplo n.º 8
0
def test_table_construction():
    """
    Tests LR table construction.
    """
    # From the Knuth's 1965 paper: On the Translation of Languages from Left to
    # Right
    grammar = r"""
    S: 'a' A 'd' | 'b' A 'd';
    A: 'c' A | 'c';
    """

    g = Grammar.from_string(grammar)
    table = create_table(g)

    c = g.get_terminal('c')
    d = g.get_terminal('d')

    assert len(table.states) == 11
    assert table.states[0].symbol.name == "S'"
    state = table.states[2]
    assert state.symbol.name == 'a'
    assert len(state.kernel_items) == 1
    assert len(state.items) == 3
    assert len(state.actions) == 1
    assert len(state.actions[c]) == 1
    action = list(state.actions.values())[0][0]
    assert action.action == SHIFT
    assert action.state.state_id == 6

    state = table.states[6]
    assert state.symbol.name == 'c'
    assert len(state.kernel_items) == 2
    assert len(state.items) == 4
    assert len(state.actions) == 2
    assert len(state.actions[c]) == 1
    assert len(state.actions[d]) == 1
    action = list(state.actions.values())[0][0]
    assert action.action == REDUCE
    assert action.prod.prod_id == 4
    action = list(state.actions.values())[1][0]
    assert action.action == SHIFT
    assert action.state.state_id == 6
Exemplo n.º 9
0
from parglare.tables import create_table, LALR
from parglare.tables.persist import table_to_serializable

from grammar import grammar, start_symbol

table = create_table(
    grammar,
    start_production=grammar.get_production_id(start_symbol),
    itemset_type=LALR,
    prefer_shifts=False,
    prefer_shifts_over_empty=False,
)
serializable_table = table_to_serializable(table)

with open('_table.py', 'w') as f:
    f.write('table = ')
    f.write(repr(serializable_table))