private Type parseNumericalExpr(Context cntx) { Token leadingSign = null; if (cntx.peek() == Token.PLUS || cntx.peek() == Token.MINUS) leadingSign = cntx.next(); Type type = parseNumericalTerm(cntx); if (leadingSign != null) { if (type == Type.BOOLEAN) error(cntx, "vmm.parser.OperatorRequiresNumerical", leadingSign == Token.PLUS ? "+" : "-"); if (leadingSign == Token.MINUS) cntx.bldr.addStackOp(type == Type.REAL ? StackOp.UNARY_MINUS : StackOp.C_UNARY_MINUS); } while (cntx.peek() == Token.PLUS || cntx.peek() == Token.MINUS) { Token op = cntx.next(); String opName = cntx.tokstr; if (type == Type.BOOLEAN) error(cntx, "vmm.parser.OperatorRequiresNumerical", opName); Type nextType = parseNumericalTerm(cntx); if (nextType == Type.BOOLEAN) error(cntx, "vmm.parser.OperatorRequiresNumerical", opName); if (type == Type.REAL && nextType == Type.COMPLEX) { cntx.bldr.addStackOp(StackOp.FIRST_OP_TO_COMPLEX); type = Type.COMPLEX; } else if (type == Type.COMPLEX && nextType == Type.REAL) cntx.bldr.addStackOp(StackOp.REAL_TO_COMPLEX); if (type == Type.REAL) cntx.bldr.addStackOp(op == Token.PLUS ? StackOp.PLUS : StackOp.MINUS); else cntx.bldr.addStackOp(op == Token.PLUS ? StackOp.C_PLUS : StackOp.C_MINUS); } return type; }
private Type parseNumericalTerm(Context cntx) { Type type = parseNumericalFactor(cntx); while (canStartFactor.contains(cntx.peek())) { Token op; String opName; if (cntx.peek() == Token.TIMES || cntx.peek() == Token.DIVIDE) { op = cntx.next(); opName = cntx.tokstr; } else { op = Token.TIMES; opName = "*"; } if (type == Type.BOOLEAN) error(cntx, "vmm.parser.OperatorRequiresNumerical", opName); Type nextType = parseNumericalFactor(cntx); if (nextType == Type.BOOLEAN) error(cntx, "vmm.parser.OperatorRequiresNumerical", opName); if (type == Type.REAL && nextType == Type.COMPLEX) { cntx.bldr.addStackOp(StackOp.FIRST_OP_TO_COMPLEX); type = Type.COMPLEX; } else if (type == Type.COMPLEX && nextType == Type.REAL) cntx.bldr.addStackOp(StackOp.REAL_TO_COMPLEX); if (type == Type.REAL) cntx.bldr.addStackOp(op == Token.TIMES ? StackOp.TIMES : StackOp.DIVIDE); else cntx.bldr.addStackOp(op == Token.TIMES ? StackOp.C_TIMES : StackOp.C_DIVIDE); } return type; }
private Type parseBTerm(Context cntx) { Type type = parseBFactor(cntx); while (cntx.peek() == Token.AND) { if (type != Type.BOOLEAN) error(cntx, "vmm.parser.OperatorRequriesBoolean", "AND"); cntx.next(); Type nextType = parseBFactor(cntx); if (nextType != Type.BOOLEAN) error(cntx, "vmm.parser.OperatorRequriesBoolean", "AND"); cntx.bldr.addStackOp(StackOp.AND); } return type; }
private Type parseRelation(Context cntx) { Type type = parseNumericalExpr(cntx); if (relationalOps.contains(cntx.peek())) { Token op = cntx.next(); String opName = cntx.tokstr; if (type == Type.BOOLEAN) error(cntx, "vmm.parser.OperatorRequiresNumerical", opName); if (type == Type.COMPLEX && op != Token.EQUAL && op != Token.NOT_EQUAL) error(cntx, "vmm.parser.RelationNotDefinedForComplex", opName); Type nextType = parseNumericalExpr(cntx); if (nextType == Type.BOOLEAN) error(cntx, "vmm.parser.OperatorRequiresNumerical", opName); if (nextType == Type.COMPLEX && op != Token.EQUAL && op != Token.NOT_EQUAL) error(cntx, "vmm.parser.RelationNotDefinedForComplex", opName); if (type == Type.REAL && nextType == Type.COMPLEX) { cntx.bldr.addStackOp(StackOp.FIRST_OP_TO_COMPLEX); type = Type.COMPLEX; } switch (op) { case EQUAL: cntx.bldr.addStackOp(type == Type.COMPLEX ? StackOp.C_EQ : StackOp.EQ); break; case NOT_EQUAL: cntx.bldr.addStackOp(type == Type.COMPLEX ? StackOp.C_NE : StackOp.NE); break; case GREATER: cntx.bldr.addStackOp(StackOp.GT); break; case LESS: cntx.bldr.addStackOp(StackOp.LT); break; case GREATER_EQUAL: cntx.bldr.addStackOp(StackOp.GE); break; case LESS_EQUAL: cntx.bldr.addStackOp(StackOp.LE); break; } if (relationalOps.contains(cntx.peek())) error(cntx, "vmm.parser.CantStringRelations"); return Type.BOOLEAN; } return type; }
private Type parseBFactor(Context cntx) { int notCount = 0; while (cntx.peek() == Token.NOT) { notCount++; cntx.next(); } Type type = parseRelation(cntx); if (notCount > 0 && type != Type.BOOLEAN) error(cntx, "vmm.parser.OperatorRequriesBoolean", "NOT"); if (notCount % 2 == 1) cntx.bldr.addStackOp(StackOp.NOT); return type; }
private Type parseBExpr(Context cntx) { Type type = parseBTerm(cntx); while (cntx.peek() == Token.OR) { if (type != Type.BOOLEAN) error(cntx, "vmm.parser.OperatorRequriesBoolean", "OR"); cntx.next(); Type nextType = parseBTerm(cntx); if (nextType != Type.BOOLEAN) error(cntx, "vmm.parser.OperatorRequriesBoolean", "OR"); cntx.bldr.addStackOp(StackOp.OR); } if (cntx.peek() == Token.QUESTION) { if (type != Type.BOOLEAN) error(cntx, "vmm.parser.ConditionalRequiresBoolean"); cntx.next(); int firstExpr = cntx.bldr.startSubProg(); type = parseNumericalExpr(cntx); if (type == Type.BOOLEAN) error(cntx, "vmm.parser.ConditionalExpressionsMustBeNumerical"); cntx.bldr.finishSubProg(); int secondExpr = cntx.bldr.startSubProg(); Type nextType; if (cntx.peek() != Token.COLON) { nextType = type; if (type == Type.REAL) cntx.bldr.addRealConstant(Double.NaN); else cntx.bldr.addComplexConstant(Double.NaN, Double.NaN); } else { cntx.next(); nextType = parseBExpr(cntx); if (nextType == Type.BOOLEAN) error(cntx, "vmm.parser.ConditionalExpressionsMustBeNumerical"); if (type == Type.COMPLEX && nextType == Type.REAL) cntx.bldr.addStackOp(StackOp.REAL_TO_COMPLEX); } cntx.bldr.finishSubProg(); if (type == Type.REAL && nextType == Type.COMPLEX) { cntx.bldr.addConditional(firstExpr, secondExpr, true); type = Type.COMPLEX; } else cntx.bldr.addConditional(firstExpr, secondExpr, false); } return type; }
private Type parseNumericalFactor(Context cntx) { Type type = parseNumericalPrimary(cntx); while (cntx.peek() == Token.POWER) { cntx.next(); String opName = cntx.tokstr; if (type == Type.BOOLEAN) error(cntx, "vmm.parser.OperatorRequiresNumerical", opName); Type nextType = parseNumericalPrimary(cntx); if (nextType == Type.BOOLEAN) error(cntx, "vmm.parser.OperatorRequiresNumerical", opName); if (type == Type.REAL) { if (nextType == Type.COMPLEX) { cntx.bldr.addStackOp(StackOp.FIRST_OP_TO_COMPLEX); type = Type.COMPLEX; } else if (cntx.complexOnly) { cntx.bldr.addStackOp(StackOp.REAL_TO_COMPLEX); cntx.bldr.addStackOp(StackOp.FIRST_OP_TO_COMPLEX); type = nextType = Type.COMPLEX; } } if (type == Type.COMPLEX && nextType == Type.REAL) cntx.bldr.addStackOp(StackOp.C_REAL_POWER); else if (type == Type.REAL) cntx.bldr.addStackOp(StackOp.POWER); else cntx.bldr.addStackOp(StackOp.C_POWER); } return type; }
private Type parseNumericalPrimary(Context cntx) { Type type; Token tok = cntx.next(); Token openingParen; switch (tok) { case NUMBER: cntx.bldr.addRealConstant(cntx.number); return Type.REAL; case VARIABLE: cntx.bldr.addVariableRef((Variable) cntx.symbol); return Type.REAL; case ARGUMENT: cntx.bldr.addArgumentReference(((Argument) cntx.symbol).argnum); return Type.REAL; case COMPLEX_VARIABLE: cntx.bldr.addComplexVariableRef((ComplexVariable) cntx.symbol); return Type.COMPLEX; case COMPLEX_ARGUMENT: cntx.bldr.addArgumentReference(((ComplexArgument) cntx.symbol).argnum); return Type.COMPLEX; case FUNCTION: case COMPLEX_FUNCTION: case STANDARD_FUNCTION: case FUNCTION_COMPLEX_TO_REAL: Token funcTok = tok; Object symbol = cntx.symbol; String funcName = cntx.tokstr; openingParen = cntx.next(); if (openingParen != Token.LEFT_PAREN && openingParen != Token.LEFT_BRACE && openingParen != Token.LEFT_BRACKET) error(cntx, "vmm.parser.FunctionRequiresParen", funcName); int argCount = 0; int expectedArgs = funcTok == Token.FUNCTION ? ((Function) symbol).getArity() : funcTok == Token.COMPLEX_FUNCTION ? ((ComplexFunction) symbol).getArity() : funcTok == Token.STANDARD_FUNCTION ? 1 : 2; Type argType = null; while (true) { tok = cntx.peek(); if (tok == Token.RIGHT_PAREN || tok == Token.RIGHT_BRACE || tok == Token.RIGHT_BRACKET) break; argCount++; if (argCount > expectedArgs) error(cntx, "vmm.parser.TooManyArguments", funcName); argType = parseBExpr(cntx); if (funcTok == Token.FUNCTION || funcTok == Token.FUNCTION_COMPLEX_TO_REAL) { if (argType != Type.REAL) error(cntx, "vmm.parser.NeedRealArgument", funcName); } else if (funcTok == Token.COMPLEX_FUNCTION) { if (argType == Type.BOOLEAN) error(cntx, "vmm.parser.NeedComplexArgument", funcName); if (argType == Type.REAL) cntx.bldr.addStackOp(StackOp.REAL_TO_COMPLEX); } else if (funcTok == Token.STANDARD_FUNCTION) { StandardFunction f = (StandardFunction) symbol; if (argType == Type.COMPLEX) { if (f.getComplexArgOp() == null) error(cntx, "vmm.parser.NeedRealArgument", funcName); } else if (argType == Type.REAL) { if (f.getRealArgOp() == null || (cntx.complexOnly && needRealToComplex.contains(f.getRealArgOp()))) { cntx.bldr.addStackOp(StackOp.REAL_TO_COMPLEX); argType = Type.COMPLEX; } } else { // argType is boolean if (f.getRealArgOp() == null || (cntx.complexOnly && needRealToComplex.contains(f.getRealArgOp()))) error(cntx, "vmm.parser.NeedComplexArgument", funcName); else error(cntx, "vmm.parser.NeedRealArgument", funcName); } } tok = cntx.peek(); if (tok != Token.COMMA) break; cntx.next(); } tok = cntx.next(); if (argCount < expectedArgs) error(cntx, "vmm.parser.NotEnoughArguments", funcName); if (openingParen == Token.LEFT_PAREN && tok != Token.RIGHT_PAREN) error(cntx, "vmm.parser.MissingCloseOfArgumentList", ")"); if (openingParen == Token.LEFT_BRACE && tok != Token.RIGHT_BRACE) error(cntx, "vmm.parser.MissingCloseOfArgumentList", "}"); if (openingParen == Token.LEFT_BRACKET && tok != Token.RIGHT_BRACKET) error(cntx, "vmm.parser.MissingCloseOfArgumentList", "]"); if (funcTok == Token.FUNCTION) { cntx.bldr.addFunctionRef(((Function) symbol).getProgFunction()); return Type.REAL; } else if (funcTok == Token.COMPLEX_FUNCTION) { cntx.bldr.addFunctionRef(((ComplexFunction) symbol).getProgFunction()); return Type.COMPLEX; } else if (funcTok == Token.FUNCTION_COMPLEX_TO_REAL) return Type.COMPLEX; else { StandardFunction f = (StandardFunction) symbol; cntx.bldr.addStackOp(argType == Type.COMPLEX ? f.getComplexArgOp() : f.getRealArgOp()); return argType == Type.COMPLEX ? f.getReturnTypeForComplexArg() : f.getReturnTypeForRealArg(); } case LEFT_PAREN: type = parseBExpr(cntx); tok = cntx.next(); if (tok == Token.EOS) error(cntx, "vmm.parser.MissingRightGroupThingAtEOS", ")", "("); if (tok != Token.RIGHT_PAREN) error(cntx, "vmm.parser.MissingRightGroupThing", ")", "(", cntx.tokstr); return type; case LEFT_BRACE: type = parseBExpr(cntx); tok = cntx.next(); if (tok == Token.EOS) error(cntx, "vmm.parser.MissingRightGroupThingAtEOS", "]", "["); if (tok != Token.RIGHT_BRACE) error(cntx, "vmm.parser.MissingRightGroupThing", "]", "[", cntx.tokstr); return type; case LEFT_BRACKET: type = parseBExpr(cntx); tok = cntx.next(); if (tok == Token.EOS) error(cntx, "vmm.parser.MissingRightGroupThingAtEOS", "}", "{"); if (tok != Token.RIGHT_PAREN) error(cntx, "vmm.parser.MissingRightGroupThing", "}", "{", cntx.tokstr); return type; case RIGHT_PAREN: error(cntx, "vmm.parser.ExtraRightGroupThing", ")", "("); return null; case RIGHT_BRACE: error(cntx, "vmm.parser.ExtraRightGroupThing", "}", "{"); return null; case RIGHT_BRACKET: error(cntx, "vmm.parser.ExtraRightGroupThing", "]", "["); return null; case UNKNOWN_CHAR: error(cntx, "vmm.parser.UnknownChar", cntx.tokstr); return null; case UNKNOWN_WORD: error(cntx, "vmm.parser.UndefinedWord", cntx.tokstr); return null; case ILLEGAL_NUMBER: error(cntx, "vmm.parser.IllegalNumber", cntx.tokstr); return null; case EOS: error(cntx, "vmm.parser.IncompleteExpression"); default: error(cntx, "vmm.parser.UnexcpectedToken", cntx.tokstr); return null; } }
private Type doParse(Context cntx) { if (cntx.peek() == Token.EOS) error(cntx, "vmm.parser.EmpytDefinition"); Type type = parseBExpr(cntx); if (cntx.peek() != Token.EOS) error(cntx, "vmm.parser.ExtraStuff"); return type; }