Example #1
0
def G9():
    G = Grammar()
    E = G.NonTerminal('E', True)
    T, F = G.NonTerminals('T F')
    num, plus, star, opar, cpar = G.Terminals('n + * ( )')

    E %= E + plus + T | T
    T %= T + star + F | F
    F %= num | opar + E + cpar

    return G
Example #2
0
def G8():
    G = Grammar()
    A = G.NonTerminal('A', True)
    B, C = G.NonTerminals('B C')
    x, y, z = G.Terminals('x y z')

    A %= C + x + A | G.Epsilon
    B %= x + C + y | x + C
    C %= x + B + x | z

    return G
Example #3
0
def __unit_testing_get_grammar():
    G = Grammar()
    E = G.NonTerminal('E', True)
    T, F, X, Y = G.NonTerminals('T F X Y')
    plus, minus, star, div, opar, cpar, num = G.Terminals('+ - * / ( ) num')

    E %= T + X
    X %= plus + T + X | minus + T + X | G.Epsilon
    T %= F + Y
    Y %= star + F + Y | div + F + Y | G.Epsilon
    F %= num | opar + E + cpar
    return G
Example #4
0
def G4():
    G = Grammar()
    E = G.NonTerminal('E', True)
    B = G.NonTerminal('B')
    cero, one, plus, star = G.Terminals('0 1 + *')

    E %= E + star + B
    E %= E + plus + B
    E %= B
    B %= cero
    B %= one

    return G
Example #5
0
def G2():
    G = Grammar()

    S = G.NonTerminal('A', True)
    E, T, F = G.NonTerminals('E T F')
    plus, opar, cpar, mul, n = G.Terminals('+ ( ) * n')

    S %= E
    E %= T | E + plus + T
    T %= F | T + mul + F
    F %= n | opar + E + cpar

    return G
Example #6
0
def remove_unit(G: Grammar):
    """
    Removes unit productions from G.
    Additionally this removes cycles.
    """
    def is_unit(p: Production) -> bool:
        """
        True if production have the form A -> B
        """
        return len(p.Right) == 1 and p.Right[0].IsNonTerminal

    prods = [prod for prod in G.Productions]

    unit_prods = [p for p in prods if is_unit(p)]
    variables = {p.Left.Name: {p.Right[0].Name} for p in unit_prods}

    change = True
    while change:
        change = False
        for v in variables:
            l = len(variables[v])
            iter_set = {s for s in variables[v]}
            for s in iter_set:
                if s == v:  # Do not check own set of a variable
                    continue
                try:
                    for x in variables[s]:
                        if v != x:  # Avoids add a key to his set
                            variables[v].add(x)
                except KeyError:  # Reached a symbol that belongs to right part of an unit prod
                    pass  # that is not in variables' keys (is not left part of a unit prod)
            if l != len(variables[v]):
                change = True
    # for x in variables.items():
    #     print(x)

    for v in variables:
        for s in variables[v]:
            for p in G[s].productions:
                if not is_unit(p):
                    prods.append(Production(G[v], p.Right))

    # Replace old productions by new productions
    # Don't add unit productions
    G.Productions = []  # Clean grammar productions
    for nt in G.nonTerminals:  # Clean non terminals productions
        nt.productions = []
    for p in prods:  # Add new productions
        if not is_unit(p):
            G.Add_Production(p)
def change_grammar_from_productions(gramm:Grammar,new_productions):
    """
    Empty all non terminal and grammar productions\n
    and add all productions in new_productions to gramm
    """
    for x in gramm.nonTerminals:
        x.productions = []
    
    gramm.Productions = []
    
    for x in new_productions:
        gramm.Add_Production(x)
    
    return gramm
def fix_non_derive_terminal(gramm:Grammar,return_derivations = False,left_derivation = True):
    """
    Remove from gramm the non terminals A that dont satisfy:\n
    A->*w  where w in {G.T}*
    return grammar 
    return grammar,derivation
    """
    gramm = gramm.copy()
    
    derivation = { x:[Production(x,Sentence(x)),] for x in gramm.terminals }
    derivation[gramm.Epsilon] = [Production(gramm.Epsilon,Sentence(gramm.Epsilon)),]
    derive_something = set(gramm.terminals)
    productions = set(gramm.Productions)
    
    change = -1
    while change != len(derive_something):
        change = len(derive_something)
        to_remove = []
        for x in productions:
            if not any([y for y in x.Right if not y in derive_something]): # if y ->* w with w in T*
                derive_something.add(x.Left)
                update_derivation(x,derivation,left_derivation)
                to_remove.append(x)
        for x in to_remove: productions.remove(x)
    
    remove_unnecessary_symbols(gramm,[x for x in gramm.nonTerminals if x not in derive_something])
    
    if return_derivations:
        return gramm,derivation
    return gramm
