Beispiel #1
0
    def _build_parsing_table(self):
        G = self.G.AugmentedGrammar(True)
        firsts = compute_firsts(G)
        follows = compute_follows(G, firsts)

        automaton = build_LR0_automaton(G).to_deterministic()
        for i, node in enumerate(automaton):
            if self.verbose:
                print(i, '\t', '\n\t '.join(str(x) for x in node.state), '\n')
            node.idx = i

        for node in automaton:
            idx = node.idx
            for state in node.state:
                item = state.state
                # Your code here!!!
                # - Fill `self.Action` and `self.Goto` according to `item`)
                # - Feel free to use `self._register(...)`)
                if item.IsReduceItem:
                    prod = item.production
                    if prod.Left == G.startSymbol:
                        self._register(self.action, (idx, G.EOF), (self.OK, None))
                    else:
                        for t in follows[prod.Left]:
                            self._register(self.action, (idx, t), (self.REDUCE, prod))
                else:
                    symbol = item.NextSymbol
                    goto_id = node.get(symbol.Name).idx
                    if goto_id is not None:
                        if symbol.IsTerminal:
                            self._register(self.action, (idx, symbol), (self.SHIFT, goto_id))
                        else:
                            self._register(self.goto, (idx, symbol), goto_id)
Beispiel #2
0
def first_follows():
    result = gp.load_grammar()
    if result[0]:
        st.error('No se ha definido una gramatica\
             o la gramatica definida no es correcta')
        st.error('Errors: ' + str(result[1]))
    else:
        G = result[1]

        firsts = compute_firsts(G)
        follows = compute_follows(G, firsts)

        st.subheader('Firsts:')

        st.write(
            pd.DataFrame({
                'keys': firsts.keys(),
                'values': firsts.values()
            }))

        st.subheader('Follows:')

        st.write(
            pd.DataFrame({
                'keys': follows.keys(),
                'values': follows.values()
            }))
Beispiel #3
0
def isLL1(G, M=None):
    if not M:
        firsts = compute_firsts(G)
        follows = compute_follows(G, firsts)
        M = build_parsing_table(G, firsts, follows)

    for cell in M:
        if len(M[cell]) > 1:
            return False
    return True
Beispiel #4
0
def build_parsing_table(G, firsts=None, follows=None):
    # init parsing table
    if firsts is None:
        firsts = compute_firsts(G)
    if follows is None:
        follows = compute_follows(G, firsts)
    M = {}

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

        ###################################################
        # working with symbols on First(alpha) ...
        ###################################################
        #                   <CODE_HERE>                   #
        ###################################################

        first = compute_local_first(firsts, alpha)

        for t in first:
            if M.get((X, t)):
                M[(X, t)].append(production)
            else:
                M[(X, t)] = [production]

        ###################################################
        # working with epsilon...
        ###################################################
        #                   <CODE_HERE>                   #
        ###################################################

        try:
            alpha_is_epsilon = alpha.IsEpsilon
        except:
            alpha_is_epsilon = False

        if alpha_is_epsilon:
            for t in follows[X]:
                if M.get((X, t)):
                    M[(X, t)].append(production)
                else:
                    M[(X, t)] = [production]

    # parsing table is ready!!!
    return M
Beispiel #5
0
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
Beispiel #6
0
def generate_lr_conflict_string(G, parser):
    automaton = build_LR1_automaton(G.AugmentedGrammar(True))
    states = {}

    for it, node in enumerate(automaton):
        states[it] = node

    # for conf in parser.conflicts:
    #     print(f'conf.key {conf.key}, conf.value {conf.value}')
    #     if conf.value[0][0] == 'REDUCE':
    #         st, symbol = conf.key
    #         production = conf.value[0][1]
    #         print(states[st])
    #     if conf.value[1][0] == 'REDUCE':
    #         st, symbol = conf.key
    #         production = conf.value[1][1]
    #         print(states[st])

    st, symbol = parser.conflicts.key
    _, production = parser.action[st, symbol].pop()
    print(f'state: {st}')
    print(f'symbol: {symbol}')

    assert (st is not None and production is not None and symbol is not None)

    print(production)
    input()
    path = sentence_path(automaton, states[st], symbol, production)

    for p in path:
        print(f'path: {p}')
    input()

    firsts = compute_firsts(G)
    follows = compute_follows(G, firsts)

    extended = expand_path(automaton, path, follows)

    return extended
