コード例 #1
0
def build_LR0_automaton(G: Grammar):
    assert len(G.startSymbol.productions) == 1, 'Grammar must be augmented'

    start_production = G.startSymbol.productions[0]
    start_item = Item(start_production, 0)

    automaton = State(start_item, True)

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

    while pending:
        current_item = pending.pop()
        if current_item.IsReduceItem:
            continue

        current_state = visited[current_item]
        next_symbol = current_item.NextSymbol
        next_item = current_item.NextItem()

        #- $(X --> a.cB) ---c---> (X --> ac.B)  con c in V_T
        #- $(X --> a.YB) ---Y---> (X --> aY.B)  con Y in V_N
        next_state = get_state(visited, pending, next_item)
        current_state.add_transition(next_symbol.Name, next_state)

        if next_symbol in G.nonTerminals:
            sym_productions = G.symbDict[next_symbol.Name].productions
            #- $(X --> a.YB) ---e---> (Y --> .Z)  con Y in V_N
            for pr in [Item(x, 0) for x in sym_productions]:
                trans_state = get_state(visited, pending, pr)
                current_state.add_epsilon_transition(trans_state)

    return automaton.to_deterministic(lr0_formatter)
コード例 #2
0
def build_larl1_automaton(G, firsts=None):
    assert len(G.startSymbol.productions) == 1, 'Grammar must be augmented'

    if not firsts:
        firsts = compute_firsts(G)
    firsts[G.EOF] = ContainerSet(G.EOF)

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

    closure = closure_lr1([start_item], firsts)
    automaton = State(frozenset(closure), True)

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

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

        current_closure = current_state.state
        for symbol in G.terminals + G.nonTerminals:
            goto = goto_lr1(current_closure, symbol, just_kernel=True)
            closure = closure_lr1(goto, firsts)
            center = frozenset(item.Center() for item in goto)

            if center == frozenset():
                continue

            try:
                next_state = visited[center]
                centers = {item.Center(): item for item in next_state.state}
                centers = {
                    item.Center(): (centers[item.Center()], item)
                    for item in closure
                }

                updated_items = set()
                for c, (itemA, itemB) in centers.items():
                    item = Item(c.production, c.pos,
                                itemA.lookaheads | itemB.lookaheads)
                    updated_items.add(item)

                updated_items = frozenset(updated_items)
                if next_state.state != updated_items:
                    pending.append(center)
                next_state.state = updated_items
            except KeyError:
                visited[center] = next_state = State(frozenset(closure), True)
                pending.append(center)

            if current_state[symbol.Name] is None:
                current_state.add_transition(symbol.Name, next_state)
            else:
                assert current_state.get(
                    symbol.Name) is next_state, 'Bad build!!!'

    automaton.set_formatter(multiline_formatter)
    return automaton
コード例 #3
0
def build_LR0_automaton(G):
    assert len(G.startSymbol.productions) == 1, "Grammar must be augmented"

    start_production = G.startSymbol.productions[0]
    start_item = Item(start_production, 0)

    automaton = State(start_item, True)

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

    while pending:
        current_item = pending.pop()
        if current_item.IsReduceItem:
            continue

        # (Decide which transitions to add)
        # agregar las epsilon transiciones
        # a estados donde el item posee producciones a partir del simbolo actual en la posicion 0
        # y agregar la transicion a partir del simbolo siguiente

        next_item = current_item.NextItem()
        try:
            next_state = visited[next_item]
        except KeyError:
            next_state = State(next_item, True)
            visited[next_item] = next_state
            pending.append(next_item)

        if current_item.NextSymbol.IsNonTerminal:
            epsilon_productions = current_item.NextSymbol.productions
        else:
            epsilon_productions = None

        current_state = visited[current_item]
        # (Adding the decided transitions)
        current_state.add_transition(current_item.NextSymbol.Name, next_state)

        if epsilon_productions:
            for eproduction in epsilon_productions:
                epItem = Item(eproduction, 0)
                try:
                    epState = visited[epItem]
                except KeyError:
                    epState = State(epItem, True)
                    visited[epItem] = epState
                    pending.append(epItem)
                current_state.add_epsilon_transition(epState)

    return automaton