Example #9
0
def unit_testing():
    G = Grammar()
    E = G.NonTerminal('E', True)
    A = G.NonTerminal('A')
    equal, plus, num = G.Terminals('= + int')

    E %= A + equal + A | num
    A %= num + plus + A | num

    parser = LR1(G)
    derivation = parser([num, plus, num, equal, num, plus, num, G.EOF])

    assert str(
        derivation
    ) == '[A -> int, A -> int + A, A -> int, A -> int + A, E -> A = A]'
    return "LR1"
Example #10
0
def eliminate_left_recursion(G: Grammar):
    recursive_prod = {}
    for production in G.Productions:
        if production.Left == production.Right[0]:
            non_terminal = production.Left
            for prod in non_terminal.productions:
                try:
                    recursive_prod[non_terminal].add(prod)
                except KeyError:
                    recursive_prod[non_terminal] = {prod}

    for non_terminal in recursive_prod.keys():
        new_non_teminal = G.NonTerminals(non_terminal.Name + "'")
        for prod in recursive_prod[non_terminal]:
            new_sentence = Sentence()
            if prod.Right[0] == non_terminal:
                for i in range(1, len(prod.Right)):
                    new_sentence += prod.Right[i]
                new_sentence += new_non_teminal[0]
                new_production = Production(new_non_teminal[0], new_sentence)
                G.Productions.append(new_production)
            else:
                for i in range(len(prod.Right)):
                    new_sentence += prod.Right[i]
                new_sentence += new_non_teminal[0]
                new_production = Production(non_terminal, new_sentence)
                G.Productions.append(new_production)
            G.Productions.remove(prod)
        G.Productions.append(Production(new_non_teminal[0], G.Epsilon))
Example #11
0
def create_new_grammar(G, new_non_terminals, productions):
    if len(productions) == 0:
        return G
    _G = Grammar()
    inst = []
    inst.append(f'{G.startSymbol} = _G.NonTerminal(\'{G.startSymbol}\', True)')
    non_term = [i for i in G.nonTerminals]
    non_term.remove(G.startSymbol)
    non_terminals = non_term + new_non_terminals

    str_non_terminals = [str(nt) for nt in non_terminals]
    str_terminals = [str(t) for t in G.terminals]
    __nt = ' '.join(str_non_terminals)
    _nt = ', '.join(str_non_terminals)
    __t = ' '.join(str_terminals)
    _t = ', '.join(str_terminals)

    if len(str_non_terminals) == 1:
        inst.append(f'{_nt} = _G.NonTerminal(\'{__nt}\')')
    elif len(str_non_terminals) > 1:
        inst.append(f'{_nt} = _G.NonTerminals(\'{__nt}\')')

    inst.append(f'{_t} = _G.Terminals(\'{__t}\')')
    p = [t[1] for t in productions]
    p = '\n'.join(p)
    inst.append(f'{p}')
    for i in inst:
        exec(i)
    return _G
Example #12
0
    def build_grammar(grammar_txt: str):
        """
        Transform a string in this format:

        S --> A B
        A --> a A | epsilon
        B --> b B | epsilon

        to a Grammar object
        """
        try:
            nonTerminals, terminals, P = [], [], []

            lines = [
                l.strip() for l in grammar_txt.splitlines() if l.strip() != ''
            ]

            head = None

            for l in lines:
                if '->' not in l:
                    l = f'{head} -> {l}'

                head, bodies = l.split('->')
                head = head.split()[0]
                nonTerminals.append(head)

                for body in bodies.split('|'):
                    if body.strip() != '':
                        P.append({'Head': head, 'Body': list(body.split())})
                        terminals.extend(P[-1]['Body'])

            set_terminals, set_nonTerminals = set(terminals).difference(
                nonTerminals + ['epsilon']), set(nonTerminals)

            N, T = [], []

            for nt in nonTerminals:
                if nt in set_nonTerminals and set_nonTerminals.discard(
                        nt) == None:
                    N.append(nt)

            for t in terminals:
                if t in set_terminals and set_terminals.discard(t) == None:
                    T.append(t)

            data = json.dumps({
                'Terminals': T,
                'NonTerminals': N,
                'Productions': P
            })
            G = Grammar.from_json(data)
            # print(data)
            G.startSymbol = G.nonTerminals[0]

            return G
        except:
            return None
