@Override public Token parse() { Token next = first.getNext(); if (!next.isOperator(Operator.BRACKET_LEFT)) throw new RuntimeException("Expected '(' after WHILE, found: " + next); next = next.getNext(); testExp = new BooleanExpression(next, scope); next = testExp.parse(); if (!next.isOperator(Operator.BRACKET_RIGHT)) throw new RuntimeException("Expected ')' after WHILE condition, found: " + next); next = next.getNext(); if (!next.isNewline()) throw new RuntimeException("Expected newline, found: " + next); next = next.getNext(); Keyword[] target = {Keyword.END}; statements = new StatementGroup(next, target, scope); next = statements.parse(); return next.getNext(); }
/** * Parses and returns a valid 'leftside' of an expression. If the left side starts with a prefix, * it consumes other expressions with a lower priority than itself. If the left side does not have * a prefix it must be an expr0. * * @param commaIsEndMarker used when the leftside is part of and argument list of expressions * @param maxPriority operators with a higher priority than this will effectivly end the * expression * @return a wrapper of: 1. term correctly structured and 2. the priority of its root operator * @throws InvalidTermException */ private IdentifiedTerm parseLeftSide(boolean commaIsEndMarker, int maxPriority) throws InvalidTermException, IOException { // 1. prefix expression Token f = tokenizer.readToken(); if (f.isOperator(commaIsEndMarker)) { int FX = opManager.opPrio(f.seq, "fx"); int FY = opManager.opPrio(f.seq, "fy"); if (f.seq.equals("-")) { Token t = tokenizer.readToken(); if (t.isNumber()) /*Michele Castagna 06/2011*/ // return new IdentifiedTerm(0, Parser.createNumber("-" + t.seq)); return identifyTerm(0, Parser.createNumber("-" + t.seq), tokenStart); /**/ else tokenizer.unreadToken(t); } // check that no operator has a priority higher than permitted if (FY > maxPriority) FY = -1; if (FX > maxPriority) FX = -1; // FX has priority over FY boolean haveAttemptedFX = false; if (FX >= FY && FX >= OperatorManager.OP_LOW) { IdentifiedTerm found = exprA(FX - 1, commaIsEndMarker); // op(fx, n) exprA(n - 1) if (found != null) /*Castagna 06/2011*/ // return new IdentifiedTerm(FX, new Struct(f.seq, found.result)); return identifyTerm(FX, new Struct(f.seq, found.result), tokenStart); /**/ else haveAttemptedFX = true; } // FY has priority over FX, or FX has failed if (FY >= OperatorManager.OP_LOW) { IdentifiedTerm found = exprA(FY, commaIsEndMarker); // op(fy,n) exprA(1200) or op(fy,n) exprA(n) if (found != null) /*Castagna 06/2011*/ // return new IdentifiedTerm(FY, new Struct(f.seq, found.result)); return identifyTerm(FY, new Struct(f.seq, found.result), tokenStart); /**/ } // FY has priority over FX, but FY failed if (!haveAttemptedFX && FX >= OperatorManager.OP_LOW) { IdentifiedTerm found = exprA(FX - 1, commaIsEndMarker); // op(fx, n) exprA(n - 1) if (found != null) /*Castagna 06/2011*/ // return new IdentifiedTerm(FX, new Struct(f.seq, found.result)); return identifyTerm(FX, new Struct(f.seq, found.result), tokenStart); /**/ } } tokenizer.unreadToken(f); // 2. expr0 return new IdentifiedTerm(0, expr0()); }
private IdentifiedTerm exprA(int maxPriority, boolean commaIsEndMarker) throws InvalidTermException, IOException { IdentifiedTerm leftSide = exprB(maxPriority, commaIsEndMarker); // if (leftSide == null) // return null; // {op(yfx,n) exprA(n-1) | op(yf,n)}* Token t = tokenizer.readToken(); for (; t.isOperator(commaIsEndMarker); t = tokenizer.readToken()) { int YFX = opManager.opPrio(t.seq, "yfx"); int YF = opManager.opPrio(t.seq, "yf"); // YF and YFX has a higher priority than the left side expr and less then top limit // if (YF < leftSide.priority && YF > OperatorManager.OP_HIGH) YF = -1; if (YF < leftSide.priority || YF > maxPriority) YF = -1; // if (YFX < leftSide.priority && YFX > OperatorManager.OP_HIGH) YFX = -1; if (YFX < leftSide.priority || YFX > maxPriority) YFX = -1; // YFX has priority over YF if (YFX >= YF && YFX >= OperatorManager.OP_LOW) { IdentifiedTerm ta = exprA(YFX - 1, commaIsEndMarker); if (ta != null) { /*Castagna 06/2011*/ // leftSide = new IdentifiedTerm(YFX, new Struct(t.seq, leftSide.result, ta.result)); leftSide = identifyTerm(YFX, new Struct(t.seq, leftSide.result, ta.result), tokenStart); /**/ continue; } } // either YF has priority over YFX or YFX failed if (YF >= OperatorManager.OP_LOW) { /*Castagna 06/2011*/ // leftSide = new IdentifiedTerm(YF, new Struct(t.seq, leftSide.result)); leftSide = identifyTerm(YF, new Struct(t.seq, leftSide.result), tokenStart); /**/ continue; } break; } tokenizer.unreadToken(t); return leftSide; }
private IdentifiedTerm exprB(int maxPriority, boolean commaIsEndMarker) throws InvalidTermException, IOException { // 1. op(fx,n) exprA(n-1) | op(fy,n) exprA(n) | expr0 IdentifiedTerm left = parseLeftSide(commaIsEndMarker, maxPriority); // 2.left is followed by either xfx, xfy or xf operators, parse these Token operator = tokenizer.readToken(); for (; operator.isOperator(commaIsEndMarker); operator = tokenizer.readToken()) { int XFX = opManager.opPrio(operator.seq, "xfx"); int XFY = opManager.opPrio(operator.seq, "xfy"); int XF = opManager.opPrio(operator.seq, "xf"); // check that no operator has a priority higher than permitted // or a lower priority than the left side expression if (XFX > maxPriority || XFX < OperatorManager.OP_LOW) XFX = -1; if (XFY > maxPriority || XFY < OperatorManager.OP_LOW) XFY = -1; if (XF > maxPriority || XF < OperatorManager.OP_LOW) XF = -1; // XFX boolean haveAttemptedXFX = false; if (XFX >= XFY && XFX >= XF && XFX >= left.priority) { // XFX has priority IdentifiedTerm found = exprA(XFX - 1, commaIsEndMarker); if (found != null) { /*Castagna 06/2011*/ // Struct xfx = new Struct(operator.seq, left.result, found.result); // left = new IdentifiedTerm(XFX, xfx); left = identifyTerm(XFX, new Struct(operator.seq, left.result, found.result), tokenStart); /**/ continue; } else haveAttemptedXFX = true; } // XFY if (XFY >= XF && XFY >= left.priority) { // XFY has priority, or XFX has failed IdentifiedTerm found = exprA(XFY, commaIsEndMarker); if (found != null) { /*Castagna 06/2011*/ // Struct xfy = new Struct(operator.seq, left.result, found.result); // left = new IdentifiedTerm(XFY, xfy); left = identifyTerm(XFY, new Struct(operator.seq, left.result, found.result), tokenStart); /**/ continue; } } // XF if (XF >= left.priority) // XF has priority, or XFX and/or XFY has failed /*Castagna 06/2011*/ // return new IdentifiedTerm(XF, new Struct(operator.seq, left.result)); return identifyTerm(XF, new Struct(operator.seq, left.result), tokenStart); /**/ // XFX did not have top priority, but XFY failed if (!haveAttemptedXFX && XFX >= left.priority) { IdentifiedTerm found = exprA(XFX - 1, commaIsEndMarker); if (found != null) { /*Castagna 06/2011*/ // Struct xfx = new Struct(operator.seq, left.result, found.result); // left = new IdentifiedTerm(XFX, xfx); left = identifyTerm(XFX, new Struct(operator.seq, left.result, found.result), tokenStart); /**/ continue; } } break; } tokenizer.unreadToken(operator); return left; }