0% found this document useful (0 votes)
6 views

cdlab week 5

The document outlines a program designed to generate an LL(1) parsing table for expression grammar by eliminating left recursion and applying left factoring. It details the computation of FIRST and FOLLOW functions, which are essential for constructing the parsing table, and includes an algorithm and code implementation. The conclusion emphasizes the program's effectiveness in enabling predictive parsing without backtracking, ensuring compatibility with the LL(1) parsing technique.

Uploaded by

yeruvamokshitha
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views

cdlab week 5

The document outlines a program designed to generate an LL(1) parsing table for expression grammar by eliminating left recursion and applying left factoring. It details the computation of FIRST and FOLLOW functions, which are essential for constructing the parsing table, and includes an algorithm and code implementation. The conclusion emphasizes the program's effectiveness in enabling predictive parsing without backtracking, ensuring compatibility with the LL(1) parsing technique.

Uploaded by

yeruvamokshitha
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 5

Roll No:160122733163.. Exp.no:5 Date:17-02-2025………...

1.Aim: Write a program to generate LL(1) parsing table for expression grammar

Description: To generate the LL(1) parsing table, the program follows multiple
preprocessing steps to ensure the grammar is suitable for LL(1) parsing. It first eliminates
left recursion, which is necessary because LL(1) parsers cannot handle left-recursive rules.
Then, it applies left factoring to remove ambiguities caused by common prefixes in
production rules.

After transforming the grammar, the program computes FIRST and FOLLOW functions:

• FIRST function: The set of terminals that can appear at the beginning of any string
derived from a non-terminal.
• FOLLOW function The set of terminals that can appear immediately after a non-
terminal in some valid derivation.

Using these sets, the program constructs the LL(1) parsing table, mapping each (non-
terminal, terminal) pair to a production rule. This table is then printed in a structured
format, making it easier to visualize how an LL(1) parser would process an input string.

By using this parsing table, an LL(1) parser can efficiently analyze an expression by making
single-symbol lookahead decisions, ensuring a deterministic and efficient parsing process.

Algorithm:

• Eliminate Left Recursion: Modify the grammar to remove left-recursive rules.


• Perform Left Factoring: Factor out common prefixes to make the grammar suitable for
LL(1) parsing.
• Extract Terminals and Non-terminals: Identify the symbols in the grammar.
• Compute FIRST function: Determine which terminal symbols can appear at the
beginning of a derivation.
• Compute FOLLOW function: Find the set of terminals that can follow each non-
terminal.
• Initialize the Parsing Table: Create an empty table indexed by non-terminals and
terminals.
• Fill Parsing Table Using FIRST function: Place rules in the table based on FIRST set
values.
• Handle ε Productions Using FOLLOW function: If a production has ε, place it in the
table for FOLLOW symbols.
• Print FIRST and FOLLOW function: Display computed sets for debugging and
verification.
• Display LL(1) Parsing Table: Show the constructed parsing table in tabular format.

Page No. ………………….. Signature of the Faculty………………………...


Roll No:160122733163.. Exp.no:5 Date:17-02-2025………...

Code:
from collections import defaultdict

def eliminate_left_recursion(grammar):
new_grammar = {}
for nt in grammar:
alpha_rules = []
beta_rules = []
for rule in grammar[nt]:
if rule[0] == nt:
alpha_rules.append(rule[1:])
else:
beta_rules.append(rule)

if alpha_rules:
new_nt = nt + "'"
new_grammar[nt] = [beta + [new_nt] for beta in beta_rules]
new_grammar[new_nt] = [alpha + [new_nt] for alpha in alpha_rules] + [['ε']]
else:
new_grammar[nt] = grammar[nt]
return new_grammar

def left_factoring(grammar):
new_grammar = {}
for nt, rules in grammar.items():
prefix_map = defaultdict(list)
for rule in rules:
prefix_map[rule[0]].append(rule)

if all(len(rules) == 1 for rules in prefix_map.values()):


new_grammar[nt] = rules
else:
new_nt = nt + "'"
new_grammar[nt] = [[prefix, new_nt] for prefix in prefix_map if
len(prefix_map[prefix]) > 1] + \
[rule for rule in rules if len(prefix_map[rule[0]]) == 1]
new_grammar[new_nt] = [rule[1:] if len(rule) > 1 else ['ε'] for prefix in prefix_map
for rule in prefix_map[prefix] if len(prefix_map[prefix]) > 1]
return new_grammar

