/** * 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()); }