Example #13
0
def remove_unreachable(G: Grammar):
    """
    Removes unreachable symbols from start symbol
    """
    prods = G.Productions
    reachables = {G.startSymbol.Name}

    # Finding unreachable symbols
    checked = set()
    change = True
    while change:
        change = False
        for i in range(len(prods)):
            if i in checked:
                continue
            if prods[i].Left.Name in reachables:
                right_set = {s.Name for s in prods[i].Right}
                if not right_set.issubset(reachables):
                    reachables = reachables.union(right_set)
                    change = True
                checked.add(i)

    # Removing all productions that have unreachable symbols
    for i in range(len(prods)):
        if prods[i].Left.Name not in reachables \
        or any(s.Name not in reachables for s in prods[i].Right):
            prods[i] = None

    # Replacing old productions by new productions
    G.Productions = []  # Clean grammar productions
    for nt in G.nonTerminals:  # Clean non terminals productions
        nt.productions = []
    for p in prods:  # Add new productions
        if p is not None:
            G.Add_Production(p)
    # Removing unreachable symbols
    symbols = [nt.Name for nt in G.nonTerminals]
    symbols.extend(t.Name for t in G.terminals)
    for s in symbols:
        if s not in reachables:
            try:
                G.nonTerminals.remove(G[s])
            except ValueError:
                G.terminals.remove(G[s])
            G.symbDict.pop(s)
Example #14
0
def remove_ambiguity(G: Grammar):
    """
    Transforms productions of a non terminal for remove ambiguity.
    """
    change = True
    while change:
        change = False
        prods = G.Productions

        for nt in G.nonTerminals:
            p_dict = {}  # pi.Right[0] : {p1, p2, ..., pn}
            for p in nt.productions:
                if p.IsEpsilon:
                    continue
                try:
                    p_dict[p.Right[0].Name].append(p)
                except KeyError:
                    p_dict[p.Right[0].Name] = [p]

            next_appendix = "'"
            for p_set in p_dict.values():
                if len(
                        p_set
                ) > 1:  # Means nt has ambiguous production (all in p_set)
                    new_left = G.NonTerminal(nt.Name + next_appendix)
                    next_appendix = next_appendix + "'"
                    for p in p_set:
                        new_right = p.Right[1:]
                        if len(new_right) == 0:
                            prods.append(Production(new_left, G.Epsilon))
                        else:
                            prods.append(
                                Production(new_left, Sentence(*new_right)))
                        prods.remove(p)
                    prods.append(Production(nt, Sentence(p.Right[0],
                                                         new_left)))
                    change = True

        # Replacing old productions by new productions
        G.Productions = []  # Clean grammar productions
        for nt in G.nonTerminals:  # Clean non terminals productions
            nt.productions = []
        for p in prods:  # Add new productions
            G.Add_Production(p)
Example #15
0
def remove_vars_nothing(G: Grammar):
    """
    Eliminates variables that derive nothing.
    """
    prods = G.Productions

    accepted = {t.Name
                for t in G.terminals
                }  # Symbols that derives in some terminal string

    # Discovering all variables that derives in terminal strings
    change = True
    checked = set()
    while change:
        change = False
        for i in range(len(prods)):  # Iter over productions
            if i in checked:
                continue
            if all(s.Name in accepted for s in prods[i].Right):
                accepted.add(prods[i].Left.Name)
                checked.add(i)
                change = True

    # Removing all productions that have non accepted variables
    variables = [nt.Name for nt in G.nonTerminals]
    for i in range(len(prods)):
        if prods[i].Left.Name not in accepted \
        or any(s.Name in variables and s.Name not in accepted for s in prods[i].Right):
            prods[i] = None

    # Replacing old productions by new productions
    G.Productions = []  # Clean grammar productions
    for nt in G.nonTerminals:  # Clean non terminals productions
        nt.productions = []
    for p in prods:  # Add new productions
        if p is not None:
            G.Add_Production(p)
    # Removing non terminals with no productions
    for v in variables:
        if v not in accepted:
            G.nonTerminals.remove(G[v])
            G.symbDict.pop(v)
