File indexing completed on 2024-04-21 09:34:01

0001 /***************************************************************************
0002  *   Copyright (C) 2004-2005 by Daniel Clarke                              *
0003  *   daniel.jc@gmail.com                                                   *
0004  *                                     *
0005  *   24-04-2007                                                            *
0006  *   Modified to add pic 16f877,16f627 and 16f628              *
0007  *   by george john george@space-kerala.org,az.j.george@gmail.com      *
0008  *   supported by SPACE www.space-kerala.org                   *
0009  *                                                                         *
0010  *   This program is free software; you can redistribute it and/or modify  *
0011  *   it under the terms of the GNU General Public License as published by  *
0012  *   the Free Software Foundation; either version 2 of the License, or     *
0013  *   (at your option) any later version.                                   *
0014  *                                                                         *
0015  *   This program is distributed in the hope that it will be useful,       *
0016  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0017  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0018  *   GNU General Public License for more details.                          *
0019  *                                                                         *
0020  *   You should have received a copy of the GNU General Public License     *
0021  *   along with this program; if not, write to the                         *
0022  *   Free Software Foundation, Inc.,                                       *
0023  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
0024  ***************************************************************************/
0025 
0026 #include "btreebase.h"
0027 #include "btreenode.h"
0028 #include "expression.h"
0029 #include "traverser.h"
0030 #include "parser.h"
0031 #include "pic14.h"
0032 
0033 #include <QDebug>
0034 #include <QRegExp>
0035 
0036 Expression::Expression( PIC14 *pic, MicrobeApp *master, SourceLineMicrobe sourceLine, bool suppressNumberTooBig )
0037     : m_sourceLine(sourceLine)
0038 {
0039     m_pic = pic;
0040     mb = master;
0041     m_bSupressNumberTooBig = suppressNumberTooBig;
0042 }
0043 
0044 Expression::~Expression()
0045 {
0046 }
0047 
0048 void Expression::traverseTree( BTreeNode *root, bool conditionalRoot )
0049 {
0050     Traverser t(root);
0051     t.start();
0052 
0053     // special case: if we are starting at the root node then
0054     // we are dealing with something of the form variable = 6
0055     // or variable = portb
0056     ///TODO reimplement assignments as two branched trees?
0057     if ( t.current() == root &&
0058             !root->hasChildren() &&
0059             t.current()->childOp() != pin &&
0060             t.current()->childOp() != notpin &&
0061             t.current()->childOp() != function &&
0062             t.current()->childOp() != read_keypad )
0063     {
0064         switch(root->type())
0065         {
0066             case number: m_pic->assignNum(root->value()); break;
0067             case variable: m_pic->assignVar(root->value()); break;
0068             default: break; // Should never get here
0069         }
0070         // no need to traverse the tree as there is none.
0071         return;
0072     }
0073 
0074     t.setCurrent(root);
0075 
0076     if(t.current()->hasChildren())
0077     {
0078         // Here we work out what needs evaulating, and in which order.
0079         // To minimize register usage, if only one branch needs traversing,
0080         // then that branch should be done first.
0081         bool evaluateLeft = t.current()->left()->needsEvaluating();
0082 
0083         BTreeNode *evaluateFirst;
0084         BTreeNode *evaluateSecond;
0085 
0086         // If both need doing, then it really doesn't matter which we do
0087         // first (unless we are looking to do really complex optimizations...
0088 
0089         // Cases:
0090         // - Both need evaluating,
0091         // - or left needs doing first,
0092         // in both cases we evaluate left, then right.
0093         if( evaluateLeft )
0094         {
0095             evaluateFirst = t.current()->left();
0096             evaluateSecond = t.current()->right();
0097         }
0098         // Otherwise it is best to evaluate right first for reasons given above.
0099         else
0100         {
0101             evaluateFirst = t.current()->right();
0102             evaluateSecond = t.current()->left();
0103         }
0104 
0105         QString dest1 = mb->dest();
0106         mb->incDest();
0107         QString dest2 = mb->dest();
0108         mb->decDest();
0109 
0110         bool evaluated = false;
0111         if( evaluateFirst->hasChildren() )
0112         {
0113             traverseTree(evaluateFirst);
0114             evaluated = true;
0115         }
0116         else if( isUnaryOp(evaluateFirst->childOp()) )
0117         {
0118             doUnaryOp( evaluateFirst->childOp(), evaluateFirst );
0119             evaluated = true;
0120         }
0121         if ( evaluated )
0122         {
0123             // We need to save the result if we are going tro traverse the other
0124             // branch, or if we are performing a subtraction in which case the
0125             // value wanted in working is not the current value.
0126             // But as the optimizer will deal with unnecessary variables anyway,
0127             // always save to a register
0128 
0129             evaluateFirst->setReg( dest1 );
0130             evaluateFirst->setType( variable );
0131             m_pic->saveToReg( dest1 );
0132         }
0133 
0134         evaluated = false;
0135         if( evaluateSecond->hasChildren() )
0136         {
0137             mb->incDest();
0138             mb->incDest();
0139             traverseTree(evaluateSecond);
0140             evaluated = true;
0141             mb->decDest();
0142             mb->decDest();
0143         }
0144         else if( isUnaryOp(evaluateSecond->childOp()) )
0145         {
0146             doUnaryOp( evaluateSecond->childOp(), evaluateSecond );
0147             evaluated = true;
0148         }
0149         if ( evaluated )
0150         {
0151             evaluateSecond->setReg( dest2 );
0152             evaluateSecond->setType( variable );
0153             m_pic->saveToReg( dest2 );
0154         }
0155     }
0156 
0157     if(t.current()->childOp()==divbyzero)
0158     {
0159         mistake( MicrobeApp::DivisionByZero );
0160     }
0161 
0162     // If we are at the top level of something like 'if a == 3 then', then we are ready to put
0163     // in the if code, else the expression just evaluates to 0 or 1
0164     if(conditionalRoot && t.current() == root)
0165         m_pic->setConditionalCode(m_ifCode, m_elseCode);
0166 
0167     // Handle operations
0168     // (functions are not actually supported)
0169     if(isUnaryOp(t.current()->childOp()))
0170         doUnaryOp( t.current()->childOp(), t.current() );
0171     else
0172         doOp( t.current()->childOp(), t.current()->left(), t.current()->right() );
0173 
0174 }
0175 
0176 void Expression::doOp( Operation op, BTreeNode *left, BTreeNode *right )
0177 {
0178     QString lvalue;
0179     if(left->reg().isEmpty())
0180         lvalue = left->value();
0181     else
0182         lvalue = left->reg();
0183 
0184     QString rvalue;
0185     if(right->reg().isEmpty())
0186         rvalue = right->value();
0187     else
0188         rvalue = right->reg();
0189 
0190     // Handle if stuff
0191     PIC14::LocationType leftType = PIC14::num;
0192     switch ( left->type() )
0193     {
0194         case number:
0195             leftType = PIC14::num;
0196             break;
0197 
0198         case variable:
0199             leftType = PIC14::var;
0200             break;
0201 
0202         case working:
0203             leftType = PIC14::work;
0204             break;
0205 
0206         case unset:
0207         case extpin:
0208         case keypad:
0209             qCritical() << Q_FUNC_INFO << "Bad left->type(): " << left->type();
0210     };
0211 
0212     PIC14::LocationType rightType = PIC14::work;
0213     switch ( right->type() )
0214     {
0215         case number:
0216             rightType = PIC14::num;
0217             break;
0218 
0219         case variable:
0220             rightType = PIC14::var;
0221             break;
0222 
0223         case working:
0224             rightType = PIC14::work;
0225             break;
0226 
0227         case unset:
0228         case extpin:
0229         case keypad:
0230             qCritical() << Q_FUNC_INFO << "Bad right->type(): " << right->type();
0231     };
0232 
0233     switch(op)
0234     {
0235         case equals:    m_pic->equal( lvalue, rvalue, leftType, rightType ); break;
0236         case notequals: m_pic->notEqual( lvalue, rvalue, leftType, rightType ); break;
0237         case lt:        m_pic->lessThan( lvalue, rvalue, leftType, rightType ); break;
0238         case gt:        m_pic->greaterThan( lvalue, rvalue, leftType, rightType ); break;
0239         case le:        m_pic->lessOrEqual( lvalue, rvalue, leftType, rightType ); break;
0240         case ge:        m_pic->greaterOrEqual( lvalue, rvalue, leftType, rightType ); break;
0241 
0242         case addition:      m_pic->add( lvalue, rvalue, leftType, rightType ); break;
0243         case subtraction:   m_pic->subtract( lvalue, rvalue, leftType, rightType ); break;
0244         case multiplication:    m_pic->mul( lvalue, rvalue, leftType, rightType ); break;
0245         case division:      m_pic->div( lvalue, rvalue, leftType, rightType ); break;
0246 
0247         case bwand: m_pic->bitwise( bwand, lvalue, rvalue, leftType, rightType ); break;
0248         case bwor:  m_pic->bitwise( bwor, lvalue, rvalue, leftType, rightType ); break;
0249         case bwxor: m_pic->bitwise( bwxor, lvalue, rvalue, leftType, rightType ); break;
0250         case bwnot: m_pic->bitwise( bwnot, lvalue, rvalue, leftType, rightType ); break;
0251 
0252         default: break;
0253     }
0254 }
0255 
0256 void Expression::buildTree( const QString & unstrippedExpression, BTreeBase *tree, BTreeNode *node, int level )
0257 {
0258     int firstEnd = 0;
0259     int secondStart = 0;
0260     bool unary = false;
0261     Operation op = noop;
0262     QString expression = stripBrackets( unstrippedExpression );
0263     switch(level)
0264     {
0265         // ==, !=
0266         case 0:
0267         {
0268         int equpos = findSkipBrackets(expression, "==");
0269         int neqpos = findSkipBrackets(expression, "!=");
0270         if( equpos != -1 )
0271         {
0272             op = equals;
0273             firstEnd = equpos;
0274             secondStart = equpos + 2;
0275         }
0276         else if( neqpos != -1 )
0277         {
0278             op = notequals;
0279             firstEnd = neqpos;
0280             secondStart = neqpos + 2;
0281         }
0282         else op = noop;
0283         break;
0284         }
0285 
0286         // <, <=, >=, >
0287         case 1:
0288         {
0289         int ltpos = findSkipBrackets(expression, "<");
0290         int lepos = findSkipBrackets(expression, "<=");
0291         int gepos = findSkipBrackets(expression, ">=");
0292         int gtpos = findSkipBrackets(expression, ">");
0293         // Note: if (for example) "<=" is present, "<" will also be present. This
0294         // means that we have to check for "<=" before "<", etc.
0295         if( lepos != -1 )
0296         {
0297             op = le;
0298             firstEnd = lepos;
0299             secondStart = lepos + 2;
0300         }
0301         else if( gepos != -1 )
0302         {
0303             op = ge;
0304             firstEnd = gepos;
0305             secondStart = gepos + 2;
0306         }
0307         else if( ltpos != -1 )
0308         {
0309             op = lt;
0310             firstEnd = ltpos;
0311             secondStart = ltpos + 1;
0312         }
0313         else if( gtpos != -1 )
0314         {
0315             op = gt;
0316             firstEnd = gtpos;
0317             secondStart = gtpos + 1;
0318         }
0319         else op = noop;
0320         break;
0321         }
0322 
0323         // +,-
0324         case 2:
0325         {
0326         int addpos = findSkipBrackets(expression, '+');
0327         int subpos = findSkipBrackets(expression, '-');
0328         if( subpos != -1 )
0329         {
0330             op = subtraction;
0331             firstEnd = subpos;
0332             secondStart = subpos + 1;
0333         }
0334         else if( addpos != -1 )
0335         {
0336             op = addition;
0337             firstEnd = addpos;
0338             secondStart = addpos + 1;
0339         }
0340         else op = noop;
0341         break;
0342         }
0343 
0344         // *,/
0345         case 3:
0346         {
0347         int mulpos = findSkipBrackets(expression, '*');
0348         int divpos = findSkipBrackets(expression, '/');
0349         if( divpos != -1 )
0350         {
0351             op = division;
0352             firstEnd = divpos;
0353             secondStart = divpos + 1;
0354         }
0355         else if( mulpos != -1 )
0356         {
0357             op = multiplication;
0358             firstEnd = mulpos;
0359             secondStart = mulpos + 1;
0360         }
0361         else op = noop;
0362         break;
0363         }
0364 
0365         // ^
0366         case 4:
0367         {
0368         int exppos = findSkipBrackets(expression, '^');
0369         if( exppos != -1 )
0370         {
0371             op = exponent;
0372             firstEnd = exppos;
0373             secondStart = exppos + 1;
0374         }
0375         else op = noop;
0376         break;
0377         }
0378 
0379         // AND, OR, XOR
0380         case 5:
0381         {
0382         int bwAndPos = findSkipBrackets(expression, " AND ");
0383         int bwOrPos = findSkipBrackets(expression, " OR ");
0384         int bwXorPos = findSkipBrackets(expression, " XOR ");
0385         if( bwAndPos != -1 )
0386         {
0387             op = bwand;
0388             firstEnd = bwAndPos;
0389             secondStart = bwAndPos + 5;
0390         }
0391         else if( bwOrPos != -1 )
0392         {
0393             op = bwor;
0394             firstEnd = bwOrPos;
0395             secondStart = bwOrPos + 4;
0396         }
0397         else if( bwXorPos != -1 )
0398         {
0399             op = bwxor;
0400             firstEnd = bwXorPos;
0401             secondStart = bwXorPos + 5;
0402         }
0403         else op = noop;
0404         break;
0405         }
0406 
0407         // NOT
0408         case 6:
0409         {
0410         int bwNotPos = findSkipBrackets(expression, " NOT ");
0411         if( bwNotPos != -1 )
0412         {
0413             op = bwnot;
0414             unary = true;
0415             firstEnd = bwNotPos; // this line is not needed for unary things/
0416             secondStart = bwNotPos + 5;
0417         }
0418         else op = noop;
0419         break;
0420         }
0421     }
0422 
0423     node->setChildOp(op);
0424 
0425     QString tokens[2];
0426     tokens[0] = expression.left(firstEnd).trimmed();
0427     tokens[1] = expression.mid(secondStart).trimmed();
0428 
0429     if( op != noop )
0430     {
0431         for( int j = 0; j < 2; j++ )
0432         {
0433 
0434             BTreeNode *newNode = new BTreeNode();
0435             tree->addNode( node, newNode, (j == 0) );
0436             // we need to strip any brackets from the sub-expression
0437 
0438             // try each token again at the same level, if they
0439             // don't have any of this level's operators, then the function
0440             // will go to the next level as below.
0441 
0442             // For unary opertaions, e.g NOT, we have no special
0443             // code for nodes with only one child, so we leave the left
0444             // hand child blank and put the rest in the right hand node.
0445             if( unary && j == 0 )
0446             {
0447                 newNode->setValue("");
0448                 newNode->setType(number);
0449             }
0450             else buildTree(tokens[j], tree, newNode, 0 );
0451         }
0452     }
0453     else
0454     {
0455         // if there was no relevant operation i.e. " 3*4 / 6" as opposed to " 3*4 + 6"
0456         // then just pass the node onto the next parsing level.
0457         // unless we are at the lowest level, in which case we have reached a final value.
0458         if( level == 6 ) expressionValue(expression,tree,node);
0459         else
0460         {
0461             buildTree(expression,tree,node,level + 1);
0462         }
0463     }
0464 }
0465 
0466 void Expression::doUnaryOp(Operation op, BTreeNode *node)
0467 {
0468     /* Note that this isn't for unary operations as such,
0469      rather for things that are operations that have no direct children,
0470      e.g. portx.n is high, and functionname(args)*/
0471 
0472     if ( op == pin || op == notpin )
0473         m_pic->Spin( m_pic->toPortPin( node->value() ), (op==notpin) );
0474 
0475     else if ( op == read_keypad )
0476         m_pic->Skeypad( mb->variable( node->value() ) );
0477 }
0478 
0479 void Expression::compileExpression( const QString & expression )
0480 {
0481     // Make a tree to put the expression in.
0482     BTreeBase *tree = new BTreeBase();
0483     BTreeNode *root = new BTreeNode();
0484 
0485     // parse the expression into the tree
0486     buildTree(expression,tree,root,0);
0487     // compile the tree into assembly code
0488     tree->setRoot(root);
0489     tree->pruneTree(tree->root());
0490     traverseTree(tree->root());
0491 
0492     // Note deleting the tree deletes all nodes, so the root
0493     // doesn't need deleting separately.
0494     delete tree;
0495     return;
0496 }
0497 
0498 void Expression::compileConditional( const QString & expression, Code * ifCode, Code * elseCode )
0499 {
0500     if( expression.contains(QRegExp("=>|=<|=!")) )
0501     {
0502         mistake( MicrobeApp::InvalidComparison, expression );
0503         return;
0504     }
0505     if( expression.contains(QRegExp("[^=><!][=][^=]")))
0506     {
0507         mistake( MicrobeApp::InvalidEquals );
0508         return;
0509     }
0510     // Make a tree to put the expression in.
0511     BTreeBase *tree = new BTreeBase();
0512     BTreeNode *root = new BTreeNode();
0513 
0514     // parse the expression into the tree
0515     buildTree(expression,tree,root,0);
0516 
0517     // Modify the tree so it is always at the top level of the form (kwoerpkwoep) == (qwopekqpowekp)
0518     if ( root->childOp() != equals &&
0519             root->childOp() != notequals &&
0520             root->childOp() != gt &&
0521             root->childOp() != lt &&
0522             root->childOp() != ge &&
0523             root->childOp() != le &&
0524             root->childOp() != pin &&
0525             root->childOp() != notpin &&
0526             root->childOp() != read_keypad )
0527     {
0528         BTreeNode *newRoot = new BTreeNode();
0529 
0530         BTreeNode *oneNode = new BTreeNode();
0531         oneNode->setChildOp(noop);
0532         oneNode->setType(number);
0533         oneNode->setValue("1");
0534 
0535         newRoot->setLeft(root);
0536         newRoot->setRight(oneNode);
0537         newRoot->setType(unset);
0538         newRoot->setChildOp(ge);
0539 
0540         tree->setRoot(newRoot);
0541         root = newRoot;
0542     }
0543     // compile the tree into assembly code
0544     tree->setRoot(root);
0545     tree->pruneTree(tree->root(),true);
0546 
0547     // We might have just a constant expression, in which case we can just always do if or else depending
0548     // on whether it is true or false.
0549     if( root->childOp() == noop )
0550     {
0551         if( root->value().toInt() == 0 )
0552             m_pic->mergeCode( elseCode );
0553         else
0554             m_pic->mergeCode( ifCode );
0555         return;
0556     }
0557 
0558     // traverse tree with argument conditionalRoot true
0559     // so that 3 == x gets integrated with code for if, repeat until etc...
0560     m_ifCode = ifCode;
0561     m_elseCode = elseCode;
0562     traverseTree(tree->root(),true);
0563 
0564     // Note deleting the tree deletes all nodes, so the root
0565     // doesn't need deleting separately.
0566     delete tree;
0567 }
0568 
0569 bool Expression::isUnaryOp(Operation op)
0570 {
0571     return op == pin || op == notpin || op == function || op == read_keypad;
0572 }
0573 
0574 
0575 void Expression::mistake( MicrobeApp::MistakeType type, const QString & context )
0576 {
0577     mb->compileError( type, context, m_sourceLine );
0578 }
0579 
0580 int Expression::findSkipBrackets( const QString & expr, char ch, int startPos)
0581 {
0582     bool found = false;
0583     int i = startPos;
0584     int bracketLevel = 0;
0585     while(!found)
0586     {
0587         if(expr[i].toLatin1() == '\'')
0588         {
0589             if( i + 2 < int(expr.length()) )
0590             {
0591                 if( expr[i+2].toLatin1() == '\'' )
0592                 {
0593                  i = i + 2;
0594                  found = true;
0595                 }
0596             }
0597         }
0598 
0599         if(expr[i].toLatin1() == '(') bracketLevel++;
0600         else if(expr[i].toLatin1() == ')') bracketLevel--;
0601 
0602         if( bracketLevel == 0 )
0603         {
0604             if(expr[i].toLatin1() == ch) found = true;
0605             else i++;
0606         }
0607         else i++;
0608 
0609         if( i >= int(expr.length()) )
0610         {
0611             found = true;
0612             i = -1;
0613         }
0614     }
0615     return i;
0616 }
0617 
0618 int Expression::findSkipBrackets( const QString & expr, QString phrase, int startPos)
0619 {
0620     bool found = false;
0621     int i = startPos;
0622     int bracketLevel = 0;
0623     while(!found)
0624     {
0625         if(expr[i].toLatin1() == '\'')
0626         {
0627             if( i + 2 < int(expr.length()) )
0628             {
0629                 if( expr[i+2].toLatin1() == '\'' )
0630                 {
0631                  i = i + 2;
0632                  found = true;
0633                 }
0634             }
0635         }
0636 
0637         if(expr[i].toLatin1() == '(') bracketLevel++;
0638         else if(expr[i].toLatin1() == ')') bracketLevel--;
0639 
0640         if( bracketLevel == 0 )
0641         {
0642             if(expr.mid(i,phrase.length()) == phrase) found = true;
0643             else i++;
0644         }
0645         else i++;
0646 
0647         if( i >= int(expr.length()) )
0648         {
0649             found = true;
0650             i = -1;
0651         }
0652     }
0653     return i;
0654 }
0655 
0656 QString Expression::stripBrackets( QString expression )
0657 {
0658     bool stripping = true;
0659     int bracketLevel = 0;
0660     int i = 0;
0661     expression = expression.trimmed();
0662     while(stripping)
0663     {
0664         if( expression.at(i) == '(' ) bracketLevel++;
0665         else if( expression.at(i) == ')' )
0666         {
0667             if( i == int(expression.length() - 1) && bracketLevel == 1)
0668             {
0669                 expression = expression.mid(1,expression.length() - 2).trimmed();
0670             }
0671             bracketLevel--;
0672         }
0673         if( i == int(expression.length() - 1) && bracketLevel > 0 )
0674         {
0675             mistake( MicrobeApp::MismatchedBrackets, expression );
0676             // Stray brackets might cause the expressionession parser some problems,
0677             // so we just avoid parsing anything altogether
0678             expression = "";
0679             stripping = false;
0680         }
0681         i++;
0682         if( bracketLevel == 0 ) stripping = false;
0683     }
0684     return expression;
0685 }
0686 
0687 void Expression::expressionValue( QString expr, BTreeBase */*tree*/, BTreeNode *node)
0688 {
0689     /* The "end of the line" for the expression parsing, the
0690     expression has been broken down into the fundamental elements of expr.value()=="to"||
0691     variable, number, special etc... so we now just set value and type */
0692 
0693 
0694 
0695     /* Alternatively we might have a function call
0696     e.g. somefunction(3,potatoes,hairstyle + 6)
0697     In which case we need to call back to parseExpr to process the arguments,
0698     saving them on the basic stack then  making the function call.
0699     Of course we also need to mark the terminal node type as a function.
0700     */
0701     expr = expr.trimmed();
0702 
0703     // My intention is so that these error checks are ordered
0704     // so that e.g. for x = 3 it picks up the = rather than the spaces first.
0705 
0706 
0707     expr = mb->alias(expr);
0708     ExprType t = expressionType(expr);
0709 
0710 
0711     // See if it is a single qouted character, e.g. 'A'
0712     if( expr.left(1) == "\'" && expr.right(1) == "\'" )
0713     {
0714         if( expr.length() == 3 ) // fall through to report as unknown variable if not of form 'x'
0715         {
0716             // If so, turn it into a number, and use the ASCII code as the value
0717             t = number;
0718             expr =  QString::number(expr[1].toLatin1());
0719         }
0720     }
0721 
0722     // Check for the most common mistake ever!
0723     if(expr.contains("="))
0724         mistake( MicrobeApp::InvalidEquals );
0725     // Check for reserved keywords
0726     if(expr=="to"||expr=="step"||expr=="then")
0727         mistake( MicrobeApp::ReservedKeyword, expr );
0728 
0729     // Check for empty expressions, or expressions contating spaces
0730     // both indicating a Mistake.
0731     if(expr.isEmpty())
0732         mistake( MicrobeApp::ConsecutiveOperators );
0733     else if(expr.contains(QRegExp("\\s")) && t!= extpin)
0734         mistake( MicrobeApp::MissingOperator );
0735 
0736 //***************modified isValidRegister is included ***********************//
0737 
0738     if( t == variable && !mb->isVariableKnown(expr) && !m_pic->isValidPort( expr ) && !m_pic->isValidTris( expr )&&!m_pic->isValidRegister( expr ) )
0739         mistake( MicrobeApp::UnknownVariable, expr );
0740 
0741 //modification ends
0742 
0743     if ( mb->isVariableKnown(expr) && !mb->variable(expr).isReadable() )
0744         mistake( MicrobeApp::WriteOnlyVariable, expr );
0745 
0746     node->setType(t);
0747 
0748     // Since we currently only implement 8 bit unsigned integers, we should disallow
0749     // anything outside the range [0-255].
0750     if( t == number && !m_bSupressNumberTooBig && (expr.toInt() > 255) )
0751     {
0752         mistake( MicrobeApp::NumberTooBig );
0753     }
0754 
0755     // if there was a pin, we need to decocde it.
0756     // For now and sacrificing syntax error checking
0757     // we just look for the word "is" then "high" or "low".
0758     if( t == extpin )
0759     {
0760         bool NOT;
0761         int i = expr.indexOf("is");
0762         if(i > 0)
0763         {
0764             NOT = expr.contains("low");
0765             if(!expr.contains("high") && !expr.contains("low"))
0766                 mistake( MicrobeApp::HighLowExpected, expr );
0767             expr = expr.left(i-1);
0768         }
0769         else NOT = false;
0770         node->setChildOp(NOT?notpin:pin);
0771     }
0772 
0773     else if ( t == keypad )
0774         node->setChildOp( read_keypad );
0775 
0776     node->setValue(expr);
0777 }
0778 
0779 ExprType Expression::expressionType( const QString & expression )
0780 {
0781     // So we can't handle complex expressions yet anyway,
0782     // let's just decide whether it is a variable or number.
0783 
0784     // Thanks to the convention that variable names must not
0785     // begin with a number this is extremely simple to do!
0786 
0787     /* But now there is a catch, because there can also be
0788     things that have a first character alpha, but are of the form
0789     "portb.3 is high", general syntax: portx.n is <high|low>
0790     additionally, there can be things that are just porta.6, which just return the truth of that port.
0791     In reality it is just:
0792     portx.n is high === portx.n
0793     portx.n is low === !(portx.n)
0794     These types of expression can be identified by the fact
0795     that they should be the only things that contain a '.'
0796     */
0797 
0798     /* Note that at the moment, literalToInt returns -1 if it is
0799     not literal so isLiteral is redundant, but this may change if say
0800     negative numbers are implemented
0801     */
0802 
0803     int value = Parser::literalToInt(expression);
0804     if ( value != -1 )
0805         return number;
0806 
0807     if( expression.contains('.') )
0808         return extpin;
0809 
0810     if ( mb->variable( expression ).type() == Variable::keypadType )
0811         return keypad;
0812 
0813     return variable;
0814 }
0815 
0816 QString Expression::processConstant( const QString & expr, bool * isConstant )
0817 {
0818     bool temp;
0819     if (!isConstant)
0820         isConstant = &temp;
0821 
0822     QString code;
0823 
0824     // Make a tree to put the expression in.
0825     BTreeBase *tree = new BTreeBase();
0826     BTreeNode *root = new BTreeNode();
0827 
0828     // parse the expression into the tree
0829     buildTree(expr,tree,root,0);
0830     // compile the tree into assembly code
0831     tree->setRoot(root);
0832     tree->pruneTree(tree->root());
0833     //code = traverseTree(tree->root());
0834     // Look to see if it is a number
0835     if( root->type() == number )
0836     {
0837         code = root->value();
0838         *isConstant = true;
0839     }
0840     else
0841     {
0842         code = "";
0843         *isConstant = false;
0844     }
0845 
0846     // Note deleting the tree deletes all nodes, so the root
0847     // doesn't need deleting separately.
0848     delete tree;
0849     return code;
0850 }