File indexing completed on 2025-04-20 08:13:13
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 }