/*
Subklassen:
Expression
Term
Factor
Terminals:
+ Plus
* Mal
( OpenRoundBracket
) ClouseRoundBracket
Terminals:
0000 to 9999
aaaa to zzzz
Jetzt machen wir das so:
Wir rufen jedes Mal, wenn Expression aufgerufen wird, ein neues Objekt, zum Beispiel. Term wiederum kann ein neues Objekt erzeugen Faktor.
Das heißt, wir haben drei Objekte. Die nicht voneinander vererbt sind
expression()
term()
factor()
Und jedes Mal, wenn wir einen Expression() erzeugen, erzeugen wir vielleicht einen Term()
Jeder diese Teile, zum Beispiel in
(5+6)*4
erzeugt ein eigenes Objekt Expression, Term, .... Es ist gleich gesagt, dass das viel Speicher in Anspruch nimmt, aber das ist uns jetzt egal.
Jetzt müssen wir unsere Objekte anschauen, wir haben
Terminale: +, *, (, ), 99, aa
Nichtterminale: Expression, Term, Factor
Es bietet sich, Expression, Term, Factor zwar nicht voneinander zu vererben, aber eine Superklass
NichtTermal zu erstellen.
Genauso wie wir eine Superklasse Terminal haben
Wir müssen bedenken, dass auf Grund unserer Linksrekursion, die Regel
expr ::= expr + term
term ::= term * factor
factor ::= const | id | (expr)
nicht gilt. Sondern wir haben expr2 und term2
Also wir haben 5
expr
expr2
term
term2
factor
Das interessante ist, dass sich unsere Vererbung schon augenscheinlich lohnt. Weil, wir haben eine lexikalische Analyse. Und die lautet gettoken()
Was wir bisher machen können, ist einen Lexer schreiben und wir ein kleines Programm bringen wir den Lexer, beim Parser unter.
Wir haben in C eine alleine stehe Funktion gettoken()
Wenn wir eine Superklasse terminal haben, dann bringen wir darin unter gettoken().
Und die gilt für alle Subklassen.
Jetzt erzeugen wir ein Objekt, von der Klasse Expression. Dann kommt bei
(5+6)*4
Ein Expression. Wir erzeugen als ein Objekt von der Klasse Expression()
Der Term
Wir haben zwei Teile vom Term
(5+6)
und
4
Wir erzeugen zwei Objekte. Dann kommt der Faktor ("").
Und darin der Expresion 5+6.
Das heißt, wir erzeugen so viele Objekte, wie Bestandteile in unserem Ausdruck. Das kann nachher nützlich sein, wenn wir zum Beispiel einen Baum machen.
Jetzt fangen wir an:
Wir verzichten auf id, das heißt, aaa
*/
public class Arithmetic {
static String SourceCode;
static int count = 0;
public static void main (String [] args) {
SourceCode = "(((5+4)*3)";
count = 0;
NumExpr ne = new NumExpr();
}
static public class Terminal {}
static public class Plus extends Terminal {
Plus () {}
boolean isThatTerminal() {
if (SourceCode.length() <= count)
return false;
if(SourceCode.charAt(count) == '+') {
count++;
return true;
}
return false;
}
}
static public class Times extends Terminal {
Times () {}
boolean isThatTerminal() {
if (SourceCode.length() <= count)
return false;
if(SourceCode.charAt(count) == '*') {
count++;
return true;
}
return false;
}
}
static public class OpenRoundBracket extends Terminal {
OpenRoundBracket () {}
boolean isThatTerminal() {
if (SourceCode.length() <= count)
return false;
if(SourceCode.charAt(count) == '(') {
count++;
return true;
}
return false;
}
}
static public class CloseRoundBracket extends Terminal {
CloseRoundBracket () {}
boolean isThatTerminal() {
if (SourceCode.length() <= count)
return false;
if(SourceCode.charAt(count) == ')') {
count++;
return true;
}
return false;
}
}
static public class Const extends Terminal {
String tokenStr;
int val;
Const () {}
int ConstToInt () {
val = 0;
if (SourceCode.length() <= count)
return -1;
if (((SourceCode.charAt (count) >= '0') && (SourceCode.charAt (count) <= '9'))) {
val = SourceCode.charAt (count);
count++;
}
else
return -1;
if (SourceCode.length() <= count)
return val;
while ((SourceCode.charAt (count) >= '0') && (SourceCode.charAt (count) <= '9')) {
count++;
if (SourceCode.length() <= count)
return val;
val *= 10;
val += SourceCode.charAt (count);
}
return val;
}
boolean isThatTerminal () {
val = 0;
int count2 = count;
if (SourceCode.length() <= count) {
return false;
}
if (((SourceCode.charAt (count2) >= '0') && (SourceCode.charAt (count2) <= '9')))
val = SourceCode.charAt (count2);
else {
return false;
}
if (SourceCode.length() <= count2) {
return true;
}
while ((SourceCode.charAt (count2) >= '0') && (SourceCode.charAt (count2) <= '9')) {
count2++;
if (SourceCode.length() <= count2)
return true;
val *= 10;
val += SourceCode.charAt (count2);
}
return true;
}
}
static public class NotTerminal {
NotTerminal() {}
}
static public class NumExpr extends NotTerminal {
NumExpr () {
Term t = new Term();
NumExpr2 e = new NumExpr2();
}
}
static public class NumExpr2 extends NotTerminal {
NumExpr2 () {
Plus p = new Plus();
if (p.isThatTerminal()) {
Term t = new Term();
NumExpr2 e = new NumExpr2();
}
}
}
static public class Term extends NotTerminal {
Term () {
Factor f = new Factor();
Term2 t = new Term2();
}
}
static public class Term2 extends NotTerminal {
Term2 () {
Times tm = new Times();
if (tm.isThatTerminal()) {
Factor f = new Factor();
Term2 t = new Term2();
}
}
}
static public class Factor extends NotTerminal {
Const c = new Const();
OpenRoundBracket o = new OpenRoundBracket();
Factor () {
if (c.isThatTerminal())
c.ConstToInt();
else if (o.isThatTerminal()) {
NumExpr e = new NumExpr();
CloseRoundBracket cl = new CloseRoundBracket();
if (cl.isThatTerminal());
else
System.out.println ("Error");
}
else
System.out.println ("Error");
}
}
}