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
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
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
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
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
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
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"
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))
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
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
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)
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)
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)
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
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
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)
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
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)
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)
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
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])
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)