예제 #1
0
def test_is_factored():
    g = ContextFreeGrammar.from_string('''
            S -> a S | a B | d S
            B -> b B | b
        ''')
    assert not g.is_factored()

    g = ContextFreeGrammar.from_string('''
            S  -> a S1 | d S
            S1 -> S | B
            B  -> b B1
            B1 -> B | &
        ''')
    assert g.is_factored()

    g = ContextFreeGrammar.from_string('''
            S -> A B | B C
            A -> a A | &
            B -> b B | d
            C -> c C | c
        ''')
    assert not g.is_factored()

    g = ContextFreeGrammar.from_string('''
            S -> a A B | B C1
            A -> a A | &
            B -> b B | d
            C -> c C1
            C1 -> C | &
        ''')
    assert g.is_factored()
예제 #2
0
def test_valid():
    ContextFreeGrammar.from_string('E -> E + T | E - T | T\n'
                                   'T -> T * F | T / F | F\n'
                                   'F -> ( E ) | id')

    ContextFreeGrammar.from_string('E -> T E1\n'
                                   'E1 -> + T E1 | &\n'
                                   'T -> F T1\n'
                                   'T1 -> * F T1 | &\n'
                                   'F -> ( E ) | id')
예제 #3
0
def test_invalid_spacing():
    with raises(ParseError):
        ContextFreeGrammar.from_string('E -> E+T | E-T | T\n'
                                       'T -> T*F | T/F | F\n'
                                       'F -> (E) | id')

    with raises(ParseError):
        ContextFreeGrammar.from_string('E -> T E1'
                                       'E1 -> T E1 | &'
                                       'T -> F T1'
                                       'T1 -> * FT1 | &'
                                       'F -> ( E ) | id')
예제 #4
0
def test_valid_with_whitespace():
    ContextFreeGrammar.from_string('''
        E -> E + T | E - T | T
        T -> T * F | T / F | F
        F -> ( E ) | id
    ''')

    ContextFreeGrammar.from_string('''
        E -> T E1
        E1 -> + T E1 | &
        T -> F T1
        T1 -> * F T1 | &
        F -> ( E ) | id
    ''')
예제 #5
0
def test_first_of_string():
    string = '''S -> A B C
                A -> a A | &
                B -> b B | A C d
                C -> c C | &'''

    g = ContextFreeGrammar.from_string(string)

    g.calculate_first()

    expected = set({Terminal('c'), Terminal('d')})

    got = g.first_of_string([NonTerminal('C'), Terminal('d')])

    assert got == expected
예제 #6
0
def test_remove_simple_productions():
    g = ContextFreeGrammar.from_string('''
        S -> F G H
        F -> G | a
        G -> d G | H | b
        H -> c
    ''')

    expected = ContextFreeGrammar.from_string('''
        S -> F G H
        F -> a | d G | b | c
        G -> d G | b | c
        H -> c
    ''')

    new_grammar = g.without_simple_productions()
    new_productions = sorted(
        (lhs, sorted(rhs))
        for lhs, rhs in new_grammar.production_rules.items())

    expected_productions = sorted(
        (lhs, sorted(rhs)) for lhs, rhs in expected.production_rules.items())

    assert new_productions == expected_productions
예제 #7
0
def test_n_sets():
    g = ContextFreeGrammar.from_string('''
        S -> F G H
        F -> G | a
        G -> d G | H | b
        H -> c
    ''')

    S, F, G, H = (NonTerminal(x) for x in 'SFGH')

    expected = {
        S: {S},
        F: {F, G, H},
        G: {G, H},
        H: {H},
    }

    assert g.simple_production_sets() == expected
예제 #8
0
def test_first_nt_02():
    S = NonTerminal('S')
    A = NonTerminal('A')
    B = NonTerminal('B')
    epsilon = Epsilon('&')

    string = '''S -> A b | A B c
                B -> b B | A d | &
                A -> a A | &'''

    g = ContextFreeGrammar.from_string(string)

    g.calculate_first_nt()

    expected_first_nt = {
        S: set([A, B]),
        B: set([epsilon, A]),
        A: set([epsilon]),
    }

    assert g.first_nt == expected_first_nt
예제 #9
0
def test_invalid_syntax():
    with raises(ParseError):
        ContextFreeGrammar.from_string('E + T | E - T | T\n'
                                       'T -> T * F | T / F | F\n'
                                       'F -> ( E ) | id')

    with raises(ParseError):
        ContextFreeGrammar.from_string('E -> T E1\n'
                                       'E1 ->'
                                       'T -> F T1\n'
                                       'T1 -> * F T1 | &\n'
                                       'F -> ( E ) | id')

    with raises(ParseError):
        ContextFreeGrammar.from_string('E -> E + T | E - T | T\n'
                                       'T -> T * F | T / F |\n'
                                       'F -> ( E ) | id')

    with raises(ParseError):
        ContextFreeGrammar.from_string('E -> T E1\n'
                                       'E1 -> + T E1 | &\n'
                                       'T -> F T1\n'
                                       'T1 -> | &\n'
                                       'F -> ( E ) | id')
예제 #10
0
def test_follow_02():
    a = Terminal('a')
    b = Terminal('b')
    c = Terminal('c')
    e = Terminal('e')
    eos = EoS('$')

    string = '''S -> A C | C e B | B a
                A -> a A | B C
                C -> c C | &
                B -> b B | A B | &'''

    g = ContextFreeGrammar.from_string(string)

    g.calculate_follow()

    expected_follow = {
        NonTerminal('S'): set([eos]),
        NonTerminal('A'): set([a, b, c, eos]),
        NonTerminal('C'): set([a, b, c, e, eos]),
        NonTerminal('B'): set([a, b, c, eos]),
    }

    assert g.follow == expected_follow
예제 #11
0
def test_follow_01():
    a = Terminal('a')
    b = Terminal('b')
    c = Terminal('c')
    d = Terminal('d')
    eos = EoS('$')

    string = '''S -> A B C
                A -> a A | &
                B -> b B | A C d
                C -> c C | &'''

    g = ContextFreeGrammar.from_string(string)

    g.calculate_follow()

    expected_follow = {
        NonTerminal('S'): set([eos]),
        NonTerminal('A'): set([a, b, c, d]),
        NonTerminal('B'): set([c, eos]),
        NonTerminal('C'): set([d, eos])
    }

    assert g.follow == expected_follow
예제 #12
0
def test_first_01():
    a = Terminal('a')
    b = Terminal('b')
    c = Terminal('c')
    d = Terminal('d')
    epsilon = Epsilon('&')

    string = '''S -> A B C
                A -> a A | &
                B -> b B | A C d
                C -> c C | &'''

    g = ContextFreeGrammar.from_string(string)

    g.calculate_first()

    expected_first = {
        NonTerminal('S'): set([a, b, c, d]),
        NonTerminal('A'): set([a, epsilon]),
        NonTerminal('B'): set([a, b, c, d]),
        NonTerminal('C'): set([c, epsilon])
    }

    assert g.first == expected_first
예제 #13
0
def test_first_02():
    a = Terminal('a')
    b = Terminal('b')
    c = Terminal('c')
    e = Terminal('e')
    epsilon = Epsilon('&')

    string = '''S -> A C | C e B | B a
                A -> a A | B C
                C -> c C | &
                B -> b B | A B | &'''

    g = ContextFreeGrammar.from_string(string)

    g.calculate_first()

    expected_first = {
        NonTerminal('S'): set([a, b, c, e, epsilon]),
        NonTerminal('A'): set([a, b, c, epsilon]),
        NonTerminal('C'): set([c, epsilon]),
        NonTerminal('B'): set([a, b, c, epsilon]),
    }

    assert g.first == expected_first
예제 #14
0
def test_first_nt_01():
    S = NonTerminal('S')
    A = NonTerminal('A')
    B = NonTerminal('B')
    C = NonTerminal('C')
    epsilon = Epsilon('&')

    string = '''S -> A B C
                A -> a A | &
                B -> b B | A C d
                C -> c C | &'''

    g = ContextFreeGrammar.from_string(string)

    g.calculate_first_nt()

    expected_first_nt = {
        S: set([A, B, C]),
        A: set([epsilon]),
        B: set([A, C]),
        C: set([epsilon]),
    }

    assert g.first_nt == expected_first_nt
예제 #15
0
from pprint import pprint
from chomchom import ContextFreeGrammar

g1 = ContextFreeGrammar.from_string('''
        S  -> a S1 | d S
        S1 -> S | B
        B  -> b B1
        B1 -> B | &
     ''')

g2 = ContextFreeGrammar.from_string('''
        S -> A B | B C
        A -> a A | &
        B -> b B | d
        C -> c C | c
     ''')

g3 = ContextFreeGrammar.from_string('''
        S -> a S | B C | B D
        A -> c C | A B
        B -> b B | &
        C -> a A | B C
        D -> d D d | c
     ''')

# Empty grammar
g4 = ContextFreeGrammar.from_string('''
        S -> a S
     ''')

g5 = ContextFreeGrammar.from_string('''