extend doku
This commit is contained in:
parent
f09e6ad09e
commit
2b45d66ac1
@ -12,8 +12,56 @@ Der Parser wurde mit dem Happy tool implementiert. Er baut aus einer Liste von T
|
|||||||
|
|
||||||
Um den Parser aufzubauen wurde zuerst ein Großteil der Grammatik auskommentiert und Stück für Stück wurden die Umwandlungen hinzugefügt. Immer wenn ein neues Feature umgesetzt wurde, wurde dafür ein weiterer Unit Test geschrieben. Es gibt also für jede komplexe Ableitungsregel mindestens einen Unittest.
|
Um den Parser aufzubauen wurde zuerst ein Großteil der Grammatik auskommentiert und Stück für Stück wurden die Umwandlungen hinzugefügt. Immer wenn ein neues Feature umgesetzt wurde, wurde dafür ein weiterer Unit Test geschrieben. Es gibt also für jede komplexe Ableitungsregel mindestens einen Unittest.
|
||||||
|
|
||||||
Als erstes wurden leere Methoden und Felder umgesetzt. Da in Java Methoden und Felder durcheinander vorkommen können geben die Ableitungsregeln einen Datentype namens `MethodOrFieldDeclaration` zurück. Über Pattern Matching baut die classbodydeclarations Regel dann eine Tupel mit einer Liste aus Methoden und einer aus Feldern. Über pattern matching werden diese Listen dann erweitert und in der darüberliegenden Regel schließlich extrahiert. Die Konstruktoren sind in diesem Fall auch normale Methoden mit dem Rückgabewert `void` und dem Namen `<init>`. Auf diese Weise müssen sie nicht mehr vom Typcheck oder vom Bytecode verändert werden.
|
## Klassenaufbau
|
||||||
|
Als erstes wurden leere Konstruktoren Methoden und Felder umgesetzt. Da in Java Konstruktoren, Methoden und Felder durcheinander vorkommen können geben die Ableitungsregeln einen Datentyp namens `MemberDeclaration` zurück. Die classbodydeclarations Regel baut dann einen 3-Tupel mit einer Liste aus Konstruktoren, einer aus Methoden und einer aus Feldern. Über pattern matching werden diese Listen dann erweitert und in der darüberliegenden Regel schließlich extrahiert.
|
||||||
|
|
||||||
|
Bei folgender Klasse:
|
||||||
|
```java
|
||||||
|
class TestClass {
|
||||||
|
int field;
|
||||||
|
|
||||||
|
TestClass() {}
|
||||||
|
|
||||||
|
void foo() {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
würde die Regel folgendes Tupel zurückgeben:
|
||||||
|
```hs
|
||||||
|
(
|
||||||
|
[ConstructorDeclaration "TestClass" [] (Block [])],
|
||||||
|
[MethodDeclaration "void" "foo" [] (Block [])],
|
||||||
|
[VariableDeclaration "int" "field" Nothing]
|
||||||
|
)
|
||||||
|
```
|
||||||
|
und folgende Klasse wird erstellt
|
||||||
|
```hs
|
||||||
|
Class "TestClass"
|
||||||
|
[ConstructorDeclaration "TestClass" [] (Block [])]
|
||||||
|
[MethodDeclaration "void" "foo" [] (Block [])]
|
||||||
|
[VariableDeclaration "int" "field" Nothing]
|
||||||
|
```
|
||||||
|
Das Nothing ist in diesem Fall ein Platzhalter für eine Zuweisung, da unser Compiler auch Zuweisung bei der Felddeklaration unterstützt.
|
||||||
|
|
||||||
In Java ist es möglich mehrere Variablen in einer Zeile zu deklarieren (Bsp.: `int x, y;`). Beim Parsen ergiebt sich dann die Schwierigkeit, dass man in dem Moment, wo man die Variable parst nicht weiß welchen Datentyp diese hat. Aus diesem Grund gibt es den Datentyp Declarator, welcher nur den Identifier und eventuell eine Zuweisung enthält. In den darüberliegenden Regeln fielddeclaration und localvariabledeclaration wird dann die Typinformation hinzugefügt mithilfe der Funktion convertDeclarator.
|
In Java ist es möglich mehrere Variablen in einer Zeile zu deklarieren (Bsp.: `int x, y;`). Beim Parsen ergiebt sich dann die Schwierigkeit, dass man in dem Moment, wo man die Variable parst nicht weiß welchen Datentyp diese hat. Aus diesem Grund gibt es den Datentyp Declarator, welcher nur den Identifier und eventuell eine Zuweisung enthält. In den darüberliegenden Regeln fielddeclaration und localvariabledeclaration wird dann die Typinformation hinzugefügt mithilfe der Funktion convertDeclarator.
|
||||||
|
|
||||||
Für die Zuweisung wird auch die Kombination mit Rechenoperatoren unterstützt. Das ganze ist als syntactic sugar im Parser umgesetzt. Wenn es einen Zuweisungsoperator gibt, dann wird der Ausdruck in eine Zuweisung und Rechnung aufgeteilt. Bsp.: `x += 3;` wird umgewandelt in `x = x + 3`.
|
## Syntactic Sugar
|
||||||
|
Für die Zuweisung wird auch die Kombination mit Rechenoperatoren unterstützt. Das ganze ist durch Syntactic Sugar im Parser umgesetzt. Wenn es einen Zuweisungsoperator gibt, dann wird der Ausdruck in eine Zuweisung und Rechnung aufgeteilt. Bsp.: `x += 3;` wird umgewandelt in `x = x + 3`.
|
||||||
|
|
||||||
|
For-Schleifen wurde auch rein im Parser durch Syntactic Sugar implementiert. Eine For-Schleife wird dabei in eine While-Schleife umgewandelt. Dafür wird zuerst ein Block erstellt, sodass die deklarierten Variablen auch nur für den Bereich der Schleife gültig sind. Die Bedingung der For-Schleife kann in die While-Schleife übernommen werden. Innerhalb der While-Schleife folgen zuerst die Statements, die im Block der For-Schleife waren und danach die Update-Statements.
|
||||||
|
|
||||||
|
Bsp.:
|
||||||
|
```java
|
||||||
|
for (int i = 0; i < 9; i++) {
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
wird umgewandelt in:
|
||||||
|
```java
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
while (i < 9) {
|
||||||
|
foo();
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
@ -386,7 +386,7 @@ multiplicativeexpression : unaryexpression { $1 }
|
|||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
data MethodOrFieldDeclaration = MethodDecl MethodDeclaration
|
data MemberDeclaration = MethodDecl MethodDeclaration
|
||||||
| ConstructorDecl ConstructorDeclaration
|
| ConstructorDecl ConstructorDeclaration
|
||||||
| FieldDecls [VariableDeclaration]
|
| FieldDecls [VariableDeclaration]
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user