Ja okay, ich glaube ich verstehs langsam.
Nur wie ich den AST so erstelle, dass die Reihenfolge bei zum Beispiel den aritmetischen Operatoren auch stimmt, verstehe ich noch nicht so ganz.
Beispiel:
|
Quellcode
|
1
|
_x = 1-2+3
|
Sollte natürlich 2 ergeben. Ergibt es aber nicht, da bei der Syntax:
|
Quellcode
|
1
2
3
4
5
|
A -> B
B -> C=D
C -> _ Variable
D -> E+E | E-E | E
E -> int Wert
|
Folgender Syntax Baum entsteht:
[Edit] Woops erst vermalt, sollte jetzt passen:
|
Quellcode
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
A
|
B
|
=
/ \
D C
/
E-E
|
-
/ \
E E
/ \
1 E+E
|
+
/ \
E E
/ \
2 3
|
Und dieser bottom-up geparsed wird. Also in Pseudo-Assembler wieder (Ausgabe meiner VM):
|
Quellcode
|
1
2
3
4
5
6
7
8
9
|
val 1
val 2
val 3
add = 5
sub = -4
use 0 # 0 = _x
assign
----------------
-4 # Wert in _x
|
Hmm. Das add und sub müsste getauscht werden, oder der Baum allgemein direkt anders erstellt werden.
Damit ihr nicht immer auf GitHub rumdümpeln müsst, hier mal der Parser Code.
Ich habe extra Kommentare eingefügt damit man nachvollziehen kann was ich mir dabei gedacht habe.
|
C-/C++-Quelltext
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
const std::string& Snippet::get() // aktuelle Token als String
bool Snippet::next() // weiter, wenn Ende der Token erreicht -> false
bool Snippet::accept(const std::string &token) // gibt true wenn der aktuelle Token übereinstimmt
bool Snippet::expect(const std::string &token) // wie accept(), wirft allerdings Fehler und erhöht Token-Zähler
Expression* Snippet::parseExpr(){
auto result = parseAssign(); // aktuell können wir nur das
return result;
}
Expression* Snippet::parseValue(){ // liest Wert in Value Knoten
auto value = new Value();
value->value = get();
next();
return value;
}
Expression* Snippet::parseVariable(){ // liest Namen in Variable Knoten
expect("_");
auto variable = new Variable();
variable->name = get();
next();
return variable;
}
Expression* Snippet::parseAssign(){
auto result = new Assign();
result->right = parseVariable(); // die Variable wird rechts angehangen, damit sie direkt vor dem assign gebunden wird
expect("=");
result->left = parseArith(); // links alles andere (aktuell nur ein aritmetischer Ausdruck)
return result;
}
Expression* Snippet::parseArith(){ // akzeptiert + oder -, gibt ansonsten einen Wert zurück (Value Knoten)
Expression* result = 0;
auto current = currentToken;
next(); // wir müssen "in die Zukunft schauen"
if(accept("+")){
currentToken = current; // und später wieder zurück...
result = new Add();
result->left = parseValue(); // links muss ein Wert stehen
expect("+"); // dann muss der Operator kommen (den wir vorher akzeptiert haben)
result->right = parseArith(); // und jetzt kann ein anderer Ausdruck kommen...
}
else if(accept("-")){
currentToken = current;
result = new Sub();
result->left = parseValue();
expect("-");
result->right = parseArith();
}
else{
currentToken = current;
result = parseValue(); // ich gehe noch davon aus dass es sich somit um einen Wert handeln muss
}
return result;
}
|