Example #16
0
def delete_common_prefix(G: Grammar):
    """
    Algoritmo para eliminar los prefijos comunes de las producciones con la misma cabecera
    Por cada no terminal busca si dos de sus produciones tiene prefijos comunes
    """
    for nonterminal in G.nonTerminals:
        change = True
        primes = ''
        while change:
            change = False
            for production0 in nonterminal.productions:
                _continue = False
                for production1 in nonterminal.productions:
                    if production0 != production1:
                        lpc = 0
                        for i in range((min(len(production0.Right),
                                            len(production1.Right)))):
                            if production0.Right[i] == production1.Right[i]:
                                lpc += 1
                            else:
                                break
                        # En caso de que si tengan prefijos comunes se realiza el siguiente cambio:
                        # E -> aA | aB
                        # Entonces se cambia por :
                        # E -> aE'
                        # E' -> A | B
                        if lpc > 0:
                            primes += '\''
                            temp = G.NonTerminal(f"{nonterminal.Name}{primes}",
                                                 False)
                            nonterminal.productions.remove(production0)
                            nonterminal.productions.remove(production1)
                            G.Productions.remove(production0)
                            G.Productions.remove(production1)
                            nonterminal %= Sentence(*production0.Right[0:lpc] +
                                                    (temp, ))
                            alpha = production0.Right[lpc:]
                            betha = production1.Right[lpc:]
                            if len(alpha) == 0:
                                temp %= G.Epsilon
                            else:
                                temp %= Sentence(*alpha)
                            if len(betha) == 0:
                                temp %= G.Epsilon
                            else:
                                temp %= Sentence(*betha)
                            change = True
                            _continue = True
                            break
                if _continue:
                    continue
    return G
Example #17
0
def remove_left_recursion(G: Grammar):
    """
    Eliminates all left-recursion for any CFG with no e-productions and no cycles.
    """
    def has_lr(nt: NonTerminal) -> bool:
        """
        True if `nt` has left recursion.
        """
        return any(p.Left == p.Right[0] for p in nt.productions)

    prods = [p for p in G.Productions]
    new_prods = []
    for nt in G.nonTerminals:
        if has_lr(nt):
            new_symbol = G.NonTerminal(nt.Name + "'")
            for p in nt.productions:
                if p.Right[0] == p.Left:  # Production has the from A -> Axyz
                    new_right = [s for s in p.Right[1:]]
                    new_right.append(new_symbol)
                    new_prods.append(
                        Production(new_symbol, Sentence(*new_right)))
                else:  # Production has the from A -> xyz
                    new_right = [s for s in p.Right[0:]]
                    new_right.append(new_symbol)
                    new_prods.append(Production(p.Left, Sentence(*new_right)))
            new_prods.append(Production(new_symbol, G.Epsilon))
        else:
            for p in nt.productions:
                new_prods.append(p)

    # Replacing old productions by new productions
    G.Productions = []  # Clean grammar productions
    for nt in G.nonTerminals:  # Clean non terminals productions
        nt.productions = []
    for p in new_prods:  # Add new productions
        G.Add_Production(p)
def fix_left_recursion(grammar:Grammar, errors):
    '''
    Fix immediate left recursion of grammar\n
    return a fixed copy of grammar
    '''
    new_grammar = grammar.copy()
    new_grammar.Productions = []
    
    for n_ter in grammar.nonTerminals:
        for prod in n_ter.productions:
            if not prod.Right.IsEpsilon and prod.Right[0] == prod.Left:
                fix_non_terminal_left_recursion(n_ter,new_grammar, errors)
                break
        else:
            new_grammar.Productions.extend(n_ter.productions)
    
    return new_grammar
def fix_unreachable_symbols(gramm:Grammar):
    gramm = gramm.copy()
    
    pending = [gramm.startSymbol]
    reachable = set(pending)
    while pending:
        symb = pending.pop()
        for prod in symb.productions:
            for r in prod.Right:
                if not r in reachable:
                    reachable.add(r)
                    if isinstance(r,NonTerminal):
                        pending.append(r)
    
    remove_unnecessary_symbols(gramm,[x for x in gramm.nonTerminals + gramm.terminals if x not in reachable])
    
    return gramm  
