This is project for my college and for TLA class
This project is about creating small compiler that checks input and validate it by the grammer that get from user, It also create tree for input that shows how we create and validate the the input, and at the end it says its is valid or no by Lexical and Parse analyis.
- Get input and store grammer
- Create First and Follow
- Create LL1 table
- Create DPDA
- Using Flask
- Show errors and mistakes in input
- Selecting nodes
In this part we get the grammer from user that its format looks like :
START = E
NON_TERMINALS = E , E_prime , T , T_prime , F
TERMINALS = IDENTIFIER , LITERAL , PLUS , STAR , LEFT_PAR , RIGHT_PAR
E -> T E_prime
E_prime -> PLUS T E_prime | eps
T -> F T_prime
T_prime -> STAR F T_prime | eps
F -> LEFT_PAR E RIGHT_PAR | IDENTIFIER | LITERAL
IDENTIFIER -> [a-zA-Z_][a-zA-Z0-9_]*
LITERAL -> \d+(\.\d+)?
PLUS -> \+
STAR -> \*
LEFT_PAR -> \(
RIGHT_PAR -> \)
That includes start-state,non-terminals,terminals,main-grammer and terminals-form that get this data and
store them in Grammer class by extracting each data by using GrammarReader class.
ℹ️ Info
These classes are in grammer folder and in grammer_reader.py file.
in this part we create First and Follow that is necesary for creating LL1 table.
First Step
we compute first by using compute_follow function, the first have form likes :
FIRST(E) = { id, ( }
FIRST(E′) = { +, ε }
FIRST(T) = { id, ( }
FIRST(T′) = { *, ε }
FIRST(F) = { id, ( }
🗺️ How we create it
- Repeat the following until no more changes occur:
- For each grammar production
A → α:
- If
αis a terminal, addαtoFIRST(α).- If
αis a non‑terminalB, addFIRST(B) - {ε}toFIRST(A).- If
αis a sequenceX1 X2 … Xn:
- Add
FIRST(X1) - {ε}toFIRST(A).- If
FIRST(X1)containsε, move on toX2, thenX3, …- If all
Xican generateε, addεtoFIRST(A).
Second Step
we compue follow by using compute_follow function, the follow have form likes :
FOLLOW(E) = { $, ) }
FOLLOW(E′) = { $, ) }
FOLLOW(T) = { +, $, ) }
FOLLOW(T′) = { +, $, ) }
FOLLOW(F) = { *, +, $, ) }
🗺️ How we create it
- Repeat the following until no more changes occur:
- Initialize:
- Add
$(end of input) toFOLLOW(Start Symbol).- For each production
A → αBβ:
- Add
FIRST(β) - {ε}toFOLLOW(B).- If
βis ε orFIRST(β)containsε, addFOLLOW(A)toFOLLOW(B).
ℹ️ Info
These classes are in first_follow folder and in first_follow.py file.
after creating First and follow then by looking the data that we extract from first and follow functions we create LL1 table, that we looks likes :
🗺️ How we create it
- Initialize:
- an empty table
M.- For each nonterminal
Aand each of its productionsα:
- If α is the epsilon production:
- For every terminal
bin FOLLOW(A), setM[A, b] = α.- Else (α ≠ ε) :
- Compute FIRST(α):
- Scan the symbols of
αleft‑to‑right, unioning their FIRST sets (excluding ε) until you hit one that doesn’t deriveε.- If all symbols can derive
ε, includeεin FIRST(α).- For each terminal
ain FIRST(α) − {ε}, setM[A, a] = α.- If ε ∈ FIRST(α), then for every terminal
bin FOLLOW(A), setM[A, b] = α.- Return the filled table
M.
ℹ️ Info
These classes are in table folder and in ll1_table.py file.
1.First Step : Create Transitions
after creating LL1 Table we create class DPDA that store transition and use create_transitions function that returns dictionary of transitions.
🗺️ How we create transitions
- Check if the pair
(non_terminal, terminal)exists in the LL(1) parsing table.- If an entry exists, retrieve its right‑hand side production as a list of symbols.
- Reverse that list before pushing onto the stack:
- We reverse so that the leftmost symbol ends up on top.
- Example: for
E → T E', the production list is[T, E'].
- Without reversing, pushing in order would put
Tat the bottom andE'on top.- By reversing to
[E', T], we pushE'first, thenT, soTis on top.
2.Second Step : Create Token From Input
then after creating transition we use create_token that create token from the input that user gives to validate it.
✂️ Purpose
Split an input string into tokens based on a user‑provided regular expression.
3.Third Step : Validate And Create Parse Tree
after tokenize the input we use check_and_create_graph that validate and create graph.
🛡️ Purpose
Validate a tokenized input sequence against an LL(1) parsing table, drive the parsing stack, and build the corresponding parse graph.
for using NetworkX and Pyvis we needed to run it on html so we decided use Flask to get more feature beside run on browser , like :
- clicking and selecting
- showing problems
we could use Graphviz too but the output was png and pdf and we wanted on html so we didn't use it and use the Networkx and Pyvis library that the output looks
more beautiful in them :)
🔗 Graph Visualization Notebook
We built and rendered our Parse graph using this Colab workflow:
📝 Open “Parse Graph Builder” on Colab
A big thank‑you to Ilya jahed that helped me to create this project :
| Contributor | Contribution | Profile |
|---|---|---|
| Ilya Jahed | Designed the LL(1) parsing algorithm Generated grammar from user input |
GitHub › Ilyajahed |