コード例 #4
0
def build_lr0_automaton(G):
    assert len(G.startSymbol.productions) == 1, 'Grammar must be augmented'

    start_production = G.startSymbol.productions[0]
    start_item = Item(start_production, 0)
    start = frozenset([start_item])

    automaton = State(closure_lr0(start), True)

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

    while pending:
        current = pending.pop()
        current_state = visited[current]
        current_closure = current_state.state
        for symbol in G.terminals + G.nonTerminals:
            kernel = goto_lr0(current_closure, symbol)

            if kernel == frozenset():
                continue

            try:
                next_state = visited[kernel]
            except KeyError:
                next_state = visited[kernel] = State(closure_lr0(kernel), True)
                pending.append(kernel)

            current_state.add_transition(symbol.Name, next_state)
    automaton.set_formatter(multiline_formatter)
    return automaton
コード例 #5
0
def build_LALR_automaton(G):
    assert len(G.startSymbol.productions) == 1, "Grammar must be augmented"

    lr1_automaton = build_LR1_automaton(G)

    same_kernel = {}
    for node in lr1_automaton:
        just_center = frozenset([item.Center() for item in node.state])
        try:
            same_kernel[just_center].append(node)
        except KeyError:
            same_kernel[just_center] = [node]

    start = frozenset([item.Center() for item in lr1_automaton.state
                       ])  # como cabecera solo quedan los items sin lookahead
    automaton = State(
        lr1_automaton.state, True
    )  # en visited se guarda el estado que corresponde a la fusion de estaods ocn el mismo nucleo

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

    while pending:
        current = pending.pop()
        current_state = visited[current]  # se van a actualizar
        # todos los estados con los que el estado actual tiene alguna transicion
        lr1_state = same_kernel[current][0]

        # chequear que cada estado del cjto analizado tenga esa transicion
        for symbol in G.terminals + G.nonTerminals:
            if lr1_state.has_transition(symbol.Name):
                state = lr1_state.transitions[symbol.Name][0]
                center_items = frozenset(
                    [item.Center() for item in state.state])
                try:
                    next_state = visited[center_items]
                except KeyError:
                    kernel_set = same_kernel[center_items]
                    items_with_lookahead = {}
                    for node in kernel_set:
                        for item in node.state:
                            try:
                                current_item = items_with_lookahead[
                                    item.Center()]
                            except KeyError:
                                current_item = items_with_lookahead[
                                    item.Center()] = set()
                            current_item.update(item.lookaheads)
                    completed_items = [
                        Item(item.production, item.pos, lookaheads)
                        for item, lookaheads in items_with_lookahead.items()
                    ]
                    next_state = State(frozenset(completed_items), True)
                    visited[center_items] = next_state
                    pending.append(center_items)

                current_state.add_transition(symbol.Name, next_state)

    automaton.set_formatter(multiline_formatter)
    return automaton
コード例 #6
0
    def build_LR1_automaton(self, G):
        assert len(G.startSymbol.productions) == 1, 'Grammar must be augmented'
        
        firsts = compute_firsts(G)
        firsts[G.EOF] = ContainerSet(G.EOF)
        
        start_production = G.startSymbol.productions[0]
        start_item = Item(start_production, 0, lookaheads=(G.EOF,))
        start = frozenset([start_item])
        
        closure = self.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 G.terminals + G.nonTerminals:
                closure_current = self.closure_lr1(current, firsts)
                goto = self.goto_lr1(closure_current, symbol, just_kernel=True)
                if len(goto) == 0:
                    continue
                try:
                    next_state = visited[goto]
                except KeyError:
                    next_closure = self.closure_lr1(goto, firsts)
                    visited[goto] = next_state = State(frozenset(next_closure), True)
                    pending.append(goto)

                current_state.add_transition(symbol.Name, next_state)
        
        automaton.set_formatter(multiline_formatter)
        return automaton
コード例 #7
0
def closure_lr0(items):
    closure = ContainerSet(*items)

    pending = list(items)
    while pending:
        current = pending.pop()
        symbol = current.NextSymbol

        if current.IsReduceItem or symbol.IsTerminal:
            continue

        new_items = [
            Item(p, 0) for p in symbol.productions if Item(p, 0) not in closure
        ]
        pending += new_items
        closure.extend(new_items)
    return frozenset(closure)
