/** * Create a new parser. (This is mainly for internal use in this class.) * * @param parent if the parent is non-null, then this parser inherits any symbols that have been * added to the parent parser. Symbols that are added to this parser do not affect the parent, * but will hide symbols in the parent that have the same name making them unavailable for use * by this parser. */ public Parser(Parser parent) { if (parent != null) symbolTable = new SymbolTable(parent.symbolTable); else { symbolTable = new SymbolTable(); add(PI); add(E); add(I); StandardFunction[] functions = StandardFunction.getFunctions(); for (StandardFunction f : functions) symbolTable.put(f.getName().toLowerCase(), f); } }
/** Non-standard constructor to create an internal call on key() with a known key fingerprint */ public static KeyFn internalKeyCall( NamePool pool, int fingerprint, String name, Expression value, Expression doc) { KeyFn k = new KeyFn(); Expression[] arguments = {new StringValue(name), value, doc}; k.argument = arguments; k.keyFingerprint = fingerprint; k.checked = true; k.internal = true; k.setDetails(StandardFunction.getFunction("key", 3)); k.setFunctionNameCode(pool.allocate("fn", NamespaceConstant.FN, "key")); k.adoptChildExpression(value); k.adoptChildExpression(doc); return k; }
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; } }