[09/10 - LL(I) AST] Add old implementation of "ÜB-Praxis-AST für X" and LL(I) grammar of modifier
This commit is contained in:
@@ -1,25 +1,477 @@
|
|||||||
/* **********************************************
|
|
||||||
* Duale Hochschule Baden-Württemberg Karlsruhe
|
|
||||||
* Prof. Dr. Jörn Eisenbiegler
|
|
||||||
*
|
|
||||||
* Vorlesung Übersetzerbau
|
|
||||||
* Praxis LL(1)-Parser für X
|
|
||||||
* - LL1-Parser
|
|
||||||
*
|
|
||||||
* **********************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.dhbw.compiler.xparser;
|
package de.dhbw.compiler.xparser;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public class XParser {
|
public class XParser {
|
||||||
|
|
||||||
public XParser(TokenBuffer in) {
|
private final TokenBuffer in;
|
||||||
//TODO Initialization
|
private long comparecount = 0;
|
||||||
}
|
|
||||||
|
|
||||||
public Tree parseProgram() {
|
private final Set<Integer> PlusMinus;
|
||||||
//TODO Parser
|
private final Set<Integer> MultDiv;
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
public XParser(TokenBuffer in) {
|
||||||
|
this.in = in;
|
||||||
|
PlusMinus = new HashSet<>();
|
||||||
|
PlusMinus.add(Token.PLUS);
|
||||||
|
PlusMinus.add(Token.MINUS);
|
||||||
|
MultDiv = new HashSet<>();
|
||||||
|
MultDiv.add(Token.MULT);
|
||||||
|
MultDiv.add(Token.DIV);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getComparecount() {
|
||||||
|
return comparecount;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Tree addLeftAssoziativ(Tree left, Tree op, Tree right, Set<Integer> samePrio) {
|
||||||
|
if (right.getChildren()
|
||||||
|
.isEmpty() || !samePrio.contains(right.getToken()
|
||||||
|
.getType())) {
|
||||||
|
op.addFirstChild(left);
|
||||||
|
op.addLastChild(right);
|
||||||
|
return op;
|
||||||
|
} else {
|
||||||
|
Tree leftop = right;
|
||||||
|
while (samePrio.contains(leftop.getChild(0)
|
||||||
|
.getToken()
|
||||||
|
.getType())) {
|
||||||
|
leftop = leftop.getChild(0);
|
||||||
|
}
|
||||||
|
Tree leftright = leftop.getChild(0);
|
||||||
|
leftop.removeChild(0);
|
||||||
|
op.addLastChild(leftright);
|
||||||
|
op.addFirstChild(left);
|
||||||
|
leftop.addFirstChild(op);
|
||||||
|
return right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tree parseToken(int type) {
|
||||||
|
comparecount++;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Token token = in.nextToken();
|
||||||
|
|
||||||
|
if (token.getType() == type) {
|
||||||
|
return new Tree(token);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------- *
|
||||||
|
*
|
||||||
|
* modifier ::= read modifier2 | print | eps.
|
||||||
|
* modifier2 ::= print | eps.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* modifier ::= read modifier2 | print | eps. */
|
||||||
|
public Tree parseModifier() {
|
||||||
|
switch (in.lookaheadToken().getType()) {
|
||||||
|
case Token.READ:
|
||||||
|
Tree read, modifier2;
|
||||||
|
|
||||||
|
if ((read = parseToken(Token.READ)) != null
|
||||||
|
&& (modifier2 = parseModifier2()) != null) {
|
||||||
|
Tree tree = new Tree(new Token(Token.MODIFIER));
|
||||||
|
tree.addLastChild(read);
|
||||||
|
tree.addLastChild(modifier2);
|
||||||
|
return tree;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Token.PRINT:
|
||||||
|
Tree print;
|
||||||
|
|
||||||
|
if ((print = parseToken(Token.PRINT)) != null) {
|
||||||
|
Tree tree = new Tree(new Token(Token.MODIFIER));
|
||||||
|
tree.addLastChild(print);
|
||||||
|
return tree;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* modifier2 ::= print | eps. */
|
||||||
|
public Tree parseModifier2() {
|
||||||
|
if (in.lookaheadToken()
|
||||||
|
.getType() == Token.PRINT) {
|
||||||
|
Tree print;
|
||||||
|
|
||||||
|
if ((print = parseToken(Token.PRINT)) != null) {
|
||||||
|
return print;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tree parseType() {
|
||||||
|
Tree type;
|
||||||
|
|
||||||
|
// type ::= int.
|
||||||
|
if (((type = parseToken(Token.INT)) != null)) {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
// type ::= float.
|
||||||
|
if (((type = parseToken(Token.FLOAT)) != null)) {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
// type ::= string.
|
||||||
|
if (((type = parseToken(Token.STRING)) != null)) {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fail
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tree parseDecl() {
|
||||||
|
|
||||||
|
// decl ::= modifier id ":" type ";".
|
||||||
|
Tree modifier, id, type;
|
||||||
|
if (((modifier = parseModifier()) != null) && ((id = parseToken(Token.ID)) != null) &&
|
||||||
|
((parseToken(Token.COLON)) != null) && ((type = parseType()) != null) && ((parseToken(Token.SEMICOLON)) != null)) {
|
||||||
|
Tree tree = new Tree(new Token(Token.DECL));
|
||||||
|
// tree.addLastChild(modifier);
|
||||||
|
tree.addLastChild(id);
|
||||||
|
tree.addLastChild(type);
|
||||||
|
for (Tree mod : modifier.getChildren()) {
|
||||||
|
tree.addLastChild(mod);
|
||||||
|
}
|
||||||
|
return tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fail
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tree parseExpr3() {
|
||||||
|
|
||||||
|
Tree minus, number, id, expr;
|
||||||
|
Token uminus;
|
||||||
|
|
||||||
|
// expr3 ::= "-" int.
|
||||||
|
if (((minus = parseToken(Token.MINUS)) != null) && ((number = parseToken(Token.INTCONST)) != null)) {
|
||||||
|
uminus = new Token(Token.UMINUS,
|
||||||
|
"-",
|
||||||
|
minus.getToken()
|
||||||
|
.getLine(),
|
||||||
|
minus.getToken()
|
||||||
|
.getColumn());
|
||||||
|
minus = new Tree(uminus);
|
||||||
|
minus.addLastChild(number);
|
||||||
|
return minus;
|
||||||
|
}
|
||||||
|
|
||||||
|
// expr3 ::= int.
|
||||||
|
if (((number = parseToken(Token.INTCONST)) != null)) {
|
||||||
|
return number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// expr3 ::= "-" float.
|
||||||
|
if (((minus = parseToken(Token.MINUS)) != null) && ((number = parseToken(Token.FLOATCONST)) != null)) {
|
||||||
|
uminus = new Token(Token.UMINUS,
|
||||||
|
"-",
|
||||||
|
minus.getToken()
|
||||||
|
.getLine(),
|
||||||
|
minus.getToken()
|
||||||
|
.getColumn());
|
||||||
|
minus = new Tree(uminus);
|
||||||
|
minus.addLastChild(number);
|
||||||
|
return minus;
|
||||||
|
}
|
||||||
|
|
||||||
|
// expr3 ::= float.
|
||||||
|
if (((number = parseToken(Token.FLOATCONST)) != null)) {
|
||||||
|
return number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// expr3 ::= string.
|
||||||
|
if (((number = parseToken(Token.STRINGCONST)) != null)) {
|
||||||
|
return number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// expr3 ::= id.
|
||||||
|
if (((id = parseToken(Token.ID)) != null)) {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// expr3 ::= "(" expr ")".
|
||||||
|
if (((parseToken(Token.LBR)) != null) && ((expr = parseExpr()) != null) && ((parseToken(Token.RBR)) != null)) {
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fail
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tree parseExpr2() {
|
||||||
|
Tree exprl, op, exprr;
|
||||||
|
|
||||||
|
// expr2 ::= expr3 "*" expr2.
|
||||||
|
if (((exprl = parseExpr3()) != null) && ((op = parseToken(Token.MULT)) != null) && ((exprr = parseExpr2()) != null)) {
|
||||||
|
// left-assoziativ!!
|
||||||
|
return addLeftAssoziativ(exprl, op, exprr, MultDiv);
|
||||||
|
}
|
||||||
|
|
||||||
|
// expr2 ::= expr3 "/" expr2.
|
||||||
|
if (((exprl = parseExpr3()) != null) && ((op = parseToken(Token.DIV)) != null) && ((exprr = parseExpr2()) != null)) {
|
||||||
|
return addLeftAssoziativ(exprl, op, exprr, MultDiv);
|
||||||
|
}
|
||||||
|
|
||||||
|
// expr2 ::= expr3.
|
||||||
|
if (((exprl = parseExpr3()) != null)) {
|
||||||
|
return exprl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fail
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tree parseExpr() {
|
||||||
|
|
||||||
|
Tree exprl, op, exprr;
|
||||||
|
|
||||||
|
// expr ::= expr2 "+" expr.
|
||||||
|
if (((exprl = parseExpr2()) != null) && ((op = parseToken(Token.PLUS)) != null) && ((exprr = parseExpr()) != null)) {
|
||||||
|
return addLeftAssoziativ(exprl, op, exprr, PlusMinus);
|
||||||
|
}
|
||||||
|
|
||||||
|
// expr ::= expr2 "-" expr.
|
||||||
|
if (((exprl = parseExpr2()) != null) && ((op = parseToken(Token.MINUS)) != null) && ((exprr = parseExpr()) != null)) {
|
||||||
|
return addLeftAssoziativ(exprl, op, exprr, PlusMinus);
|
||||||
|
}
|
||||||
|
|
||||||
|
// expr ::= expr2.
|
||||||
|
if (((exprl = parseExpr2()) != null)) {
|
||||||
|
return exprl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fail
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tree parseAssignStat() {
|
||||||
|
|
||||||
|
Tree id, assign, expr;
|
||||||
|
|
||||||
|
// assignStat ::= id ":=" expr ";".
|
||||||
|
if (((id = parseToken(Token.ID)) != null) && ((assign = parseToken(Token.ASSIGN)) != null) &&
|
||||||
|
((expr = parseExpr()) != null)) {
|
||||||
|
assign.addLastChild(id);
|
||||||
|
assign.addLastChild(expr);
|
||||||
|
return assign;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fail
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tree parseForStat() {
|
||||||
|
|
||||||
|
Tree tfor, init, cond, cont, stat;
|
||||||
|
|
||||||
|
// forstat ::= for "(" assignstat cond ";" assignstat ")" stat.
|
||||||
|
if (((tfor = parseToken(Token.FOR)) != null) && ((parseToken(Token.LBR)) != null) &&
|
||||||
|
((init = parseAssignStat()) != null) && ((parseToken(Token.SEMICOLON)) != null) && ((cond = parseCond()) != null) &&
|
||||||
|
((parseToken(Token.SEMICOLON)) != null) && ((cont = parseAssignStat()) != null) &&
|
||||||
|
((parseToken(Token.RBR)) != null) && ((stat = parseStat()) != null)) {
|
||||||
|
tfor.addLastChild(init);
|
||||||
|
tfor.addLastChild(cond);
|
||||||
|
tfor.addLastChild(cont);
|
||||||
|
tfor.addLastChild(stat);
|
||||||
|
return tfor;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fail
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tree parseWhileStat() {
|
||||||
|
|
||||||
|
Tree twhile, cond, stat;
|
||||||
|
|
||||||
|
// whilestat ::= while "(" cond ")" stat.
|
||||||
|
if (((twhile = parseToken(Token.WHILE)) != null) && ((parseToken(Token.LBR)) != null) && ((cond = parseCond()) != null) &&
|
||||||
|
((parseToken(Token.RBR)) != null) && ((stat = parseStat()) != null)) {
|
||||||
|
twhile.addLastChild(cond);
|
||||||
|
twhile.addLastChild(stat);
|
||||||
|
return twhile;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fail
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tree parseCondStat() {
|
||||||
|
|
||||||
|
Tree tif, cond, thenstat, elsestat;
|
||||||
|
|
||||||
|
// condstat ::= if cond then stat else stat.
|
||||||
|
if (((tif = parseToken(Token.IF)) != null) && ((cond = parseCond()) != null) && ((parseToken(Token.THEN)) != null) &&
|
||||||
|
((thenstat = parseStat()) != null) && ((parseToken(Token.ELSE)) != null) && ((elsestat = parseStat()) != null)) {
|
||||||
|
tif.addLastChild(cond);
|
||||||
|
tif.addLastChild(thenstat);
|
||||||
|
tif.addLastChild(elsestat);
|
||||||
|
return tif;
|
||||||
|
}
|
||||||
|
|
||||||
|
// condstat ::= if cond then stat.
|
||||||
|
if (((tif = parseToken(Token.IF)) != null) && ((cond = parseCond()) != null) && ((parseToken(Token.THEN)) != null) &&
|
||||||
|
((thenstat = parseStat()) != null)) {
|
||||||
|
tif.addLastChild(cond);
|
||||||
|
tif.addLastChild(thenstat);
|
||||||
|
return tif;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fail
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tree parseCond() {
|
||||||
|
|
||||||
|
Tree left, comp, right;
|
||||||
|
|
||||||
|
// cond ::= expr "<" expr.
|
||||||
|
if (((left = parseExpr()) != null) && ((comp = parseToken(Token.LESS)) != null) && ((right = parseExpr()) != null)) {
|
||||||
|
comp.addLastChild(left);
|
||||||
|
comp.addLastChild(right);
|
||||||
|
return comp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// cond ::= expr ">" expr.
|
||||||
|
if (((left = parseExpr()) != null) && ((comp = parseToken(Token.MORE)) != null) && ((right = parseExpr()) != null)) {
|
||||||
|
comp.addLastChild(left);
|
||||||
|
comp.addLastChild(right);
|
||||||
|
return comp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// cond ::= expr "=" expr.
|
||||||
|
if (((left = parseExpr()) != null) && ((comp = parseToken(Token.EQUALS)) != null) && ((right = parseExpr()) != null)) {
|
||||||
|
comp.addLastChild(left);
|
||||||
|
comp.addLastChild(right);
|
||||||
|
return comp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fail
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tree parseStat() {
|
||||||
|
|
||||||
|
Tree stat;
|
||||||
|
|
||||||
|
// stat ::= assignstat.
|
||||||
|
if (((stat = parseAssignStat()) != null)) {
|
||||||
|
return stat;
|
||||||
|
}
|
||||||
|
|
||||||
|
// stat ::= condstat.
|
||||||
|
if (((stat = parseCondStat()) != null)) {
|
||||||
|
return stat;
|
||||||
|
}
|
||||||
|
|
||||||
|
// stat ::= whilestat.
|
||||||
|
if (((stat = parseWhileStat()) != null)) {
|
||||||
|
return stat;
|
||||||
|
}
|
||||||
|
|
||||||
|
// stat ::= forstat.
|
||||||
|
if (((stat = parseForStat()) != null)) {
|
||||||
|
return stat;
|
||||||
|
}
|
||||||
|
|
||||||
|
// stat ::= block.
|
||||||
|
if (((stat = parseBlock()) != null)) {
|
||||||
|
return stat;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fail
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tree parseBlock() {
|
||||||
|
|
||||||
|
Tree statlist;
|
||||||
|
|
||||||
|
// block ::= begin statlist end.
|
||||||
|
if (((parseToken(Token.BEGIN)) != null) && ((statlist = parseStatlist()) != null) && ((parseToken(Token.END)) != null)) {
|
||||||
|
return statlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fail
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tree parseStatlist() {
|
||||||
|
Tree stat;
|
||||||
|
|
||||||
|
Tree tree = new Tree(new Token(Token.STATLIST));
|
||||||
|
// statlist ::= { statwithsemi }.
|
||||||
|
while (((stat = parseStatwithsemi())) != null) {
|
||||||
|
tree.addLastChild(stat);
|
||||||
|
}
|
||||||
|
return tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tree parseStatwithsemi() {
|
||||||
|
|
||||||
|
Tree stat;
|
||||||
|
|
||||||
|
// statwithsemi ::= stat ";"
|
||||||
|
if ((((stat = parseStat())) != null) && ((parseToken(Token.SEMICOLON)) != null)) {
|
||||||
|
return stat;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fail
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* decllist ::= decl decllist.
|
||||||
|
* decllist ::= eps.
|
||||||
|
*/
|
||||||
|
public Tree parseDecllist() {
|
||||||
|
Tree decl;
|
||||||
|
|
||||||
|
Tree tree = new Tree(new Token(Token.DECLLIST));
|
||||||
|
// decllist ::= { decl }.
|
||||||
|
while (((decl = parseDecl())) != null) {
|
||||||
|
tree.addLastChild(decl);
|
||||||
|
}
|
||||||
|
return tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tree parseProgram() {
|
||||||
|
|
||||||
|
Tree program, id, decllist, block;
|
||||||
|
|
||||||
|
// program ::= program id ";" decllist block "." EOF.
|
||||||
|
if (((program = parseToken(Token.PROGRAM)) != null) && (((id = parseToken(Token.ID))) != null) &&
|
||||||
|
((parseToken(Token.SEMICOLON)) != null) && ((decllist = parseDecllist()) != null) &&
|
||||||
|
((block = parseBlock()) != null) && ((parseToken(Token.DOT)) != null) && ((parseToken(Token.EOF)) != null)) {
|
||||||
|
program.addLastChild(id);
|
||||||
|
program.addLastChild(decllist);
|
||||||
|
program.addLastChild(block);
|
||||||
|
return program;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fail
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user