Beispiel #7
0
def LL1_to_dataframe(G):
    firsts = compute_firsts(G)
    follows = compute_follows(G, firsts)
    M = build_parsing_table(G, firsts, follows)

    rows, columns = set(), set()
    matrix = []

    for item in M:
        rows.add(item[0])
        columns.add(item[1])

    for row in rows:
        matrix.append([])
        for column in columns:
            try:
                production = M[row, column][0]
                matrix[-1].append(
                    str(production.Left) + ' -> ' + str(production.Right))
            except KeyError:
                matrix[-1].append(' ')

    return pd.DataFrame(matrix, index=rows, columns=columns)
Beispiel #8
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`)
            closure = closure_lr1(current, firsts)
            goto = frozenset(goto_lr1(closure, symbol, just_kernel=True))
            if not goto:
                continue
            try:
                next_state = visited[goto]
            except KeyError:
                closure = closure_lr1(goto, firsts)
                next_state = visited[goto] = State(frozenset(closure), True)
                pending.append(goto)
            current_state.add_transition(symbol.Name, next_state)

    automaton.set_formatter(multiline_formatter)
    return automaton
Beispiel #9
0
def LL1_to_dataframe(G):
    firsts = compute_firsts(G)
    follows = compute_follows(G, firsts)
    M = build_parsing_table(G, firsts, follows)

    rows, columns = set(), set()
    matrix = []

    for item in M:
        rows.add(item[0])
        columns.add(item[1])

    for row in rows:
        matrix.append([])
        for column in columns:
            try:
                productions = ""
                for prod in M[row, column]:
                    productions += f'{prod.Left} -> {prod.Right}\n'
                matrix[-1].append(productions)
            except KeyError:
                matrix[-1].append(' ')

    return pd.DataFrame(matrix, index=rows, columns=columns)
Beispiel #10
0
        if isLL1(new_G):
            st.success('La gramática transformada es LL(1).')
        else:
            st.error('La gramática transformada tampoco es LL(1).')

# Calcular Firsts & Follows
elif choice == choices[2]:
    result = gp.load_grammar()
    if result[0]:
        st.error('No se ha definido una gramatica\
             o la gramatica definida no es correcta')
        st.error('Errors: ' + str(result[1]))
    else:
        G = result[1]

        firsts = compute_firsts(G)
        follows = compute_follows(G, firsts)

        st.subheader('Firsts:')

        st.write(pd.DataFrame({
            'keys': firsts.keys(),
            'values': firsts.values()
        }))

        st.subheader('Follows:')

        st.write(pd.DataFrame({
            'keys': follows.keys(),
            'values': follows.values()
        }))
Beispiel #11
0
def metodo_predictivo_no_recursivo(G, M=None, firsts=None, follows=None):

    # checking table...
    if M is None:
        if firsts is None:
            firsts = compute_firsts(G)
        if follows is None:
            follows = compute_follows(G, firsts)
        M = build_parsing_table(G, firsts, follows)
    
    
    # parser construction...
    def parser(w):
        
        ###################################################
        # w ends with $ (G.EOF)
        ###################################################
        # init:
        ### stack =  ????
        ### cursor = ????
        ### output = ????
        ###################################################
        stack = [G.startSymbol]
        cursor = 0
        output = []
        
        # parsing w...
        while len(stack) > 0 and cursor < len(w):
            top = stack.pop()
            a = w[cursor]
    
            ###################################################
            #                   <CODE_HERE>                   #
            ###################################################

            nextToken = cursor
            
            if top.IsTerminal:
                nextToken += 1
                
                if a != top:
                    # print(a, "!=", top)
                    return False
            
            elif top.IsNonTerminal:
                if not M.get((top, w[nextToken])):
                    return False
                production = M[ (top, w[nextToken]) ][0]
                prodRight = production.Right
                
                # if not production:
                #     return False
                
                output.append(production)
                
                for i in range(len(prodRight) - 1, -1, -1):
                    stack.append(prodRight[i])
                
            cursor = nextToken
        
        if len(stack) or cursor != len(w) - 1:
            # print("different size: ", len(stack), "!= 0 or", cursor, "!=", len(w))
            # print("the partial output is: ", output)
            return False
        # left parse is ready!!!
        return output
    
    # parser is ready!!!
    return parser