/** * Evaluates a PostfixMathCommandI with given arguments. Not used in normal use. * * @param pfmc the command to evaluate. * @param children the parameters to the function. * @return the value of the function * @throws ParseException */ public Object eval(PostfixMathCommandI pfmc, Node children[]) throws ParseException { if (pfmc instanceof SpecialEvaluationI) { ASTFunNode node = new ASTFunNode(ParserTreeConstants.JJTFUNNODE); node.setFunction("TmpFun", pfmc); node.jjtOpen(); for (int i = 0; i < children.length; ++i) { node.jjtAddChild(children[i], i); } node.jjtClose(); return ((SpecialEvaluationI) pfmc).evaluate(node, null, this, new Stack(), this.symTab); } if (pfmc instanceof CallbackEvaluationI) { ASTFunNode node = new ASTFunNode(ParserTreeConstants.JJTFUNNODE); node.setFunction("TmpFun", pfmc); node.jjtOpen(); for (int i = 0; i < children.length; ++i) { node.jjtAddChild(children[i], i); } node.jjtClose(); Object val = ((CallbackEvaluationI) pfmc).evaluate(node, this); return val; } Stack lstack = new Stack(); for (int i = 0; i < children.length; ++i) { if (!(children[i] instanceof ASTConstant)) throw new ParseException("buildConstantNode: arguments must all be constant nodes"); lstack.push(((ASTConstant) children[i]).getValue()); } pfmc.setCurNumberOfParameters(children.length); pfmc.run(lstack); return lstack.pop(); }
/** * Visit a function node. The values of the child nodes are first pushed onto the stack. Then the * function class associated with the node is used to evaluate the function. * * <p>If a function implements SpecialEvaluationI then the evaluate method of PFMC is called. */ public Object visit(ASTFunNode node, Object data) throws ParseException { if (node == null) return null; PostfixMathCommandI pfmc = node.getPFMC(); // check if the function class is set if (pfmc == null) throw new ParseException("No function class associated with " + node.getName()); // Some operators (=) need a special method for evaluation // as the pfmc.run method does not have enough information // in such cases we call the evaluate method which passes // all available info. Note evaluating the children is // the responsibility of the evaluate method. if (pfmc instanceof SpecialEvaluationI) { return ((SpecialEvaluationI) pfmc).evaluate(node, data, this, stack, this.symTab); } if (pfmc instanceof CallbackEvaluationI) { Object val = ((CallbackEvaluationI) pfmc).evaluate(node, this); stack.push(val); return val; } if (debug == true) { System.out.println("Stack size before childrenAccept: " + stack.size()); } // evaluate all children (each leaves their result on the stack) data = node.childrenAccept(this, data); if (debug == true) { System.out.println("Stack size after childrenAccept: " + stack.size()); } if (pfmc.getNumberOfParameters() == -1) { // need to tell the class how many parameters it can take off // the stack because it accepts a variable number of params pfmc.setCurNumberOfParameters(node.jjtGetNumChildren()); } // try to run the function pfmc.run(stack); if (debug == true) { System.out.println("Stack size after run: " + stack.size()); } return data; }
/** * Returns the value of the expression as an object. The expression tree is specified with its top * node. The algorithm uses a stack for evaluation. * * <p>The symTab parameter can be null, if no variables are expected in the expression. If a * variable is found, an error is added to the error list. * * <p>An exception is thrown, if an error occurs during evaluation. * * @return The value of the expression as an object. * @throws ParseException if there is a problem with the evaluation. */ public Object getValue(Node topNode, SymbolTable symTab_in) throws ParseException { // check if arguments are ok if (topNode == null) { throw new ParseException("topNode parameter is null"); } // set member vars // errorList = errorList_in; symTab = symTab_in; // System.out.println("Evaluating expression " + topNode.toLongString() + " with symTab: " + // symTab); // errorFlag = false; stack.removeAllElements(); // rjm addition ensure stack is correct before beginning. // njf changed from clear() to removeAllElements for 1.1 compatibility // evaluate by letting the top node accept the visitor topNode.jjtAccept(this, null); /* } catch (ParseException e) { this.addToErrorList("Error: "+e.getMessage()); return null; } if(errorFlag) return null; */ // something is wrong if not exactly one item remains on the stack // or if the error flag has been set if (stack.size() != 1) { throw new ParseException("Stack corrupted"); } // return the value of the expression return stack.pop(); }
/** * Visit a variable node. The value of the variable is obtained from the symbol table (symTab) and * pushed onto the stack. */ public Object visit(ASTVarNode node, Object data) throws ParseException { // try to get the variable object Variable var = symTab.getVar(node.getVarName()); if (var == null) { String message = "Could not evaluate " + node.getVarName() + ": "; throw new ParseException(message + "the variable was not found in the symbol table"); } // get the variable value // Object temp = var.getValue(); Object temp = var.getValue(); if (trapNullValues && temp == null) { String message = "Could not evaluate " + node.getVarName() + ": "; throw new ParseException(message + "variable not set"); } // all is fine // push the value on the stack stack.push(temp); return data; }
/** Visit a constant node. The value of the constant is pushed onto the stack. */ public Object visit(ASTConstant node, Object data) { stack.push(node.getValue()); return data; }
/** * Evaluates a given node, in the current context. * * @param node The node to evaluate * @return result of the evaluation */ public Object eval(Node node) throws ParseException { node.jjtAccept(this, null); return stack.pop(); }