コード例 #8
0
ファイル: parserSLR1.py プロジェクト: svex99/compilers1
def build_LR0_automaton(G):
    assert len(G.startSymbol.productions) == 1, 'Grammar must be augmented'

    start_production = G.startSymbol.productions[0]
    start_item = Item(start_production, 0)

    automaton = State(start_item, True)

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

    while pending:
        current_item = pending.pop()
        if current_item.IsReduceItem:
            continue

        # Your code here!!! (Decide which transitions to add)
        current_state = visited[current_item]
        next_symbol = current_item.NextSymbol
        next_item = current_item.NextItem()
        try:
            next_state = visited[next_item]
        except KeyError:
            next_state = State(next_item, True)
            visited[next_item] = next_state
        current_state.add_transition(next_symbol.Name, next_state)
        # print('Added trans:  ', current_state, f'==={next_symbol.Name}===>', next_state)
        pending.append(next_item)

        if next_symbol.IsNonTerminal:   # If symbol is non terminal, add e-productions to Y->.alpha
            for prod in next_symbol.productions:
                new_item = Item(prod, 0)
                try:
                    new_state = visited[new_item]
                    item_was_found = True
                except KeyError:
                    new_state = State(new_item, True)
                    visited[new_item] = new_state
                    item_was_found = False
                current_state.add_epsilon_transition(new_state)
                # print('Added e-trans:', current_state, '==>', new_state)
                if not item_was_found:
                    pending.append(new_item)

    return automaton
コード例 #9
0
def build_LR0_automaton(G):
    assert len(G.startSymbol.productions) == 1, 'Grammar must be augmented'

    start_production = G.startSymbol.productions[0]
    start_item = Item(start_production, 0)

    automaton = State(start_item, True)

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

    while pending:
        current_item = pending.pop()
        if current_item.IsReduceItem:
            continue

        # Your code here!!! (Decide which transitions to add)
        new_item = current_item.NextItem()
        transition_symbol = current_item.NextSymbol.Name
        next_items = [(new_item, transition_symbol)]

        if current_item.NextSymbol in G.nonTerminals:
            for production in current_item.NextSymbol.productions:
                new_item = Item(production, 0)
                next_items.append((new_item, G.Epsilon))

        current_state = visited[current_item]
        # Your code here!!! (Add the decided transitions)
        for item, symbol in next_items:
            try:
                state = visited[item]
            except KeyError:
                state = State(item, True)
                visited[item] = state
                pending.append(item)

            if symbol == G.Epsilon:
                current_state.add_epsilon_transition(state)
            else:
                current_state.add_transition(symbol, state)

    return automaton
コード例 #10
0
ファイル: tools.py プロジェクト: cicr99/TypeInferencer
def expand(item, firsts):
    next_symbol = item.NextSymbol
    if next_symbol is None or not next_symbol.IsNonTerminal:
        return []

    lookaheads = ContainerSet()
    for preview in item.Preview():
        lookaheads.hard_update(compute_local_first(firsts, preview))

    assert not lookaheads.contains_epsilon
    return [Item(prod, 0, lookaheads) for prod in next_symbol.productions]
コード例 #11
0
    def compress(self, items):
        centers = {}

        for item in items:
            center = item.Center()
            try:
                lookaheads = centers[center]
            except KeyError:
                centers[center] = lookaheads = set()
            lookaheads.update(item.lookaheads)
        
        return { Item(x.production, x.pos, set(lookahead)) for x, lookahead in centers.items() }
コード例 #12
0
def build_LR0_automaton(G):
    assert len(G.startSymbol.productions) == 1, 'Grammar must be augmented'

    start_production = G.startSymbol.productions[0]
    start_item = Item(start_production, 0)

    automaton = State(start_item, True)

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

    while pending:
        current_item = pending.pop()
        if current_item.IsReduceItem:
            continue
            
        state = visited[current_item]
        next_item = current_item.NextItem()
        try:
            new_state = visited[next_item]
        except KeyError:
            new_state = visited[next_item] = State(next_item, True)
            pending.append(next_item)
        
        next_symbol = current_item.NextSymbol
        state.add_transition(next_symbol.Name, new_state)
        
        if next_symbol.IsNonTerminal:
            for prod in next_symbol.productions:
                item = Item(prod, 0)
                try:
                    visited[item]
                except KeyError:
                    visited[item] = State(item, True)
                    pending.append(item)
                state.add_epsilon_transition(visited[item])

        current_state = visited[current_item]
        
    return automaton
