New paste Repaste Download
def compute_first(productions):
    first = {nt: set() for nt in productions}
    def first_string(s):
        r = set()
        if s == "": r.add('ε'); return r
        for symbol in s:
            if not symbol.isupper():
                r.add(symbol); break
            else:
                r |= (first[symbol] - {'ε'})
                if 'ε' not in first[symbol]: break
        else: r.add('ε')
        return r
    changed = True
    while changed:
        changed = False
        for nt, prods in productions.items():
            for prod in prods:
                temp = set()
                if prod == 'ε' or prod == '': temp.add('ε')
                else:
                    for symbol in prod:
                        if not symbol.isupper():
                            temp.add(symbol); break
                        else:
                            temp |= (first[symbol] - {'ε'})
                            if 'ε' not in first[symbol]: break
                    else: temp.add('ε')
                before = len(first[nt])
                first[nt] |= temp
                if len(first[nt]) != before: changed = True
    return first
def compute_follow(productions, first, start_symbol):
    follow = {nt: set() for nt in productions}
    follow[start_symbol].add('$')
    changed = True
    while changed:
        changed = False
        for nt, prods in productions.items():
            for prod in prods:
                for i, symbol in enumerate(prod):
                    if symbol.isupper():
                        beta = prod[i+1:]
                        first_beta = set()
                        if beta == "": first_beta.add('ε')
                        else:
                            for s in beta:
                                if not s.isupper():
                                    first_beta.add(s); break
                                else:
                                    first_beta |= (first[s] - {'ε'})
                                    if 'ε' not in first[s]: break
                            else: first_beta.add('ε')
                        before = len(follow[symbol])
                        follow[symbol] |= (first_beta - {'ε'})
                        if 'ε' in first_beta: follow[symbol] |= follow[nt]
                        if len(follow[symbol]) != before: changed = True
    return follow
def build_parsing_table(productions, first, follow, nts_order, terms_order):
    table = {nt: {t: None for t in terms_order} for nt in productions}
    for nt, prods in productions.items():
        for prod in prods:
            first_prod = set()
            if prod == 'ε' or prod == '': first_prod.add('ε')
            else:
                for symbol in prod:
                    if not symbol.isupper():
                        first_prod.add(symbol); break
                    else:
                        first_prod |= (first[symbol] - {'ε'})
                        if 'ε' not in first[symbol]: break
                else: first_prod.add('ε')
            for t in (first_prod - {'ε'}):
                table[nt][t] = f"{nt}->{prod}"
            if 'ε' in first_prod:
                for t in follow[nt]:
                    table[nt][t] = f"{nt}->{prod}"
    return table
def simulate_parsing(inp, start, table):
    stack = [start, '$']; ip = 0; actions = []
    while True:
        curr_stack = "".join(stack)
        curr_inp = inp[ip:]
        top = stack[0]
        if not top.isupper():
            if top == inp[ip]:
                actions.append((curr_stack, curr_inp, "POP ACTION"))
                stack.pop(0); ip += 1
            else:
                actions.append((curr_stack, curr_inp, f"Error: expected '{top}'"))
                return actions, False
        else:
            curr_sym = inp[ip] if ip < len(inp) else '$'
            rule = table[top].get(curr_sym)
            if rule is None:
                actions.append((curr_stack, curr_inp, f"Error: no rule for {top} on '{curr_sym}'"))
                return actions, False
            else:
                actions.append((curr_stack, curr_inp, rule))
                stack.pop(0)
                prod = rule.split("->")[1]
                if prod != 'ε' and prod != '':
                    for symbol in prod[::-1]:
                        stack.insert(0, symbol)
        if stack == ['$'] and inp[ip:] == '$':
            actions.append(("$", "$", "POP ACTION"))
            stack.pop(0); ip += 1; break
    return (actions, True) if ip == len(inp) else (actions, False)
def print_parsing_table(table, nts_order, terms_order):
    print("\n\t\t\t\t\t\t\t The LL(1) Parsing Table for the above grammer :-")
    print("\t\t\t\t\t\t\t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n")
    sep = "  " + "=" * 101
    print("\t\t\t" + sep)
    print("\t\t\t\t|\t" + "\t\t".join(terms_order))
    print("\t\t\t" + sep.replace("=", "-"))
    for nt in nts_order:
        row = f"\t\t\t   {nt}\t|\t" + "\t\t".join(table[nt].get(t) or "" for t in terms_order)
        print(row)
        print("\t\t\t" + sep.replace("=", "-"))
def print_parsing_steps(actions):
    print("\n\t\t\t\t\t===========================================================================\n")
    print("\t\t\t\t\t\tStack\t\t\tInput\t\t\tAction")
    print("\t\t\t\t\t===========================================================================\n")
    for s, i, a in actions:
        print(f"\t\t\t\t\t\t{''.join(reversed(s)):<24}{i:<24}{a}")
    print("\n\t\t\t\t\t===========================================================================\n")
def main():
    count = int(input("How many productions? : "))
    print(f"\nEnter {count} productions in form A->B where A and B are grammar symbols:")
    productions, order = {}, []
    for _ in range(count):
        prod_str = input().strip()
        if '->' not in prod_str:
            print("Incorrect production format. Expected A->B."); return
        left, right = map(str.strip, prod_str.split('->', 1))
        if left == "":
            print("Nonterminal missing in production."); return
        if left not in productions:
            productions[left] = []; order.append(left)
        productions[left].append(right)
    start = order[0]
    first = compute_first(productions)
    follow = compute_follow(productions, first, start)
    print("\nFirst sets:")
    for nt in order:
        print(f"First({nt}) = {{ {', '.join(sorted(first[nt]))} }}")
    print("\nFollow sets:")
    for nt in order:
        print(f"Follow({nt}) = {{ {', '.join(sorted(follow[nt]))} }}")
    terms_order = ['+', '*', '(', ')', 'i', '$']
    table = build_parsing_table(productions, first, follow, order, terms_order)
    print_parsing_table(table, order, terms_order)
    inp = input("\nPlease enter the desired INPUT STRING = ").strip()
    if inp[-1] != '$': inp += '$'
    actions, accepted = simulate_parsing(inp, start, table)
    print_parsing_steps(actions)
    print("\n\t\t\t" + "=" * 90)
    print("\t\t\t\t\t\t\t\tYOUR STRING HAS BEEN ACCEPTED !!" if accepted else "\t\t\t\t\t\t\t\tYOUR STRING HAS BEEN REJECTED !!")
    print("\t\t\t" + "=" * 90)
if __name__ == "__main__":
    main()
Filename: None. Size: 7kb. View raw, , hex, or download this file.

This paste expires on 2025-04-17 13:22:11.754721. Pasted through web.