Example #20
0
def create_productions(G, left, right, new=False, new_symbol=None):
    _G = Grammar()
    left = NonTerminal(left, _G)
    list_symbols = []
    if right == G.Epsilon:
        return Production(left, _G.Epsilon)
    for r in right:
        s = search(G, r)
        if not s:
            s = NonTerminal(r, _G)
        list_symbols.append(s)
    if new:
        s = NonTerminal(new_symbol, _G)
        list_symbols.append(s)
    right = Sentence(list_symbols[0])
    for i in range(1, len(list_symbols)):
        right = right + list_symbols[i]
    return Production(left, right)
Example #21
0
def delete_unreachable_variables(G: Grammar):
    # Para eliminar mas rapido castearemos las listas a set,
    # de esta forma la eliminacion sera O(1)
    G.terminals = set(G.terminals)
    G.nonTerminals = set(G.nonTerminals)
    G.Productions = set(G.Productions)

    # Los elementos que no pueden ser alcanzados por una o mas producciones del caracter inicial
    # No son necesarias pues nunca son utilizadas para generar ningun elemento del lenguaje
    # estos elementos inalcanzables pueden ser tanto terminales como no terminales
    stack = [G.startSymbol]
    reacheable_nonterminals = {G.startSymbol}
    reacheable_terminals = set()

    # Encontramos los terminales y no terminales alcanzables
    while stack:
        current = stack.pop()
        for _, body in current.productions:
            for symbol in body:
                if symbol.IsNonTerminal:
                    if symbol not in reacheable_nonterminals:
                        reacheable_nonterminals.add(symbol)
                        stack.append(symbol)
                else:
                    reacheable_terminals.add(symbol)

    # Eliminamos las producciones con elementos no alcanzables
    G.Productions -= {
        production
        for production in G.Productions
        if production.Left not in reacheable_nonterminals
    }

    # Ahora removemos los no terminales no alcanzables
    G.nonTerminals -= {
        nonterminal
        for nonterminal in G.nonTerminals
        if nonterminal not in reacheable_nonterminals
    }

    # Ahora removemos los terminales no alcanzables
    G.terminals -= {
        terminal
        for terminal in G.terminals if terminal not in reacheable_terminals
    }

    # Finalmente casteamos a lista otra vez
    G.terminals = list(G.terminals)
    G.nonTerminals = list(G.nonTerminals)
    G.Productions = list(G.Productions)
    return G
def fix_common_prefix(grammar:Grammar):
    """
    returns a copy of grammar without common prefixes
    """
    G = grammar.copy()
    G.Productions = []
    
    for non_terminal in grammar.nonTerminals:
        trie = Trie()
        epsilon = False
        for x in non_terminal.productions:
            if not x.Right.IsEpsilon:
                trie.add(x.Right)
            else:
                epsilon = True
        non_terminal.productions = []
        if epsilon:
            G.Add_Production(Production(x.Left,G.Epsilon))
        for node in trie.top.sons:
            execute_node(trie.top.sons[node],non_terminal,[],G,0)
    return G
Example #23
0
    def parseGrammar(self, text: str):
        terminals, nonTerminals, productions = [], [], []

        try:
            lines = text.split('\r\n')

            for line in lines:
                head, bodies = line.split('->')
                head, = head.split()

                if len(head[0]) > 1:
                    raise BadGrammarException()

                nonTerminals.append(head)

                for body in bodies.split('|'):
                    productions.append({
                        'Head': head,
                        'Body': list(body.split())
                    })
                    terminals.extend(productions[-1]['Body'])

        except:
            raise BadGrammarException()

        nonTerminals = set(nonTerminals)
        terminals = set(
            [t for t in terminals if t not in nonTerminals and t != 'epsilon'])

        data = json.dumps({
            'NonTerminals': [nt for nt in nonTerminals],
            'Terminals': [t for t in terminals],
            'Productions': productions
        })

        return Grammar.from_json(data)
def fix_unit_productions(gramm:Grammar):
    """
    returns an equivalent grammar without productions of the form:\n
    A -> B
    """
    gramm = gramm.copy()
    
    unit_productions = {x for x in gramm.Productions if len(x.Right) == 1 and x.Right[0].IsNonTerminal}

    new_productions = set()
    
    for x in gramm.Productions:
        if not x in unit_productions:
            new_productions.add(x)
    
    pending = get_unit_tuples(unit_productions)
    
    while pending:
        l,r = pending.pop()
        for prod in r.productions:
            if not prod in unit_productions:
                new_productions.add(Production(l,prod.Right))
        
    return change_grammar_from_productions(gramm,new_productions)
        items_to_expand = items_to_conflict_way + items_conflict_way
        #print(items_to_expand)

        conflict_string = FindConflictString(items_to_expand)

        if not conflict_string is None:
            text += "Cadena de conflicto:\n"
            for char in conflict_string:
                text += str(char)
            text += "\n"

    return text, automaton, parser