コード例 #13
0
def expand(item, firsts):
    next_symbol = item.NextSymbol
    if next_symbol is None or not next_symbol.IsNonTerminal:
        return []

    lookaheads = ContainerSet()
    # Your code here!!! (Compute lookahead for child items)
    for string in item.Preview():
        lookaheads.update(compute_local_first(firsts, string))

    assert not lookaheads.contains_epsilon
    # Your code here!!! (Build and return child items)
    return [Item(prod, 0, lookaheads) for prod in next_symbol.productions]
コード例 #14
0
def build_LR0_automaton(G):
    assert len(G.startSymbol.productions) == 1, 'Grammar must be augmented'

    start_production = G.startSymbol.productions[0]
    start_item = Item(start_production, 0)

    automaton = State(start_item, True)
    pending = [start_item]
    visited = {start_item: automaton}

    while pending:
        current_item = pending.pop()
        if current_item.IsReduceItem:
            continue

        next_item = current_item.NextItem()
        symbol = current_item.NextSymbol

        try:
            visited[current_item].add_transition(symbol.Name,
                                                 visited[next_item])
        except:
            visited[next_item] = State(next_item, True)
            visited[current_item].add_transition(symbol.Name,
                                                 visited[next_item])
            pending.append(next_item)

        if symbol.IsNonTerminal:
            prod = symbol.productions
            for p in prod:
                item = Item(p, 0)
                try:
                    visited[current_item].add_epsilon_transition(visited[item])
                except KeyError:
                    visited[item] = State(item, True)
                    visited[current_item].add_epsilon_transition(visited[item])
                    pending.append(item)

    return automaton
コード例 #15
0
def build_LALR1_automaton(G):
    automaton = build_LR1_automaton(G)

    stKernel = {}
    for node in automaton:
        kernel = frozenset([item.Center() for item in node.state])
        try:
            stKernel[kernel].append(node)
        except KeyError:
            stKernel[kernel] = [node]

    initial = frozenset([item.Center() for item in automaton.state])
    automaton = State(automaton.state, True)

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

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

        for symbol in G.terminals + G.nonTerminals:
            if symbol.Name in lr1_state.transitions:
                dest_core = frozenset([
                    item.Center()
                    for item in lr1_state.transitions[symbol.Name][0].state
                ])

                try:
                    next_state = visited[dest_core]

                except KeyError:
                    union_core = {center: set() for center in dest_core}
                    for node in stKernel[dest_core]:
                        for item in node.state:
                            union_core[item.Center()].update(item.lookaheads)
                    union_core = frozenset([
                        Item(center.production,
                             center.pos,
                             lookaheads=lookaheads)
                        for center, lookaheads in union_core.items()
                    ])
                    next_state = State(union_core, True)
                    visited[dest_core] = next_state
                    pending.append(dest_core)
                current_state.add_transition(symbol.Name, next_state)

    automaton.set_formatter(multiline_formatter)
    return automaton
コード例 #16
0
def expand(item, firsts):
    next_symbol = item.NextSymbol
    if next_symbol is None or not next_symbol.IsNonTerminal:
        return []
    lookaheads = ContainerSet()
    for prev in item.Preview():
        new_first = compute_local_first(firsts, prev)
        lookaheads.update(new_first)

    assert not lookaheads.contains_epsilon
    result = []
    for prod in next_symbol.productions:
        result.append(Item(prod, 0, lookaheads))

    return result
コード例 #17
0
def expand(item, firsts):
    next_symbol = item.NextSymbol
    if next_symbol is None or not next_symbol.IsNonTerminal:
        return []

    lookaheads = ContainerSet()
    # Your code here!!! (Compute lookahead for child items)
    for preview in item.Preview():
        lookaheads.hard_update(compute_local_first(firsts, preview))

    assert not lookaheads.contains_epsilon
    # Your code here!!! (Build and return child items)
    items = []
    for production in next_symbol.productions:
        items.append(Item(production, 0, lookaheads))
    return items