def get_symbols(grammar):
terminals = set()
non_terminals = set(grammar.keys())
for rules in grammar.values():
for rule in rules:
for symbol in rule:
if not symbol.isupper() and symbol != 'ε':
terminals.add(symbol)
terminals.add('$') # End-of-input symbol

Page No. ………………….. Signature of the Faculty………………………...


Roll No:160122733163.. Exp.no:5 Date:17-02-2025………...

return terminals, non_terminals

def compute_first_sets(grammar, terminals, non_terminals):


first = {nt: set() for nt in non_terminals}

def first_of(symbol):
if symbol in terminals:
return {symbol}
if symbol == 'ε':
return {'ε'}
result = set()
for rule in grammar[symbol]:
for s in rule:
sub_first = first_of(s)
result.update(sub_first - {'ε'})
if 'ε' not in sub_first:
break
else:
result.add('ε')
return result

for nt in non_terminals:
first[nt] = first_of(nt)
return first

def compute_follow_sets(grammar, terminals, non_terminals, first_sets):


follow = {nt: set() for nt in non_terminals}
follow[next(iter(grammar))].add('$') # Start symbol

changed = True
while changed:
changed = False
for nt, rules in grammar.items():
for rule in rules:
trailer = follow[nt].copy()
for symbol in reversed(rule):
if symbol in non_terminals:
if trailer - follow[symbol]:
follow[symbol].update(trailer)
changed = True
if 'ε' in first_sets[symbol]:
trailer.update(first_sets[symbol] - {'ε'})
else:
trailer = first_sets[symbol]
else:
trailer = {symbol}
return follow

def construct_parsing_table(grammar, terminals, non_terminals, first_sets, follow_sets):


table = {nt: {t: '' for t in terminals} for nt in non_terminals}
for nt, rules in grammar.items():

Page No. ………………….. Signature of the Faculty………………………...


Roll No:160122733163.. Exp.no:5 Date:17-02-2025………...

for rule in rules:


first_of_rule = set()
for symbol in rule:
first_of_symbol = first_sets[symbol] if symbol in first_sets else {symbol}
first_of_rule.update(first_of_symbol - {'ε'})
if 'ε' not in first_of_symbol:
break
else:
first_of_rule.add('ε')

for terminal in first_of_rule:


if terminal != 'ε':
table[nt][terminal] = rule

if 'ε' in first_of_rule:
for terminal in follow_sets[nt]:
table[nt][terminal] = rule
return table

def print_sets(title, sets):


print(f"\n{title}:")
for key, value in sets.items():
print(f"{key}: {value}")

def print_parsing_table(parsing_table, terminals):


print("\nLL(1) Parsing Table:")
print("\t" + "\t".join(terminals))
for nt, row in parsing_table.items():
print(nt, end="\t")
for t in terminals:
print("".join(row[t]) if row[t] else "-", end="\t")
print()

# Example Grammar
grammar = {
'E': [['T', "E'"], ],
"E'": [['+', 'T', "E'"], ['ε']],
'T': [['F', "T'"], ],
"T'": [['*', 'F', "T'"], ['ε']],
'F': [['(', 'E', ')'], ['id']]
}

grammar = eliminate_left_recursion(grammar)
grammar = left_factoring(grammar)
terminals, non_terminals = get_symbols(grammar)
first_sets = compute_first_sets(grammar, terminals, non_terminals)
follow_sets = compute_follow_sets(grammar, terminals, non_terminals, first_sets)
parsing_table = construct_parsing_table(grammar, terminals, non_terminals, first_sets,
follow_sets)

print_sets("First Function", first_sets)

Page No. ………………….. Signature of the Faculty………………………...


Roll No:160122733163.. Exp.no:5 Date:17-02-2025………...

print_sets("Follow Function", follow_sets)


print_parsing_table(parsing_table, terminals)

Output1 :

Conclusion:
The program successfully constructs an LL(1) parsing table for the given expression grammar
by eliminating left recursion, performing left factoring, and computing FIRST and FOLLOW
sets. This table helps in predictive parsing, enabling top-down parsing without backtracking.
The approach ensures that the grammar is compatible with the LL(1) parsing technique,
making it deterministic and efficient.

Page No. ………………….. Signature of the Faculty………………………...

You might also like