G = Grammar()

A = G.NonTerminal('A', True)
B, C, D = G.NonTerminals('B C D')
a, b, c, d = G.Terminals('a b c d')
"""
S %= E
E %= T | E + plus + T
T %= F | T + mul + F
F %= n | opar + E + cpar
"""
A %= B + d | C + d
B %= b + a
C %= b + a + d

text, automaton, parser = Execute_SLR1(G)
Example #26
0
def define_cool_grammar(print_grammar=False):
    # grammar
    G = Grammar()

    # non-terminals
    program = G.NonTerminal("<program>", startSymbol=True)
    class_list, def_class = G.NonTerminals("<class-list> <def-class>")
    feature_list, def_attr, def_func = G.NonTerminals(
        "<feature-list> <def-attr> <def-func>")
    param_list, param_list_rest, param = G.NonTerminals(
        "<param-list> <param-list-rest> <param>")
    expr, not_exp, comp, arith, term, factor, element, atom = G.NonTerminals(
        "<expr> <not_exp> <comp> <arith> <term> <factor> <element> <atom>")
    identifiers_list, identifier_init = G.NonTerminals(
        "<ident-list> <ident-init>")
    block, case_block, case_item = G.NonTerminals(
        "<block> <case-block> <case-item>")
    func_call, arg_list, arg_list_rest = G.NonTerminals(
        "<func-call> <arg-list> <arg-list-rest>")

    # terminals
    classx, inherits, notx, isvoid = G.Terminals("class inherits not isvoid")
    let, inx = G.Terminals("let in")
    ifx, then, elsex, fi = G.Terminals("if then else fi")
    whilex, loop, pool = G.Terminals("while loop pool")
    case, of, esac = G.Terminals("case of esac")
    semi, colon, comma, dot, opar, cpar, ocur, ccur, at, larrow, rarrow = G.Terminals(
        "; : , . ( ) { } @ <- =>")
    equal, plus, minus, star, div, less, equal, lesseq, neg = G.Terminals(
        "= + - * / < = <= ~")
    idx, type_id, num, new, string, true, false = G.Terminals(
        "id type_id int new string true false")

    # productions
    program %= class_list, lambda h, s: ProgramNode(s[1])

    class_list %= def_class + class_list, lambda h, s: [s[1]] + s[2]
    class_list %= def_class, lambda h, s: [s[1]]

    def_class %= (
        classx + type_id + ocur + feature_list + ccur + semi,
        lambda h, s: ClassDeclarationNode(s[2], s[4], s[1]),
    )
    def_class %= (
        classx + type_id + inherits + type_id + ocur + feature_list + ccur +
        semi,
        lambda h, s: ClassDeclarationNode(s[2], s[6], s[1], s[4]),
    )

    feature_list %= def_attr + semi + feature_list, lambda h, s: [s[1]] + s[3]
    feature_list %= def_func + semi + feature_list, lambda h, s: [s[1]] + s[3]
    feature_list %= G.Epsilon, lambda h, s: []

    def_attr %= (
        idx + colon + type_id + larrow + expr,
        lambda h, s: AttrDeclarationNode(s[1], s[3], s[5], s[4]),
    )
    def_attr %= idx + colon + type_id, lambda h, s: AttrDeclarationNode(
        s[1], s[3], token=s[2])

    def_func %= (
        idx + opar + param_list + cpar + colon + type_id + ocur + expr + ccur,
        lambda h, s: FuncDeclarationNode(s[1], s[3], s[6], s[8], s[2]),
    )

    param_list %= param + param_list_rest, lambda h, s: [s[1]] + s[2]
    param_list %= param, lambda h, s: [s[1]]
    param_list %= G.Epsilon, lambda h, s: []

    param_list_rest %= comma + param + param_list_rest, lambda h, s: [s[2]
                                                                      ] + s[3]
    param_list_rest %= comma + param, lambda h, s: [s[2]]
    param %= idx + colon + type_id, lambda h, s: (s[1], s[3])

    expr %= idx + larrow + expr, lambda h, s: AssignNode(s[1], s[3], s[2])
    expr %= let + identifiers_list + inx + expr, lambda h, s: LetNode(
        s[2], s[4], s[1])
    expr %= notx + comp, lambda h, s: NotNode(s[2], s[1])
    expr %= comp, lambda h, s: s[1]

    identifiers_list %= (
        identifier_init + comma + identifiers_list,
        lambda h, s: [s[1]] + s[3],
    )
    identifiers_list %= identifier_init, lambda h, s: [s[1]]

    identifier_init %= (
        idx + colon + type_id + larrow + expr,
        lambda h, s: VarDeclarationNode(s[1], s[3], s[5]),
    )
    identifier_init %= idx + colon + type_id, lambda h, s: VarDeclarationNode(
        s[1], s[3])

    comp %= arith + less + arith, lambda h, s: LessNode(s[1], s[3], s[2])
    comp %= arith + less + notx + expr, lambda h, s: LessNode(
        s[1], NotNode(s[4], s[3]), s[2])
    comp %= arith + equal + arith, lambda h, s: EqualNode(s[1], s[3], s[2])
    comp %= arith + equal + notx + expr, lambda h, s: EqualNode(
        s[1], NotNode(s[4], s[3]), s[2])
    comp %= arith + lesseq + arith, lambda h, s: LessEqualNode(
        s[1], s[3], s[2])
    comp %= arith + lesseq + notx + expr, lambda h, s: LessEqualNode(
        s[1], NotNode(s[4], s[3]), s[2])
    comp %= arith, lambda h, s: s[1]

    arith %= arith + plus + term, lambda h, s: PlusNode(s[1], s[3], s[2])
    arith %= arith + minus + term, lambda h, s: MinusNode(s[1], s[3], s[2])
    arith %= term, lambda h, s: s[1]

    term %= term + star + factor, lambda h, s: StarNode(s[1], s[3], s[2])
    term %= term + div + factor, lambda h, s: DivNode(s[1], s[3], s[2])
    term %= factor, lambda h, s: s[1]

    factor %= isvoid + element, lambda h, s: IsvoidNode(s[2], s[1])
    factor %= neg + element, lambda h, s: NegNode(s[2], s[1])
    factor %= element, lambda h, s: s[1]

    element %= (
        ifx + expr + then + expr + elsex + expr + fi,
        lambda h, s: IfNode(s[2], s[4], s[6], s[1]),
    )
    element %= whilex + expr + loop + expr + pool, lambda h, s: WhileNode(
        s[2], s[4], s[1])
    element %= case + expr + of + case_block + esac, lambda h, s: CaseNode(
        s[2], s[4], s[1])
    element %= new + type_id, lambda h, s: InstantiateNode(s[2], s[1])
    element %= opar + expr + cpar, lambda h, s: s[2]
    element %= ocur + block + ccur, lambda h, s: BlockNode(s[2], s[1])
    element %= (element + dot + func_call,
                lambda h, s: CallNode(*s[3], obj=s[1], token=s[2]))
    element %= (
        element + at + type_id + dot + func_call,
        lambda h, s: CallNode(*s[5], obj=s[1], at_type=s[3], token=s[2]),
    )
    element %= func_call, lambda h, s: CallNode(*s[1], )
    element %= atom, lambda h, s: s[1]

    case_block %= case_item + case_block, lambda h, s: [s[1]] + s[2]
    case_block %= case_item, lambda h, s: [s[1]]
    case_item %= (
        idx + colon + type_id + rarrow + expr + semi,
        lambda h, s: CaseItemNode(s[1], s[3], s[5], s[4]),
    )

    atom %= num, lambda h, s: ConstantNumNode(s[1])
    atom %= idx, lambda h, s: VariableNode(s[1])
    atom %= (
        true,
        lambda h, s: BooleanNode(s[1]),
    )
    atom %= false, lambda h, s: BooleanNode(s[1])
    atom %= string, lambda h, s: StringNode(s[1])

    block %= expr + semi, lambda h, s: [s[1]]
    block %= expr + semi + block, lambda h, s: [s[1]] + s[3]

    func_call %= idx + opar + arg_list + cpar, lambda h, s: (s[1], s[3])

    arg_list %= expr + arg_list_rest, lambda h, s: [s[1]] + s[2]
    arg_list %= expr, lambda h, s: [s[1]]
    arg_list %= G.Epsilon, lambda h, s: []

    arg_list_rest %= comma + expr + arg_list_rest, lambda h, s: [s[2]] + s[3]
    arg_list_rest %= comma + expr, lambda h, s: [s[2]]

    if print_grammar:
        print(G)
    return (G, idx, type_id, string, num)