コード例 #18
0
def expand(item, firsts):
    next_symbol = item.NextSymbol
    if next_symbol is None or not next_symbol.IsNonTerminal:
        return []

    lookaheads = ContainerSet(
    )  # lookahead = que yo quiero ver cuando vaya a reducir
    # Your code here!!! (Compute lookahead for child items)

    for prev in item.Preview():
        lookaheads.update(compute_local_first(firsts, prev))

    assert not lookaheads.contains_epsilon

    # Your code here!!! (Build and return child items)
    return [Item(x, 0, lookaheads) for x in next_symbol.productions]
コード例 #19
0
def expand(item, firsts):
    next_symbol = item.NextSymbol

    if next_symbol is None or next_symbol.IsTerminal:
        return []

    lookaheads = ContainerSet()
    result = []
    for preview in item.Preview():
        lookaheads.update(compute_local_firsts(firsts, preview))

    assert not lookaheads.contains_epsilon, "lookaheads contains epsilon"
    result = []
    for i, production in enumerate(next_symbol.productions):
        result.append(Item(production, 0, lookaheads))
    return result
コード例 #20
0
ファイル: parserLALR1.py プロジェクト: svex99/compilers1
def build_lalr_automaton(G):
    def centers(items: [Item]):
        return frozenset(item.Center() for item in items)

    def lookaheads(items: [Item]):
        return {item.Center(): item.lookaheads for item in items}

    def subset(items1, items2):
        return all(items1[i] <= items2[i] for i in items1)

    assert len(G.startSymbol.productions) == 1, 'Grammar must be augmented'
    firsts = compute_firsts(G)
    firsts[G.EOF] = ContainerSet(G.EOF)

    start_production = G.startSymbol.productions[0]
    start_item = Item(start_production, 0, (G.EOF, ))

    start = State(frozenset(closure_lr1([start_item], firsts)), True)

    pending = [start_item]
    visisted_centers = {centers(start.state): start}
    visited = {start_item: start}

    while pending:
        current_state = visited[pending.pop()]
        for symbol in G.terminals + G.nonTerminals:
            next_item = frozenset(goto_lr1(current_state.state, symbol,
                                           firsts))

            if next_item:
                try:
                    next_state = visisted_centers[centers(next_item)]
                    if not subset(lookaheads(next_item),
                                  lookaheads(next_state.state)):
                        next_state.state = compress(
                            list(next_state.state) + list(next_item))
                        pending.append(frozenset(next_state.state))
                        visited[frozenset(next_state.state)] = next_state
                except KeyError:
                    next_state = State(next_item, True)
                    pending += [next_item]
                    visisted_centers[centers(next_item)] = next_state
                    visited[next_item] = next_state
                current_state.add_transition(symbol.Name, next_state)

    return start
コード例 #21
0
    def find_conflict(self):
        conflicts = []
        automaton_reverse, state_dict = state_transpose(self.automaton)
        for key, value in self.action.items():
            if type(value) == type(set()):
                conflict_productions = [
                    x[1] for x in value if isinstance(x[1], Production)
                ]
                for production in conflict_productions:
                    conflict_state = state_dict[key[0]][0]
                    conflict_item = find_conflict_item(conflict_state,
                                                       production)
                    stack = [(conflict_state, conflict_item)]

                    sentence = [y for y in production.Right]
                    sentence.reverse()
                    current_state = conflict_state
                    current_item = conflict_item
                    for y in sentence:
                        current_item = Item(current_item.production,
                                            current_item.pos - 1,
                                            current_item.lookaheads)
                        current_state = go_back(current_state, y, current_item,
                                                state_dict)
                        stack.append((current_state, current_item))
                    stack.reverse()

                    initial_item = find_initial_item(self.automaton)
                    path = [(self.automaton, initial_item, False)]
                    visited = {(initial_item, self.automaton.idx)}
                    find_path_to(
                        stack[0][0], stack[0][1], self.automaton, initial_item,
                        path, visited
                    )  # una lista de tuplas que es (estado en que estoy,item en el que estoy)

                    terminals = items_to_terminals(path[:len(path) - 1], stack)
                    conflicts.append(
                        self._generate_error(value, terminals,
                                             [x[1] for x in path] +
                                             [x[1] for x in stack[1:]], key[0],
                                             key[1]))
                    break

        return conflicts
