diff --git a/ÜB-Praxis-LL1-Parser für X-Leer/src/de/dhbw/compiler/xparser/XParser.java b/ÜB-Praxis-LL1-Parser für X-Leer/src/de/dhbw/compiler/xparser/XParser.java index 7e201b3..55629de 100644 --- a/ÜB-Praxis-LL1-Parser für X-Leer/src/de/dhbw/compiler/xparser/XParser.java +++ b/ÜB-Praxis-LL1-Parser für X-Leer/src/de/dhbw/compiler/xparser/XParser.java @@ -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; +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; + public class XParser { - public XParser(TokenBuffer in) { - //TODO Initialization - } + private final TokenBuffer in; + private long comparecount = 0; - public Tree parseProgram() { - //TODO Parser - return null; - } + private final Set PlusMinus; + private final Set MultDiv; -} \ No newline at end of file + 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 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; + } +}