void doSum(ListIterator &i, TokenList *pf) { char oper; // For holding the operator doProduct(i, pf); // Sum = product + product if(!i.ended()) oper = i.token().tokenChar(); // Grab an operator, only if current != NULL while(((oper == '+') || (oper == '-')) && !i.ended() ) { i.advance(); // Move to next token, an int or a '(' doProduct(i, pf); Token t(oper); pf->push_back(t); // Add the operator the the expression if(!i.ended()) oper = i.token().tokenChar(); // Grab the next operator } }
void doAssign(ListIterator &i, ExprNode *&node) { ExprNode *left, *right; string eq; ListIterator temp = i; node = new Variable(i.token().tokenChar()); if(!i.ended()) i.advance(); if(!i.ended()) eq = i.token().tokenChar(); if(eq == "=" && !i.ended()) { while(eq == "=" && !i.ended()) { if(!i.ended()) i.advance(); if(!i.ended()) doSum(i, right); node = new Operation(node, eq, right); if(!i.ended()) eq = i.token().tokenChar(); else eq = "Done"; } } else if(!i.ended() && (i.token().tokenChar() != "(")) i = temp; else if(!i.ended() && (i.token().tokenChar() == "(")) { i = temp; doCall(i, node); } }
int evaluate(const char str[], VarTree &vars, FunctionDef &fmap) { TokenList l(str); // Declare and construct our linked list ExprNode *root; static int ans = 0; // For handling previous answers ListIterator i = l.begin(); if((!i.token().isInteger()) && (i.token().isOperator())) { Token newHead(ans); l.push_front(newHead); i = l.begin(); } if(i.token().tokenChar() == "deffn") { doDefine(i, fmap); root = new Value(0); } else doCompare(i, root); // Here begins the Conversion cout << *root << endl; return root->evaluate(vars, fmap); }
void doCall(ListIterator &i, ExprNode *&node) { string name; ExprNode *parameters[10]; int p = 0; if(!i.ended()) name = i.token().tokenChar(); i.advance(); if(!i.ended()) doCompare(i, node); parameters[p] = node; p++; if(!i.ended()){ while(!i.ended() && i.token().tokenChar() != ")") { if(!i.ended()) doCompare(i, node); parameters[p] = node; p++; } } for(; p < 10; p++) parameters[p] = NULL; node = new Function(name, parameters); }
//This function takes in the iterator, and rewrite both sides of the sum expression in postFix //Pre- The position is at a symbol +,-,*,/,% //Post- It will change postFix and the iterator void addOp(ListIterator &iter, TokenList &postFix) { int pos; Token saveToken; bool solved = false; while(solved == false) { if (iter.tokenChar() == '*' || iter.tokenChar() == '/' || iter.tokenChar() == '%') { //This means that a product operation was encountered immediately so the prgoram can finish the expression and return without multOp(iter, postFix); } else if (iter.tokenChar() == '+' || iter.tokenChar() == '-') { //We advance to save the next number and then again to check the next character saveToken = iter.token(); iter.advance(); getValue(iter, postFix); iter.advance(); if (iter.tokenChar() == '*' || iter.tokenChar() == '/' || iter.tokenChar() == '%') { //If a product expression is found it will calculate the entirety of that multOp(iter, postFix); } postFix.push_back(saveToken); } else { solved = true; } } }
string tokenText(ListIterator& infix, TokenList& list) { if (infix != list.end()) return infix.token().tokenText(); else return ""; }
// output operation // Display all of the tokens in the list ostream& operator<<( ostream &stream, TokenList &t ) { for (ListIterator iter = t.begin(); iter != t.end(); iter.advance()) { stream << iter.token() << " "; } return stream; }
void doCompare(ListIterator &i, ExprNode *&test) { ExprNode *trueCase, *falseCase, *right; string comp; doSum(i, test); if(!i.ended()) { if(i.token().tokenChar() == ")") i.advance(); } if(!i.ended() && i.token().isOperator()) { comp = i.token().tokenChar(); i.advance(); doSum(i, right); test = new Operation(test, comp, right); } if(!i.ended() && (i.token().tokenChar() == "?" || i.token().isOperator())) { i.advance(); doSum(i, trueCase); } if(!i.ended() && (i.token().isOperator() || i.token().tokenChar() == ":")) { i.advance(); doSum(i, falseCase); test = new Conditional(test, trueCase, falseCase); } }
// handleMultiplyLevelOperation // Handles *, /, and % // Parameters: // iter - the iterator for the list of tokens // postExpr - the postfix expression we are converting to // Pre-condition: iter.tokenChar() == '*' or '/' or '%' // Post-condition: iter.tokenChar() == end of what was multiplied (last int/parenthesis) // postExpr has both operands and the operator pushed to it void handleMultiplyLevelOperation(ListIterator& iter, TokenList& postExpr) { Token operation(iter.token()); iter.advance(); getValue(iter, postExpr, false); //Do not handle multiplication (see getValue()) postExpr.push_back(operation); }
// handleMultiplyLevelOperation // Handles + and - // Parameters: // iter - the iterator for the list of tokens // postExpr - the postfix expression we are converting to // Pre-condition: iter.tokenChar() == '+' or '-' // Post-condition: iter.tokenChar() == end of what was added (last int/parenthesis) // postExpr has both operands and the operator pushed to it void handleAdditionLevelOperation(ListIterator& iter, TokenList& postExpr) { Token operation(iter.token()); iter.advance(); getValue(iter, postExpr, true); //Do evaluate multiplication (see getValue()) postExpr.push_back(operation); }
void doDefine(ListIterator &i, FunctionDef &fmap) { string n; string parameters[10]; ExprNode *body; int p = 0; i.advance(); // i is now on the function name if(!i.ended()) n = i.token().tokenChar(); i.advance(); // i is now on open paren of parameters i.advance(); // i is now on the first parameter if(!i.ended()) parameters[p] = i.token().tokenChar(); p++; i.advance(); // i is now on comma separating parameters or close paren while(i.token().tokenChar() == "," && !i.ended()) { i.advance(); // i is now on next parameter if(!i.ended()) parameters[p] = i.token().tokenChar(); p++; i.advance(); // i is on new comma or close paren } i.advance(); // i is now on "=" i.advance(); if(!i.ended()) doCompare(i, body); fmap[n].name = n; for(int i = 0; i < p; i++) { fmap[n].parameter[i] = parameters[i]; } fmap[n].functionBody = body; fmap[n].locals = new VarTree(); cout << *fmap[n].functionBody << endl; }
void doProduct(ListIterator & i, ExprNode *&node) { ExprNode *left, *right; string oper; doFactor(i, node); if(!i.ended()) oper = i.token().tokenChar(); while(oper == "*" || oper == "/" || oper == "%") { i.advance(); doFactor(i, right); node = new Operation(node, oper, right); if(!i.ended()) oper = i.token().tokenChar(); else oper = "Done"; } }
void doFactor(ListIterator &i, TokenList *pf) // Grabs a factor; evaluates if needed; return { int left; // factor = int || factor = (int + int) if(i.token().tokenChar() == '(') { i.advance(); doSum(i, pf); } else { left = i.token().integerValue(); // grab the factor Token t(left); pf->push_back(t); // add it to the list } if(!i.ended()) i.advance(); }
void doFactor(ListIterator &i, ExprNode *&node) { ExprNode *left; if(i.token().tokenChar() == "(") { i.advance(); doSum(i, node); } else { if(i.token().isInteger()) { node = new Value(i.token().integerValue()); } else if(!i.token().isOperator()) doAssign(i, node); else doCompare(i, node); } if(!i.ended()) i.advance(); }
void doProduct(ListIterator &i, TokenList *pf) // Works exactly the same way as doSum(), except { // here, left and right are factors int left, right; char oper; doFactor(i, pf); // product = factor * factor if(!i.ended()) oper = i.token().tokenChar(); while(((oper == '*') || (oper == '/') || (oper =='%')) && !i.ended()) { i.advance(); doFactor(i, pf); Token t(oper); pf->push_back(t); if(!i.ended()) oper = i.token().tokenChar(); } }
//This function takes in the iterator, and the TokeList, and will rewrite any product expressions //Pre- The position will be on a operation symbol that is either *, /, % //Post- It will rewrite the infix to postFix product expression void multOp(ListIterator &iter, TokenList &postFix) { Token saveToken; //This loop will run indefinately and rewrite to postFix until the product expression ends while (iter.tokenChar() == '*' || iter.tokenChar() == '/' || iter.tokenChar() == '%') { saveToken = iter.token(); iter.advance(); getValue(iter, postFix); iter.advance(); postFix.push_back(saveToken); } }
//The function takes in an iterator and TokenList and will rewrite numbers at the iterator's //Pre- The position is located at a number or a parethesis //Post- It will write to the postFix TokenList and update the iterator void getValue(ListIterator &iter, TokenList &postFix) { //If parethesis are found this else if will rewrite the parenthesis in postFix if (iter.tokenChar() == '(') { iter.advance(); getValue(iter, postFix); iter.advance(); assignOp(iter, postFix); } //If the current position is an integer else { postFix.push_back(iter.token()); } }
//This function will solve a postFix notation TokenList. //Pre- This function takes in an iterator for a postFix TokenList and a TokenList in postFix notation. //Post- It will return the result of the entire postFix notation. int evalPost(ListIterator &iter, TokenList &postFix, VarTree &vt) { Token v1, v2; int value = 0, n1, n2; bool solved = false, solvedI = false; char saveChar; //Making the stack TokenList toSolve; //Runs until the equation is determined to be solved. while (solved == false) { //Will add all the consecutive integers onto the stack while (iter.tokenChar() != '=' && iter.tokenChar() != '+' && iter.tokenChar() != '-' && iter.tokenChar() != '*' && iter.tokenChar() != '/' && iter.tokenChar() != '%') { //Actually pushing onto the stack toSolve.push_front(iter.token()); iter.advance(); } //Getting 2 numbers from the stack v2 = toSolve.pop_front(); v1 = toSolve.pop_front(); //If it a normal integer if(v2.isInteger()) { n2 = v2.integerValue(); } //If it is a variable find it else { n2 = vt.lookup(v2.tokenText()); } //If it a normal integer if(v1.isInteger()) { n1 = v1.integerValue(); } //If it is a variable find it else { n1 = vt.lookup(v1.tokenText()); } //Grabbing the character operation from the originol TokenList saveChar = iter.tokenChar(); iter.advance(); if(saveChar == '+') { value = n1 + n2; } else if(saveChar == '-') { value = n1 - n2; } else if(saveChar == '*') { value = n1 * n2; } else if(saveChar == '/') { value = n1 / n2; } else if(saveChar == '%') { value = n1 % n2; } else if(saveChar == '=') { vt.assign(v1.tokenText(), n2); value = n2; } //Checks if the equation is done if(toSolve.empty() && !(iter != postFix.end())) { solved = true; } //If the equation is not done you push the current result and loop else { toSolve.push_front(Token(value)); } } return value; }
// evaluate // Evaluates the entire expression // Parameters: // expression (input string) the expression to evaluate // Pre-condition: The expression is correctly formatted // Return: Value of the expression int evaluate(const char expression[]) { TokenList expr(expression), //Original expression postExpr, //Expression converted to postfix numberStack; //Stack of numbers to facilitate evaluation //Converts expr into postfix and store it into postExpr convertToPostfix(expr, postExpr); std::cout << "Original expression: " << expr << std::endl; std::cout << "Converted postfix expression: " << postExpr << std::endl; for (ListIterator iter = postExpr.begin(); iter != postExpr.end(); iter.advance()) { Token t = iter.token(); if (t.isInteger()) { numberStack.push_front(t); } else { //This is the huge bit that handles operators //val2 is created but uninitialized to handle binary operators and //unary operators ('~') easily in the same switch int value = numberStack.pop_front().integerValue(); int val2 = 0; switch (t.tokenChar()) { case '*': val2 = numberStack.pop_front().integerValue(); val2 *= value; numberStack.push_front(Token(val2)); break; case '/': val2 = numberStack.pop_front().integerValue(); val2 /= value; numberStack.push_front(Token(val2)); break; case '%': val2 = numberStack.pop_front().integerValue(); val2 %= value; numberStack.push_front(Token(val2)); break; case '+': val2 = numberStack.pop_front().integerValue(); val2 += value; numberStack.push_front(Token(val2)); break; case '-': val2 = numberStack.pop_front().integerValue(); val2 -= value; numberStack.push_front(Token(val2)); break; case '~': value = -value; numberStack.push_front(Token(value)); break; } } } //Value left on the top of the number stack is the final value of the expression return numberStack.pop_front().integerValue(); }
int evaluate(const char str[]) { TokenList l(str); // Declare and construct our linked list TokenList *pf = new TokenList; // List for postfix expression static int ans = 0; // For handling previous answers ListIterator i = l.begin(); if((!i.token().isInteger()) && (i.token().tokenChar() != '(')) { // Complicated condition: evaluates as true if l.head is an operator // but not a parenthesis. // In this case, we want to push the previous answer to the front Token newHead(ans); l.push_front(newHead); i = l.begin(); } doSum(i, pf); // Here begins the Conversion cout << l << endl; cout << *pf << endl; TokenList *stack = new TokenList; // Stack for holding operators ListIterator eval = pf->begin(); // Iterator to parse postfix expression Token left, right; // Containers while(!eval.ended()) { if(eval.token().isInteger()) // While there are integers, push them onto the stack stack->push_front(eval.token()); else { right = stack->pop(); // grab the operands in order left = stack->pop(); switch(eval.token().tokenChar()) // Evaluate each piece of postfix { case '+': left = (left.integerValue() + right.integerValue()); break; case '-': left = (left.integerValue() - right.integerValue()); break; case '*': left = (left.integerValue() * right.integerValue()); break; case '/': left = (left.integerValue() / right.integerValue()); break; case '%': left = (left.integerValue() % right.integerValue()); break; } stack->push_front(left); } eval.advance(); } ans = left.integerValue(); return ans; }