Example #27
0
from cmp.ast import *
from utils.macros import *
from cmp.pycompiler import Grammar
from cmp.utils_parser import LR1Parser

CoolGrammar = Grammar()

# non-terminals
program = CoolGrammar.NonTerminal('<program>', startSymbol=True)
class_list, def_class = CoolGrammar.NonTerminals('<class-list> <def-class>')
feature_list, feature = CoolGrammar.NonTerminals('<feature-list> <feature>')
param_list, param = CoolGrammar.NonTerminals('<param-list> <param>')
expr, member_call, expr_list, let_list, case_list = CoolGrammar.NonTerminals(
    '<expr> <member-call> <expr-list> <let-list> <case-list>')
truth_expr, comp_expr = CoolGrammar.NonTerminals('<truth-expr> <comp-expr>')
arith, term, factor, factor_2 = CoolGrammar.NonTerminals(
    '<arith> <term> <factor> <factor-2>')
atom, func_call, arg_list = CoolGrammar.NonTerminals(
    '<atom> <func-call> <arg-list>')

# terminals
classx, inherits = CoolGrammar.Terminals('class inherits')
ifx, then, elsex, fi = CoolGrammar.Terminals('if then else fi')
whilex, loop, pool = CoolGrammar.Terminals('while loop pool')
let, inx = CoolGrammar.Terminals('let in')
case, of, esac = CoolGrammar.Terminals('case of esac')
semi, colon, comma, dot, at, opar, cpar, ocur, ccur, larrow, rarrow = CoolGrammar.Terminals(
    '; : , . @ ( ) { } <- =>')
