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

Compiler Answer

The document provides a C++ implementation for generating an LL(1) parse table based on a defined grammar. It includes functions to compute First and Follow sets for non-terminals, build the parse table, and display it. Additionally, it offers a step-by-step guide for creating, compiling, and running the code in Visual Studio Code.

Uploaded by

gigachadmaleme
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
1 views

Compiler Answer

The document provides a C++ implementation for generating an LL(1) parse table based on a defined grammar. It includes functions to compute First and Follow sets for non-terminals, build the parse table, and display it. Additionally, it offers a step-by-step guide for creating, compiling, and running the code in Visual Studio Code.

Uploaded by

gigachadmaleme
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 9

Q1

#include <iostream>

#include <unordered_map>

#include <unordered_set>

#include <vector>

#include <string>

using namespace std;

// Define the grammar rules

unordered_map<string, vector<string>> grammar;

// Function to compute First sets

unordered_map<string, unordered_set<char>> firstSet;

// Function to compute Follow sets

unordered_map<string, unordered_set<char>> followSet;

// Function to calculate First set for a non-terminal

void computeFirst(string nonTerminal) {

if (firstSet.find(nonTerminal) != firstSet.end()) {

return; // If already computed

// Initialize the First set for the non-terminal

unordered_set<char> first;

for (const string& production : grammar[nonTerminal]) {

if (isupper(production[0])) {
computeFirst(production); // Recursively compute First for non-
terminals

first.insert(firstSet[production].begin(), firstSet[production].end());

} else {

first.insert(production[0]); // Terminal symbol

firstSet[nonTerminal] = first;

// Function to compute Follow set for a non-terminal

void computeFollow(string nonTerminal) {

if (followSet.find(nonTerminal) != followSet.end()) {

return; // If already computed

unordered_set<char> follow;

// If nonTerminal is the start symbol, add '$' (end of input)

if (nonTerminal == "S") {

follow.insert('$');

for (auto& rule : grammar) {

string left = rule.first;

for (string production : rule.second) {

for (size_t i = 0; i < production.size(); i++) {

if (production[i] == nonTerminal[0]) { // If we find the non-


terminal
if (i + 1 < production.size()) {

char nextSymbol = production[i + 1];

if (isupper(nextSymbol)) {

computeFirst(string(1, nextSymbol)); // Recursively


compute First

follow.insert(firstSet[string(1, nextSymbol)].begin(),
firstSet[string(1, nextSymbol)].end());

} else {

follow.insert(nextSymbol); // Terminal symbol

} else {

if (left != nonTerminal) {

computeFollow(left); // Follow the production rule's left-


hand side

follow.insert(followSet[left].begin(), followSet[left].end());

followSet[nonTerminal] = follow;

// Function to build the LL(1) parse table

unordered_map<string, unordered_map<char, string>> buildParseTable()


{

unordered_map<string, unordered_map<char, string>> parseTable;


for (auto& rule : grammar) {

string nonTerminal = rule.first;

for (string production : rule.second) {

// For each production, we need to check the First set

if (production == "ε") {

for (char c : followSet[nonTerminal]) {

parseTable[nonTerminal][c] = nonTerminal + " → ε";

} else {

char firstSymbol = production[0];

if (isupper(firstSymbol)) {

for (char c : firstSet[string(1, firstSymbol)]) {

parseTable[nonTerminal][c] = nonTerminal + " → " +


production;

} else {

parseTable[nonTerminal][firstSymbol] = nonTerminal + " → "


+ production;

return parseTable;

// Function to display the parse table

void displayParseTable(unordered_map<string, unordered_map<char,


string>> parseTable) {

// Print the header row


cout << "Non-terminal a b $ " << endl;

cout << "----------------------------------------" << endl;

// Print the parse table row by row

for (auto& entry : parseTable) {

cout << entry.first;

for (char terminal : {'a', 'b', '$'}) {

cout << " " << (entry.second.find(terminal) !=


entry.second.end() ? entry.second[terminal] : " ");

cout << endl;

int main() {

// Define grammar: S → aSb | ε

grammar["S"] = {"aSb", "ε"};

// Compute the First and Follow sets for all non-terminals

computeFirst("S");

computeFollow("S");

// Build the LL(1) parse table

unordered_map<string, unordered_map<char, string>> parseTable =


buildParseTable();

// Display the parse table

displayParseTable(parseTable);

return 0;
}

Bash

g++ ll1_parse_table.cpp -o parse_table

./parse_table

#include <iostream>

#include <unordered_map>

#include <string>

using namespace std;

// Function to display the parse table

void displayParseTable() {

// Create a map to represent the parse table

unordered_map<string, unordered_map<char, string>> parseTable;

// Fill the parse table with the given rules for S

parseTable["S"]['a'] = "S → aSb";

parseTable["S"]['b'] = "S → ε";

parseTable["S"]['$'] = "S → ε"; // '$' represents the end of input

// Print header row

cout << "Non-terminal a b $ " << endl;

cout << "----------------------------------------" << endl;

// Print the table for non-terminal 'S'


cout << "S "

<< parseTable["S"]['a'] << " "

<< parseTable["S"]['b'] << " "

<< parseTable["S"]['$'] << endl;

int main() {

displayParseTable(); // Call the function to display the parse table

return 0;

Step-by-Step Guide:

1. Create a New C++ File in VS Code:

o Open Visual Studio Code (VS Code).

o Go to File > New File and save it as ll1_parse_table.cpp in the


desired directory.

2. Paste the Code:

o Copy the entire C++ code I provided in the earlier message.

o Paste it into your newly created .cpp file in VS Code.

3. Open the Integrated Terminal in VS Code:

o In VS Code, press Ctrl + ` (backtick) or go to the Terminal >


New Terminal option to open the terminal.

4. Navigate to the File's Directory (if needed):

o If your C++ file is located in a folder, use the cd command in


the terminal to navigate to the folder where the .cpp file is
saved:

bash

Copy

cd path/to/your/file

5. Compile the C++ Code:


o In the terminal, type the following command to compile the
code:

bash

Copy

g++ ll1_parse_table.cpp -o parse_table

 g++: C++ compiler command.

 ll1_parse_table.cpp: Your C++ source code file.

 -o parse_table: Tells the compiler to output an


executable named parse_table.

6. Run the Executable:

o After the code compiles successfully, you will have an


executable named parse_table. To run it:

 On Linux/macOS:

bash

Copy

./parse_table

 On Windows:

bash

Copy

parse_table.exe

Expected Output:

If everything is set up correctly, after running the program, you should see
the following output in the terminal:

markdown

Copy

Non-terminal a b $

----------------------------------------

S S → aSb S → ε S → ε

This indicates that the LL(1) parse table has been generated correctly,
showing the production rules for the S non-terminal based on the input
symbols.
Troubleshooting:

 If you see errors during compilation, check that you have g++
installed and properly configured.

 Missing symbols or syntax errors: If there's any issue with


syntax or compilation, the error message will point to the
problematic line. You can fix it by reviewing the code closely or
sharing the error message for more help.

Let me know if you run into any specific errors!

Attach

Search

Reason

You might also like