Esempio n. 1
0
def expand(item, firsts):
    next_symbol = item.NextSymbol
    if next_symbol is None or not next_symbol.IsNonTerminal:
        return []

    look_a_heads = ContainerSet()

    for preview in item.Preview():
        look_a_heads.hard_update(compute_local_first(firsts, preview))

    assert not look_a_heads.contains_epsilon

    return [[Item(prod, 0, look_a_heads)] for prod in next_symbol.productions]
Esempio n. 2
0
def compute_firsts(G):
    firsts = {}
    change = True

    # init First(Vt)
    for terminal in G.terminals:
        firsts[terminal] = ContainerSet(terminal)

    # init First(Vn)
    for non_terminal in G.nonTerminals:
        firsts[non_terminal] = ContainerSet()

    while change:
        change = False

        # P: X -> alpha
        for production in G.Productions:
            X = production.Left
            alpha = production.Right

            # get current First(X)
            first_x = firsts[X]

            # init First(alpha)
            try:
                first_alpha = firsts[alpha]
            except:
                first_alpha = firsts[alpha] = ContainerSet()

            # CurrentFirst(alpha)???
            local_first = compute_local_first(firsts, alpha)

            # update First(X) and First(alpha) from CurrentFirst(alpha)
            change |= first_alpha.hard_update(local_first)
            change |= first_x.hard_update(local_first)

    # First(Vt) + First(Vt) + First(RightSides)
    return firsts
Esempio n. 3
0
def compute_follows(G, firsts):
    follows = {}
    change = True

    # init Follow(Vn)
    for non_terminal in G.nonTerminals:
        follows[non_terminal] = ContainerSet()
    follows[G.startSymbol] = ContainerSet(G.EOF)

    while change:
        change = False

        # P: X -> alpha
        for production in G.Productions:
            X = production.Left
            alpha = production.Right

            for w in range(0, len(alpha)):
                if alpha[w].IsTerminal:
                    continue

                if w < len(alpha) - 1:
                    t = alpha[w + 1]
                else:
                    t = G.Epsilon
                    if w == len(alpha) - 1:
                        change = follows[alpha[w]].add(follows[X])
                        continue
                first = firsts[t]
                cop = copy.copy(first)
                cop.set_epsilon(False)
                change = follows[alpha[w]].add(cop)
                if first.contains_epsilon:
                    change = follows[alpha[w]].add(follows[X])

    return follows
Esempio n. 4
0
def epsilon_closure(automaton, states):
    pending = [s for s in states
               ]  # equivalente a list(states) pero me gusta así :p
    closure = {s
               for s in states
               }  # equivalente a  set(states) pero me gusta así :p

    while pending:
        state = pending.pop()
        for trans in automaton.epsilon_transitions(state):
            if not trans in closure:
                pending.append(trans)
                closure.add(trans)

    resp = ContainerSet(*closure)
    return resp
Esempio n. 5
0
def closure_lr1(items, firsts):
    closure = ContainerSet(*items)

    changed = True
    while changed:
        changed = False

        new_items = ContainerSet()
        for item in closure:
            exp = expand(item, firsts)
            new_items.extend(exp)

        changed = closure.update(new_items)

    return compress(closure)
Esempio n. 6
0
def compute_local_first(firsts, alpha):
    first_alpha = ContainerSet()

    try:
        alpha_is_epsilon = alpha.IsEpsilon
    except:
        alpha_is_epsilon = False
    if alpha_is_epsilon:
        first_alpha.set_epsilon()

    else:
        for symbol in alpha:
            first_alpha.update(firsts[symbol])
            if not firsts[symbol].contains_epsilon:
                break
        else:
            first_alpha.set_epsilon()

    return first_alpha
Esempio n. 7
0
def build_lr1_automaton(grammar):
    assert len(grammar.startSymbol.productions) == 1, 'Grammar must be augmented'

    firsts = compute_firsts(grammar)
    firsts[grammar.EOF] = ContainerSet(grammar.EOF)

    start_production = grammar.startSymbol.productions[0]
    start_item = Item(start_production, 0, lookaheads=(grammar.EOF,))
    start = frozenset([start_item])

    closure = closure_lr1(start, firsts)
    automaton = State(frozenset(closure), True)

    pending = [start]
    visited = {start: automaton}

    while pending:
        current = pending.pop()
        current_state = visited[current]

        for symbol in grammar.terminals + grammar.nonTerminals:

            kernels = goto_lr1(current_state.state, symbol, just_kernel=True)

            if not kernels:
                continue

            try:
                next_state = visited[kernels]
            except KeyError:
                pending.append(kernels)
                visited[pending[-1]] = next_state = State(frozenset(goto_lr1(current_state.state, symbol, firsts)),
                                                          True)

            current_state.add_transition(symbol.Name, next_state)

    automaton.set_formatter(multi_line_formatter)
    return automaton