QString Expression::processConstant( const QString & expr, bool * isConstant ) { bool temp; if (!isConstant) isConstant = &temp; QString code; // Make a tree to put the expression in. BTreeBase *tree = new BTreeBase(); BTreeNode *root = new BTreeNode(); // parse the expression into the tree buildTree(expr,tree,root,0); // compile the tree into assembly code tree->setRoot(root); tree->pruneTree(tree->root()); //code = traverseTree(tree->root()); // Look to see if it is a number if( root->type() == number ) { code = root->value(); *isConstant = true; } else { code = ""; *isConstant = false; } // Note deleting the tree deletes all nodes, so the root // doesn't need deleting separately. delete tree; return code; }
void BTreeBase::pruneTree(BTreeNode *root, bool /*conditionalRoot*/) { Traverser t(root); t.descendLeftwardToTerminal(); bool done = false; while(!done) { //t.descendLeftwardToTerminal(); if( t.current()->parent() ) { if( t.oppositeNode()->hasChildren() ) pruneTree(t.oppositeNode()); } t.moveToParent(); if( !t.current()->hasChildren() ) { //if(t.current() == t.root()) done = true; if(!t.current()->parent()) done = true; continue; } BTreeNode *l = t.current()->left(); BTreeNode *r = t.current()->right(); BTreeNode *n = 0; BTreeNode *z = 0; // Deal with situations where there are two constants so we want // to evaluate at compile time if( (l->type() == number && r->type() == number) ) // && !(t.current()==root&&conditionalRoot) ) { if(t.current()->childOp() == Expression::division && r->value() == "0" ) { t.current()->setChildOp(Expression::divbyzero); return; } QString value = QString::number(Parser::doArithmetic(l->value().toInt(),r->value().toInt(),t.current()->childOp())); t.current()->deleteChildren(); t.current()->setChildOp(Expression::noop); t.current()->setType(number); t.current()->setValue(value); } // Addition and subtraction else if(t.current()->childOp() == Expression::addition || t.current()->childOp() == Expression::subtraction) { // See if one of the nodes is 0, and set n to the node that actually has data, // z to the one containing zero. bool zero = false; if( l->value() == "0" ) { zero = true; n = r; z = l; } else if( r->value() == "0" ) { zero = true; n = l; z = r; } // Now get rid of the useless nodes if(zero) { BTreeNode *p = t.current(); // save in order to delete after replaceNode(p,n); t.setCurrent(n); // Delete the old nodes delete p; delete z; } } // Multiplication and division else if(t.current()->childOp() == Expression::multiplication || t.current()->childOp() == Expression::division) { // See if one of the nodes is 0, and set n to the node that actually has data, // z to the one containing zero. bool zero = false; bool one = false; if( l->value() == "1" ) { one = true; n = r; z = l; } else if( r->value() == "1" ) { one = true; n = l; z = r; } if( l->value() == "0" ) { zero = true; n = r; z = l; } else if( r->value() == "0" ) { // since we can't call compileError from in this class, we have a special way of handling it: // Leave the children as they are, and set childOp to divbyzero if( t.current()->childOp() == Expression::division ) { t.current()->setChildOp(Expression::divbyzero); return; // no point doing any more since we are going to raise a compileError later anyway. } zero = true; n = l; z = r; } // Now get rid of the useless nodes if(one) { BTreeNode *p = t.current(); // save in order to delete after replaceNode(p,n); t.setCurrent(n); // Delete the old nodes delete p; delete z; } if(zero) { BTreeNode *p = t.current(); p->deleteChildren(); p->setChildOp(Expression::noop); p->setType(number); p->setValue("0"); } } else if( t.current()->childOp() == Expression::bwand || t.current()->childOp() == Expression::bwor || t.current()->childOp() == Expression::bwxor ) { bool zero = false; if( l->value() == "0" ) { zero = true; n = r; z = l; } else if( r->value() == "0" ) { zero = true; n = l; z = r; } // Now get rid of the useless nodes if(zero) { BTreeNode *p = t.current(); QString value; if( p->childOp() == Expression::bwand ) { value = "0"; p->deleteChildren(); p->setChildOp(Expression::noop); p->setType(number); } if( p->childOp() == Expression::bwor || p->childOp() == Expression::bwxor ) { value = n->value(); BTreeNode *p = t.current(); // save in order to delete after replaceNode(p,n); t.setCurrent(n); // Delete the old nodes delete p; delete z; } p->setValue(value); } } if(!t.current()->parent() || t.current() == root) done = true; else { } } }
void Expression::compileConditional( const QString & expression, Code * ifCode, Code * elseCode ) { if( expression.contains(QRegExp("=>|=<|=!")) ) { mistake( Microbe::InvalidComparison, expression ); return; } if( expression.contains(QRegExp("[^=><!][=][^=]"))) { mistake( Microbe::InvalidEquals ); return; } // Make a tree to put the expression in. BTreeBase *tree = new BTreeBase(); BTreeNode *root = new BTreeNode(); // parse the expression into the tree buildTree(expression,tree,root,0); // Modify the tree so it is always at the top level of the form (kwoerpkwoep) == (qwopekqpowekp) if ( root->childOp() != equals && root->childOp() != notequals && root->childOp() != gt && root->childOp() != lt && root->childOp() != ge && root->childOp() != le && root->childOp() != pin && root->childOp() != notpin && root->childOp() != read_keypad ) { BTreeNode *newRoot = new BTreeNode(); BTreeNode *oneNode = new BTreeNode(); oneNode->setChildOp(noop); oneNode->setType(number); oneNode->setValue("1"); newRoot->setLeft(root); newRoot->setRight(oneNode); newRoot->setType(unset); newRoot->setChildOp(ge); tree->setRoot(newRoot); root = newRoot; } // compile the tree into assembly code tree->setRoot(root); tree->pruneTree(tree->root(),true); // We might have just a constant expression, in which case we can just always do if or else depending // on whether it is true or false. if( root->childOp() == noop ) { if( root->value().toInt() == 0 ) m_pic->mergeCode( elseCode ); else m_pic->mergeCode( ifCode ); return; } // traverse tree with argument conditionalRoot true // so that 3 == x gets integrated with code for if, repeat until etc... m_ifCode = ifCode; m_elseCode = elseCode; traverseTree(tree->root(),true); // Note deleting the tree deletes all nodes, so the root // doesn't need deleting separately. delete tree; }