コード例 #22
0
def build_LR1_automaton(G):
    assert len(G.startSymbol.productions) == 1, "Grammar must be augmented"

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

    start_production = G.startSymbol.productions[0]
    start_item = Item(start_production, 0, lookaheads=(G.EOF, ))
    start = frozenset([start_item])  # como cabecera solo queda el kernel

    closure = closure_lr1(start, firsts)
    automaton = State(frozenset(closure),
                      True)  # en visited si se guarda el estado completo

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

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

        closure = closure_lr1(current, firsts)
        for symbol in G.terminals + G.nonTerminals:
            # (Get/Build `next_state`)
            # closure = closure_lr1(current,firsts)
            goto = goto_lr1(closure, symbol, firsts, True)

            if not goto:
                continue

            try:
                next_state = visited[goto]
            except KeyError:
                next_state = visited[goto] = State(
                    frozenset(closure_lr1(goto, firsts)), True)
                pending.append(goto)

            current_state.add_transition(symbol.Name, next_state)

    automaton.set_formatter(multiline_formatter)
    return automaton
コード例 #23
0
def build_LR1_automaton(G):
    assert len(G.startSymbol.productions) == 1, 'Grammar must be augmented'

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

    start_production = G.startSymbol.productions[0]
    start_item = Item(start_production, 0, lookaheads=(G.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 G.terminals + G.nonTerminals:
            # Your code here!!! (Get/Build `next_state`)
            next_state_key = goto_lr1(current_state.state,
                                      symbol,
                                      just_kernel=True)
            # next_state_key = frozenset([i.NextItem() for i in current_state.state if i.NextSymbol == symbol])
            if not next_state_key:
                continue
            try:
                next_state = visited[next_state_key]
            except KeyError:
                next_state_items = goto_lr1(current_state.state, symbol,
                                            firsts)
                next_state = State(frozenset(next_state_items), True)
                pending.append(next_state_key)
                visited[next_state_key] = next_state
            current_state.add_transition(symbol.Name, next_state)

    automaton.set_formatter(multiline_formatter)
    return automaton
コード例 #24
0
def FindStart(automata, state_conf, reduce_item_conflict):
    #Calcular las transiciones inversas
    ReverseAutomaton(automata)

    #Reducir el item de conflicto
    symbols_to_reduce = []
    for symbol in reduce_item_conflict.production.Right:
        symbols_to_reduce.append(symbol)

    items_way_reverse = [(reduce_item_conflict, state_conf)]
    current_state = state_conf
    current_item = reduce_item_conflict
    item_pos = current_item.pos
    while symbols_to_reduce:
        #Mover al estado anterior
        symbol = symbols_to_reduce.pop()
        current_state = current_state.reverse_transitions[symbol.Name][0]

        item_pos -= 1
        items_way_reverse.append((Item(reduce_item_conflict.production, item_pos), current_state))
    
    return items_way_reverse[::-1]
コード例 #25
0
def build_lr1_automaton(G, firsts=None):
    assert len(G.startSymbol.productions) == 1, 'Grammar must be augmented'

    if not firsts:
        firsts = compute_firsts(G)
    firsts[G.EOF] = ContainerSet(G.EOF)

    start_production = G.startSymbol.productions[0]
    start_item = Item(start_production, 0, lookaheads=(G.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]

        current_closure = current_state.state
        for symbol in G.terminals + G.nonTerminals:
            kernel = goto_lr1(current_closure, symbol, just_kernel=True)

            if kernel == frozenset():
                continue

            try:
                next_state = visited[kernel]
            except KeyError:
                goto = closure_lr1(kernel, firsts)
                visited[kernel] = next_state = State(frozenset(goto), True)
                pending.append(kernel)
            current_state.add_transition(symbol.Name, next_state)

    automaton.set_formatter(multiline_formatter)
    return automaton
コード例 #26
0
 def expand(self, item, firsts):
     next_symbol = item.NextSymbol
     if next_symbol is None or not next_symbol.IsNonTerminal:
         return []
     
     lookaheads = ContainerSet()
     new_items = []
     previews = item.Preview()
     for preview in previews:
         sentence = self.G.Epsilon
         for symbol in preview:
             sentence = sentence + symbol
         try:
             prev_first = firsts[sentence]
         except KeyError:
             prev_first = firsts[sentence] = compute_local_first(firsts, preview)
         
         lookaheads.update(prev_first)
         
     for prod in next_symbol.productions:
         new_item = Item(prod, 0, lookaheads = lookaheads)
         new_items.append(new_item)
     
     return new_items