Name: Sakshi Shashikant Yeole2
Roll No.: 20CS01047
Semester: 7th
Year of study: 4th year
Subject: Compiler Design Laboratory
Assignment: Assignment - 5
- Clone the repository: https://github.com/SakshiYeole/Predictive_Parser.git
- Open in your favourite editor. (The editor used while making this project is VS Code and also the path are currently coded to handle only windows)
- Run the complete project by running the Grammar.py. Follow the prompt to give input.
For each of the grammars, perform the following steps and implement a predictive LL(1) parser.
-
Transform the given grammar to LL(1).
Details:
Transform the grammar to LL(1) (without affecting/changing the language) by removal of left-recursion, and finding an equivalent left-factored Grammar. Write a LL(1) grammar in an output file.
-
Compute First and Follow Set.
Details:
For the LL(1) grammar obtained from step1, compute the FIRST set of all symbols and the FOLLOW set of all the non-terminalsymbols. Store this information in a separate file.
-
Compute the parse table.
Details:
Create a parsing table for the LL(1) using FIRST and FOLLOW set.
-
Take a string input and parse it using the parse table computed in step3.
-
First line contains the start symbol.
-
Second line contains all the Non-terminal symbols in space separated manner.
-
Next Line contains all the Terminal symbols in space separated manner.
-
Next line till the end of file ontains production rules in format:
P -> prog DL SL end | if else then
The left hand side and right side separated by ->. The right hand side rules separated by '|'. And for each rule, the symbols also be space separated
Example input grammar
P
AE BE D DL E F ES IOS IS NE P PE RE S SL T TY VL WS
+ - * / = < > ( ) { } := ; and else end ic id if int do fc float not or print prog scan str then while
P -> prog DL SL end
DL -> D DL | ε
D -> TY VL ;
TY -> int | float
VL -> id VL | id
SL -> S SL | ε
S -> ES | IS | WS | IOS
ES -> id := E ;
IS -> if BE then SL end | if BE then SL else SL end
WS -> while BE do SL end
IOS -> print PE | scan id
PE -> E | str
BE -> BE or AE | AE
AE -> AE and NE | NE
NE -> not NE | { BE } | RE
RE -> E = E | E < E | E > E
E -> E + T | E - T | T
T -> T * F | T / F | F
F -> ( E ) | id | ic | fc
NOTE: The input grammar should be written here and the input text here.
The project consists of many folders, lets walk through one after another.
-
Flex directory:
The flex directory consists of all the files related to flex. Currently, there are two subdirectories, Grammar1 and Grammar2. In each of this directory, there is a file with ".l" extension. This is the lex file, which will be used for lexical analysis.
-
Input directory:
This is the directory for input text file from which all the input is read. The files in this directory is, InputText.txt and InputGrammar.txt.
-
Output directory: (will be created on the go)
This directory contains the output files, namely "FirstFollowSet.txt", "EquivalentLeftFactoredandRemovingLeftRecursionGrammar.txt", "InputGrammar.txt", "ParsingSteps.txt", and "ParsingTable.txt". The names are quite self explanatory.
-
Grammar.py file:
This file contains all the source code.
Check the Grammar.py file to understand the flow. Following are the steps:
- Create empty output directory.
- Take in the grammar choice which needs to be run, currently there are two grammar choices 1 and 2.
- Read the text from InputText.txt and feed it the lex program.
- Compile and run the flex program.
- Take the input grammar from "InputGrammar.txt".
- Print the input grammar to output file.
- Transform the input grammar into LL(1) grammar by applying algorithm for producing an equivalent left factored grammar and removal of left recursion. Print the grammar to output file.
- Compute the first and follow set, and print it to output file.
- Read the list of tokens from flex program output file.
- Create a parsing table for LL(1) grammar, and print it to output file.
- Feed the tokens to parser, which parses using parsing table.
- Write the steps of parser to output file.
- Print corresponding output whether the input text is accepted by the grammar or not.
For more details check the pdf: "Question.pdf"
- As the above written steps can be done in parallel manner, we can find a dependency graph for the above steps, and apply threading.
- Currently, the program does not check if the grammar is LL(1) or not. (This can be done by checking if their exists more than one production rule in a cell of parsing table.)
- Also, the program does not check for error in lexical analysis explicitly. It will print error while parsing, but we can analyse the tokens and comment on lexical analysis.
- The lex program is now hardcoded explicitly, we can write a program which can create a "lex.l" , and then use it for lexical analysis.