2021-11-28 23:08:27 +01:00
|
|
|
# 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
|
2021-11-29 22:47:39 +01:00
|
|
|
A -> M + A | M - A | M
|
|
|
|
M -> G * M | G / M | G
|
|
|
|
G -> P ^ G | P
|
2021-11-28 23:08:27 +01:00
|
|
|
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;
|
2021-11-29 22:47:39 +01:00
|
|
|
a1("[A->.M+A] | [A->.M-A] | [A->.M]")
|
|
|
|
a3(["[A->M.+A] | [A->M.-A] | [A->M.]"])
|
|
|
|
a4("[A->M+.A]")
|
|
|
|
a5(["[A->M+A.]"])
|
|
|
|
a6("[A->M-.A]")
|
|
|
|
a7(["[A->M-A.]"])
|
|
|
|
|
|
|
|
a1 -- M --> a3
|
2021-11-28 23:08:27 +01:00
|
|
|
a3 -- + --> a4
|
|
|
|
a4 -- A --> a5
|
|
|
|
a3 -- - --> a6
|
|
|
|
a6 -- A --> a7
|
|
|
|
```
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
graph LR;
|
2021-11-29 22:47:39 +01:00
|
|
|
m1("[M->.G*M] | [M->.G/M] | [M->.G]")
|
|
|
|
m3(["[M->G.*M] | [M->G./M] | [M->G.]"])
|
|
|
|
m4("[M->G*.M]")
|
|
|
|
m5(["[M->G*M.]"])
|
|
|
|
m6("[M->G/.M]")
|
|
|
|
m7(["[M->G/M.]"])
|
|
|
|
|
|
|
|
m1 -- G --> m3
|
2021-11-28 23:08:27 +01:00
|
|
|
m3 -- * --> m4
|
|
|
|
m4 -- M --> m5
|
|
|
|
m3 -- / --> m6
|
|
|
|
m6 -- M --> m7
|
|
|
|
```
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
graph LR;
|
2021-11-29 22:47:39 +01:00
|
|
|
g1("[G->.P^G] | [G->.P]")
|
|
|
|
g5(["[G->P.^G] | [G->P.]"])
|
2021-11-28 23:08:27 +01:00
|
|
|
g6("[G->P^.G]")
|
|
|
|
g7(["[G->P^G.]"])
|
|
|
|
|
|
|
|
g1 -- P --> g5
|
|
|
|
g5 -- ^ --> g6
|
|
|
|
g6 -- G --> g7
|
|
|
|
```
|
|
|
|
|
|
|
|
```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
|
|
|
|
```
|