# Grammar The grammar for the calculator. It is segmented into two parts: 1. **Regular Grammar** for the Lexer 2. **Context-free Grammar** for the Parser ## Lexer Grammar ```regexp ID: \d+ OBR: ( CBR: ) OP: \*|/|^|-|\+ ``` ### Lexer DFA ```mermaid graph LR; init["s0"] -- "(" --> f0((f0)) init -- ")" --> f1((f1)) init -- "\d" --> f2((f2)) f2 -- "\d" --> f2 init -- "*, /, ^, -, +" --> f3((f3)) init -- "[ ]" --> init init -- "otherwise" --> error[[error]] ``` ## Parser Grammar ``` S -> A A -> A + A | A - A | M M -> M * M | M / M | G G -> ( A ) | P ^ G | ID P -> ( A ) | ID ``` Die Grammatik ist eindeutig und nicht linksrekursiv. Außerdem hat sie eine weitere interessante Eigenschaft: Wenn die Grammatik mehrere Potenzen parsed, expandieren diese nach rechts. Beispiel: ``` S A M G P ^ G ID ^ G ID ^ P ^ G ID ^ ID ^ G ID ^ ID ^ P ^ G ID ^ ID ^ ID ^ ID 5 ^ 4 ^ 3 ^ 2 ``` Dabei sieht der Syntax Tree so aus: ``` S | A | M | G | \ P G | | \ 5 P G | | \ 4 P G | | 3 P | 2 ``` Wenn also per Recursive Descent immer zuerst das "tiefste" Ergebnis ausgewertet wird, heißt 5^4^3^2 5^(4^(3^(2))), ohne weitere Berechnungen auszuführen. ```mermaid graph LR; s1("[S->.A]") --> s2(["[S->A.]"]) ``` ```mermaid graph LR; a1("[A->.A+A] | [A->.A-A] | [A->.M]") a2(["[A->M.]"]) a3("[A->A.+A] | [A->A.-A]") a4("[A->A+.A]") a5(["[A->A+A.]"]) a6("[A->A-.A]") a7(["[A->A-A.]"]) a1 -- M --> a2 a1 -- A --> a3 a3 -- + --> a4 a4 -- A --> a5 a3 -- - --> a6 a6 -- A --> a7 ``` ```mermaid graph LR; m1("[M->.M*M] | [M->.M/M] | [M->.G]") m2(["[M->G.]"]) m3("[M->M.*M] | [M->M./M]") m4("[M->M*.M]") m5(["[M->M*M.]"]) m6("[M->M/.M]") m7(["[M->M/M.]"]) m1 -- G --> m2 m1 -- M --> m3 m3 -- * --> m4 m4 -- M --> m5 m3 -- / --> m6 m6 -- M --> m7 ``` ```mermaid graph LR; g1("[G->.(A)] | [G->.P^G] | [G->.ID]") g2("[G->(.A)]") g3("[G->(A.)]") g4(["[G->(A).]"]) g5("[G->P.^G]") g6("[G->P^.G]") g7(["[G->P^G.]"]) g8(["[G->ID.]"]) g1 -- "(" --> g2 g2 -- A --> g3 g3 -- ")" --> g4 g1 -- P --> g5 g5 -- ^ --> g6 g6 -- G --> g7 g1 -- ID --> g8 ``` ```mermaid graph LR; p1("[P->.(A)] | [G->.ID]") p2("[P->(.A)]") p3("[P->(A.)]") p4(["[P->(A).]"]) p5(["[P->ID.]"]) p1 -- "(" --> p2 p2 -- A --> p3 p3 -- ")" --> p4 p1 -- ID --> p5 ```