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); } }
// getValue // Gets the value of the number/expression at the current position // If the current value is an integer, return it // If it's a parenthetical expression, evaluate, and return // evalMultiplication is a flag used to ensure multiplication happens before addition // If true, it will handle any multiplication that is applied to the current value // That way, what is returned to the addition function is what we actually want to add // Parameters: // iter - the iterator for the list of tokens // postExpr - the postfix expression we are converting to // evalMultiplication (input boolean) whether to evaluate multiplication, see above // Pre-condition: expr[pos] is an int or parenthesis // Post-condition: expr[pos] is the end of the value // If it was an int, it's on the int // If it was a parenthesis, it's on the end parenthesis // If handling multiplication, it's on the last multiplied int // postExpr has the values handled here pushed to it void getValue(ListIterator& iter, TokenList& postExpr, bool evalMultiplication) { bool negative = false; if (!iter.currentIsInteger() && iter.tokenChar() == '-') { negative = true; iter.advance(); } if (iter.currentIsInteger()) { postExpr.push_back(iter.integerValue()); if (negative) { postExpr.push_back(Token('~')); } while (evalMultiplication && isNextOperatorMultiplication(iter)) { iter.advance(); handleMultiplyLevelOperation(iter, postExpr); } } else { handleParenthesis(iter, postExpr); if (negative) { postExpr.push_back(Token('~')); } } }
//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; } } }
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); } }
const List<Object>& List<Object>::operator =( const List<Object>& rhs ) { if (this != &rhs) { makeEmpty(); ListIterator<Object> rightiter = rhs.first( ); ListIterator<Object> myiterator = zeroth(); while( rightiter.isValid() ) { insert( rightiter.retrieve(), myiterator ); rightiter.advance(); myiterator.advance(); } } return( *this ); }
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 } }
//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()); } }
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 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); } }
// 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 makeFunction(ListIterator& infix, TokenList& list, FunctionDef& funs) { infix.advance(); //advance past deffn string name = tokenText(infix, list); funs[name] = FunDef(); FunDef* function = &funs[name]; //to avoid multiple lookups in this function body function->name = name; infix.advance(); //advance past function name infix.advance(); //advance past '(' function->locals = new VarTree(); int paramcount = 0; while (tokenText(infix, list) != ")") { string paramname = tokenText(infix, list); function->parameter[paramcount] = paramname; function->locals->assign(paramname, 0); ++paramcount; infix.advance(); if (tokenText(infix, list) == ",") infix.advance(); } //we are now on a ")" infix.advance(); //so advance past ")" for (int i = paramcount; i < 10; ++i) function->parameter[i] = ""; function->functionBody = assignmentToTree(infix,list,funs); #ifdef DEBUG cout << "Function:" << endl; cout << " Name: " << function->name << endl; for (int i = 0; i < 10 && function->parameter[i] != ""; ++i) cout << " Parameter " << i << ": " << function->parameter[i] << endl; cout << " VarTree: " << function->locals << endl; cout << " VarTree: " << *function->locals << endl; cout << " ExprNode: " << function->functionBody << endl; cout << " ExprNode: " << *function->functionBody << endl; #endif }
// 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 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(); }
// handleParenthesis // Helper function to handle evaluating parenthesis // Parameters: // iter - the iterator for the list of tokens // postExpr - the postfix expression we are converting to // Pre-condition: iter.tokenChar() == '(' // Post-condition: iter.tokenChar() == ')' // postExpr has everything inside the parenthesis pushed to it void handleParenthesis(ListIterator& iter, TokenList& postExpr) { iter.advance(); getValue(iter, postExpr, false); while (iter.tokenChar() != ')') { evalStep(iter, postExpr); } }
void printList( const List<int>& l ) { if (l.isEmpty()) cout << "Empty list" << endl; else { ListIterator<int> iter = l.first(); while (iter.isValid()) { cout << iter.retrieve() << " -> "; iter.advance(); } cout << "NULL"; cout << endl; } }
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(); }
// evalStep // Evaluates the current operator // Parameters: // iter - the iterator for the list of tokens // postExpr - the postfix expression we are converting to // Pre-condition: Next token is an operator (although, it will just advance if it isn't) // Post-condition: All values related to this operation pushed to postExpr in the order dictated by postfix // Iter is on the last token evaluated in this step (so iter.advance() next time will // bring it to the next thing to be evaluated) void evalStep(ListIterator& iter, TokenList& postExpr) { iter.advance(); switch (iter.tokenChar()) { case '*': case '/': case '%': handleMultiplyLevelOperation(iter, postExpr); break; case '+': case '-': handleAdditionLevelOperation(iter, postExpr); break; } }
// isNextOperatorMultiplication // Checks if the next operation in the expression has multiplication precedence // This is used to ensure multiplication is handled before addition // Parameters: // iter - the iterator for the list of tokens - not sent by reference, as in the other // functions, so that we can look ahead without having to go back again. // Pre-condition: Next token is an operator (although, if it's not, I suppose the next operation isn't // technically multiplication) // Return: whether the next operation is multiplication bool isNextOperatorMultiplication(ListIterator iter) { bool isMultiplication; iter.advance(); switch (iter.tokenChar()) { case '*': case '/': case '%': isMultiplication = true; break; default: isMultiplication = false; break; } return isMultiplication; }
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 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, 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 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; }
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; }
// 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(); }