plus, minus, star, div, isvoid, compl = CoolGrammar.Terminals(
    '+ - * / isvoid ~')
notx, less, leq, equal = CoolGrammar.Terminals('not < <= =')
import first_follow as ff
from cmp.pycompiler import Grammar

G = Grammar()
E = G.NonTerminal('E', True)
T, F, X, Y = G.NonTerminals('T F X Y')
plus, minus, star, div, opar, cpar, num = G.Terminals('+ - * / ( ) num')

E %= T + X
X %= plus + T + X | minus + T + X | G.Epsilon
T %= F + Y
Y %= star + F + Y | div + F + Y | G.Epsilon
F %= num | opar + E + cpar

import cmp.languages

xcool = cmp.languages.BasicXCool(G)

firsts = ff.compute_firsts(G)
assert firsts == xcool.firsts
Example #29
0
            items_conflict_way[0])

        items_to_expand = items_to_conflict_way + items_conflict_way
        print(items_to_expand)

        conflict_string = FindConflictString(items_to_expand)

        if not conflict_string is None:
            text += "Cadena de conflicto:\n"
            for char in conflict_string:
                text += str(char)
            text += "\n"

    return text, automaton, parser


G = Grammar()

S = G.NonTerminal('A', True)
E, T, F = G.NonTerminals('E T F')
plus, opar, cpar, mul, n = G.Terminals('+ ( ) * n')

S %= E
E %= T | E + plus + T
T %= F | T + mul + F
F %= n | opar + E + cpar

text, automaton, parser = Execute_LALR(G)

#automata = Derivation_Tree_ShiftReduce(parser, [a, b, G.EOF])
Example #30
0
rec_izq =  st.sidebar.selectbox('Eliminar recursion izquierda ',('No','Si'))
fact =st.sidebar.selectbox('Eliminar prefijos comunes ',('No','Si'))
non_terminals = st.text_area("Introduzca los no terminales (poniendo de primero al no terminal inicial)", value=non_terminals6)
terminals = st.text_area("Introduzca los terminales", value=terminals6)
grammar = st.text_area("Gramatica", value=grammar6)

cadenas = st.text_area('introduzca(s) cadena(s) a parsear', value=string21)

bt_analize = st.button('Analizar gramatica')


###############################
###  INICIALIZAR VARIABLES  ###
###############################

G = Grammar()


if bt_analize:
    
    for item in get_inst(parser_terminal(terminals), non_terminals.split(), grammar):
        exec(item)

    _parser = ''

    if parser == 'LL(1)':
        _parser = LL1Parser(G)


    elif parser == 'SLR(1)':
        _parser = SLR1Parser(G)