LEFT RECURSION
LEFT RECURSION
PROCEDURE:
1. Input the number of non-terminals and their productions, storing them
in a map.
2. For each non-terminal, separate left-recursive and non-recursive
productions.
3. Identify left recursion in productions for each non-terminal.
4. Create a new non-terminal (A') to handle left recursion.
5. Modify non-recursive productions to append the new non-terminal.
6. Update left-recursive productions to include the new non-terminal and
epsilon (ε).
7. Print the updated grammar after eliminating left recursion.
PROGRAM:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
public class LeftRecursionElimination {
// Function to eliminate left recursion from the given grammar
public static void eliminateLeftRecursion(Map<String, List<String>>
grammar) {
Map<String, List<String>> newGrammar = new HashMap<>();
for (String nonTerminal : grammar.keySet()) {
List<String> productions = grammar.get(nonTerminal);
List<String> alpha = new ArrayList<>();
List<String> beta = new ArrayList<>();
// Separate alpha (A -> Aα) and beta (A -> β) productions
for (String production : productions) {
if (production.startsWith(nonTerminal)) {
// Left recursive production
alpha.add(production.substring(nonTerminal.length()));
} else {
// Non-left recursive production
beta.add(production);
}
}
if (!alpha.isEmpty()) {
// Create new non-terminal A'
String newNonTerminal = nonTerminal + "'";
// Update the grammar for A -> βA'
List<String> newProductionsForA = new ArrayList<>();
for (String b : beta) {
newProductionsForA.add(b + newNonTerminal);
}
newGrammar.put(nonTerminal, newProductionsForA);
// Update the grammar for A' -> αA' | ε
List<String> newProductionsForNewA = new ArrayList<>();
for (String a : alpha) {
newProductionsForNewA.add(a + newNonTerminal);
}
newProductionsForNewA.add("ε"); // A' -> ε
newGrammar.put(newNonTerminal, newProductionsForNewA);
} else {
// No left recursion, retain original productions
newGrammar.put(nonTerminal, productions);
}
}
// Display the new grammar
System.out.println("Grammar after eliminating left recursion:");
for (String nonTerminal : newGrammar.keySet()) {
System.out.print(nonTerminal + " -> ");
List<String> productions = newGrammar.get(nonTerminal);
for (int i = 0; i < productions.size(); i++) {
if (i > 0) System.out.print(" | ");
System.out.print(productions.get(i));
}
System.out.println();
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Input the grammar
Map<String, List<String>> grammar = new HashMap<>();
System.out.println("Enter the number of non-terminals:");
int numNonTerminals = scanner.nextInt();
scanner.nextLine(); // Consume newline
for (int i = 1; i <= numNonTerminals; i++) {
System.out.println("Enter the non-terminal " + i +" (like A):");
String nonTerminal = scanner.nextLine();
System.out.println("Enter the productions for " + nonTerminal + "
separated by '|':");
String[] productions = scanner.nextLine().split("\\|");
List<String> productionList = new ArrayList<>();
for (String production : productions) {
productionList.add(production.trim());
}
grammar.put(nonTerminal, productionList);
}
// Eliminate left recursion
eliminateLeftRecursion(grammar);
scanner.close();
}
}
OUTPUT: