parser.cpp
Go to the documentation of this file.
00001 /*
00002         Aseba - an event-based framework for distributed robot control
00003         Copyright (C) 2007--2012:
00004                 Stephane Magnenat <stephane at magnenat dot net>
00005                 (http://stephane.magnenat.net)
00006                 and other contributors, see authors.txt for details
00007         
00008         This program is free software: you can redistribute it and/or modify
00009         it under the terms of the GNU Lesser General Public License as published
00010         by the Free Software Foundation, version 3 of the License.
00011         
00012         This program is distributed in the hope that it will be useful,
00013         but WITHOUT ANY WARRANTY; without even the implied warranty of
00014         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015         GNU Lesser General Public License for more details.
00016         
00017         You should have received a copy of the GNU Lesser General Public License
00018         along with this program. If not, see <http://www.gnu.org/licenses/>.
00019 */
00020 
00021 #include "compiler.h"
00022 #include "tree.h"
00023 #include "../utils/FormatableString.h"
00024 #include <memory>
00025 #include <valarray>
00026 #include <iostream>
00027 #include <cassert>
00028 #include <typeinfo>
00029 
00030 #define IS_ONE_OF(array) (isOneOf<sizeof(array)/sizeof(Token::Type)>(array))
00031 #define EXPECT_ONE_OF(array) (expectOneOf<sizeof(array)/sizeof(Token::Type)>(array))
00032 
00033 #define STRICT          false
00034 
00035 namespace Aseba
00036 {
00038         void Compiler::internalCompilerError() const
00039         {
00040                 throw TranslatableError(tokens.front().pos, ERROR_INTERNAL);
00041         }
00042         
00044         void Compiler::expect(const Token::Type& type) const
00045         {
00046                 if (tokens.front() != type)
00047                         throw TranslatableError(tokens.front().pos,
00048                                 ERROR_EXPECTING)
00049                                         .arg(Token(type).typeName())
00050                                         .arg(tokens.front().typeName());
00051         }
00052         
00054         unsigned Compiler::expectUInt12Literal() const
00055         {
00056                 expect(Token::TOKEN_INT_LITERAL);
00057                 if (tokens.front().iValue < 0 || tokens.front().iValue > 4095)
00058                         throw TranslatableError(tokens.front().pos,
00059                                 ERROR_UINT12_OUT_OF_RANGE)
00060                                         .arg(tokens.front().iValue);
00061                 return tokens.front().iValue;
00062         }
00063         
00065         unsigned Compiler::expectUInt16Literal() const
00066         {
00067                 expect(Token::TOKEN_INT_LITERAL);
00068                 if (tokens.front().iValue < 0 || tokens.front().iValue > 65535)
00069                         throw TranslatableError(tokens.front().pos,
00070                                 ERROR_UINT16_OUT_OF_RANGE)
00071                                         .arg(tokens.front().iValue);
00072                 return tokens.front().iValue;
00073         }
00074         
00076         unsigned Compiler::expectPositiveInt16Literal() const
00077         {
00078                 expect(Token::TOKEN_INT_LITERAL);
00079                 if (tokens.front().iValue < 0 || tokens.front().iValue > 32767)
00080                         throw TranslatableError(tokens.front().pos,
00081                                 ERROR_PINT16_OUT_OF_RANGE)
00082                                         .arg(tokens.front().iValue);
00083                 return tokens.front().iValue;
00084         }
00085         
00087         int Compiler::expectAbsoluteInt16Literal(bool negative) const
00088         {
00089                 expect(Token::TOKEN_INT_LITERAL);
00090                 int limit(32767);
00091                 if (negative)
00092                         limit++;
00093                 if (tokens.front().iValue < 0 || tokens.front().iValue > limit)
00094                         throw TranslatableError(tokens.front().pos,
00095                                 ERROR_INT16_OUT_OF_RANGE)
00096                                         .arg(tokens.front().iValue);
00097                 return tokens.front().iValue;
00098         }
00099         
00101         unsigned Compiler::expectPositiveConstant() const
00102         {
00103                 expect(Token::TOKEN_STRING_LITERAL);
00104                 const std::wstring name = tokens.front().sValue;
00105                 const SourcePos pos = tokens.front().pos;
00106                 const ConstantsMap::const_iterator constIt(findConstant(name, pos));
00107                 
00108                 const int value = constIt->second;
00109                 if (value < 0 || value > 32767)
00110                         throw TranslatableError(tokens.front().pos,
00111                                 ERROR_PCONSTANT_OUT_OF_RANGE)
00112                                         .arg(tokens.front().sValue)
00113                                         .arg(value);
00114                 return value;
00115         }
00116         
00118         int Compiler::expectConstant() const
00119         {
00120                 expect(Token::TOKEN_STRING_LITERAL);
00121                 const std::wstring name = tokens.front().sValue;
00122                 const SourcePos pos = tokens.front().pos;
00123                 const ConstantsMap::const_iterator constIt(findConstant(name, pos));
00124                 
00125                 const int value = constIt->second;
00126                 if (value < -32768 || value > 32767)
00127                         throw TranslatableError(tokens.front().pos,
00128                                 ERROR_CONSTANT_OUT_OF_RANGE)
00129                                         .arg(tokens.front().sValue)
00130                                         .arg(value);
00131                 return value;
00132         }
00133         
00135         unsigned Compiler::expectPositiveInt16LiteralOrConstant() const
00136         {
00137                 if (tokens.front() == Token::TOKEN_INT_LITERAL)
00138                         return expectPositiveInt16Literal();
00139                 else
00140                         return expectPositiveConstant();
00141         }
00142         
00144         int Compiler::expectInt16LiteralOrConstant()
00145         {
00146                 if (tokens.front() == Token::TOKEN_OP_NEG)
00147                 {
00148                         tokens.pop_front();
00149                         return -expectAbsoluteInt16Literal(true);
00150                 }
00151                 else if (tokens.front() == Token::TOKEN_INT_LITERAL)
00152                 {
00153                         return expectAbsoluteInt16Literal(false);
00154                 }
00155                 else
00156                         return expectConstant();
00157         }
00158         
00160         unsigned Compiler::expectGlobalEventId() const
00161         {
00162                 assert(commonDefinitions);
00163                 
00164                 expect(Token::TOKEN_STRING_LITERAL);
00165                 
00166                 const std::wstring & name = tokens.front().sValue;
00167                 const SourcePos pos = tokens.front().pos;
00168                 const EventsMap::const_iterator eventIt(findGlobalEvent(name, pos));
00169                 
00170                 return eventIt->second;
00171         }
00172         
00174         unsigned Compiler::expectAnyEventId() const
00175         {
00176                 assert(targetDescription);
00177                 
00178                 expect(Token::TOKEN_STRING_LITERAL);
00179                 
00180                 const std::wstring & name = tokens.front().sValue;
00181                 const SourcePos pos = tokens.front().pos;
00182                 const EventsMap::const_iterator eventIt(findAnyEvent(name, pos));
00183                 
00184                 return eventIt->second;
00185         }
00186         
00188         std::wstring Compiler::eventName(unsigned eventId) const
00189         {
00190                 // search for global
00191                 if (eventId < commonDefinitions->events.size())
00192                         return commonDefinitions->events[eventId].name;
00193                 
00194                 // then for local
00195                 int localId = ASEBA_EVENT_LOCAL_EVENTS_START - eventId;
00196                 if ((localId >= 0) && (localId < (int)targetDescription->localEvents.size()))
00197                         return targetDescription->localEvents[localId].name;
00198                 
00199                 return L"unknown";
00200         }
00201         
00203         template <int length>
00204         bool Compiler::isOneOf(const Token::Type types[length]) const
00205         {
00206                 for (size_t i = 0; i < length; i++)
00207                 {
00208                         if (tokens.front() == types[i])
00209                                 return true;
00210                 }
00211                 return false;
00212         }
00213         
00215         template <int length>
00216         void Compiler::expectOneOf(const Token::Type types[length]) const
00217         {
00218                 if (!isOneOf<length>(types))
00219                 {
00220                         std::wstring expectedTypes;
00221                         for (size_t i = 0; i < length; i++)
00222                         {
00223                                 expectedTypes += Token(types[i]).typeName();
00224                                 if (i + 1 < length)
00225                                         expectedTypes += L", ";
00226                         }
00227 
00228                         throw TranslatableError(tokens.front().pos, ERROR_EXPECTING_ONE_OF).arg(expectedTypes).arg(tokens.front().typeName());
00229                 }
00230         }
00231 
00232         void Compiler::freeTemporaryMemory()
00233         {
00234                 endVariableIndex = 0;
00235         }
00236 
00237         void Compiler::allocateTemporaryMemory(const SourcePos varPos, const unsigned size, unsigned& varAddr)
00238         {
00239                 // allocate space at the end of the variables' memory
00240                 unsigned endOfMemory = targetDescription->variablesSize - endVariableIndex;
00241                 varAddr = endOfMemory - size;
00242                 endVariableIndex += size;
00243 
00244                 // free space check
00245                 if (freeVariableIndex + endVariableIndex > targetDescription->variablesSize)
00246                         throw TranslatableError(varPos, ERROR_NOT_ENOUGH_TEMP_SPACE);
00247         }
00248 
00249         AssignmentNode* Compiler::allocateTemporaryVariable(const SourcePos varPos, Node* rValue)
00250         {
00251                 static unsigned uid = 0;
00252 
00253                 // allocate the temporary variable
00254                 const unsigned size = rValue->getVectorSize();
00255                 unsigned addr = Node::E_NOVAL;
00256                 allocateTemporaryMemory(varPos, size, addr);
00257 
00258                 // create assignment
00259                 std::auto_ptr<AssignmentNode> assignment(new AssignmentNode(varPos));
00260                 assignment->children.push_back(new MemoryVectorNode(varPos, addr, size, WFormatableString(L"temp%0").arg(uid++)));
00261                 assignment->children.push_back(rValue);
00262                 return assignment.release();
00263         }
00264         
00266         Node* Compiler::parseProgram()
00267         {
00268                 std::auto_ptr<ProgramNode> block(new ProgramNode(tokens.front().pos));
00269                 // parse all vars declarations
00270                 while (tokens.front() == Token::TOKEN_STR_var)
00271                 {
00272                         // we may receive NULL pointers because non initialized variables produce no code
00273                         Node *child = parseVarDef();
00274                         if (child)
00275                                 block->children.push_back(child);
00276                 }
00277                 // parse the rest of the code
00278                 while (tokens.front() != Token::TOKEN_END_OF_STREAM)
00279                 {
00280                         // only var declaration are allowed to return NULL node, so we assert on node
00281                         Node *child = parseStatement();
00282                         assert(child);
00283                         block->children.push_back(child);
00284                 }
00285                 return block.release();
00286         }
00287         
00289         Node* Compiler::parseStatement()
00290         {
00291                 // reset temporary variables
00292                 freeTemporaryMemory();
00293 
00294                 switch (tokens.front())
00295                 {
00296                         case Token::TOKEN_STR_var: throw TranslatableError(tokens.front().pos, ERROR_MISPLACED_VARDEF);
00297                         case Token::TOKEN_STR_onevent: return parseOnEvent();
00298                         case Token::TOKEN_STR_sub: return parseSubDecl();
00299                         default: return parseBlockStatement();
00300                 }
00301         }
00302         
00304         Node* Compiler::parseBlockStatement()
00305         {
00306                 switch (tokens.front())
00307                 {
00308                         case Token::TOKEN_STR_if: return parseIfWhen(false);
00309                         case Token::TOKEN_STR_when: return parseIfWhen(true);
00310                         case Token::TOKEN_STR_for: return parseFor();
00311                         case Token::TOKEN_STR_while: return parseWhile();
00312                         case Token::TOKEN_STR_emit: return parseEmit();
00313                         case Token::TOKEN_STR_call: return parseFunctionCall();
00314                         case Token::TOKEN_STR_callsub: return parseCallSub();
00315                         case Token::TOKEN_STR_return: return parseReturn();
00316                         default: return parseAssignment();
00317                 }
00318         }
00319         
00321         Node* Compiler::parseReturn()
00322         {
00323                 SourcePos pos = tokens.front().pos;
00324                 tokens.pop_front();
00325                 return new ReturnNode(pos);
00326         }
00327         
00329         Node* Compiler::parseVarDef()
00330         {
00331                 tokens.pop_front();
00332                 
00333                 // check for string literal
00334                 if (tokens.front() != Token::TOKEN_STRING_LITERAL)
00335                         throw TranslatableError(tokens.front().pos,
00336                                 ERROR_EXPECTING_IDENTIFIER).arg(tokens.front().toWString());
00337                 
00338                 // save variable
00339                 std::wstring varName = tokens.front().sValue;
00340                 SourcePos varPos = tokens.front().pos;
00341                 unsigned varSize = Node::E_NOVAL;
00342                 unsigned varAddr = freeVariableIndex;
00343                 
00344                 tokens.pop_front();
00345                 
00346                 // optional array
00347                 varSize = parseVariableDefSize();
00348                 
00349                 // check if variable exists
00350                 if (variablesMap.find(varName) != variablesMap.end())
00351                         throw TranslatableError(varPos, ERROR_VAR_ALREADY_DEFINED).arg(varName);
00352 
00353                 // check if variable conflicts with a constant
00354                 if(commonDefinitions->constants.contains(varName))
00355                         throw TranslatableError(varPos, ERROR_VAR_CONST_COLLISION).arg(varName);
00356                 
00357                 // optional assignation
00358                 std::auto_ptr<MemoryVectorNode> me(new MemoryVectorNode(varPos, varAddr, varSize, varName));
00359                 std::auto_ptr<Node> temp;
00360                 temp.reset(parseVarDefInit(me.get()));
00361                 if (temp.get())
00362                 {
00363                         // valid
00364                         varSize = me->getVectorSize();
00365                         me.release();
00366                 }
00367 
00368                 // sanity check for array
00369                 if (varSize == 0 || varSize == Node::E_NOVAL)
00370                         throw TranslatableError(varPos, ERROR_UNDEFINED_SIZE).arg(varName);
00371 
00372                 // save variable
00373                 variablesMap[varName] = std::make_pair(varAddr, varSize);
00374                 freeVariableIndex += varSize;
00375 
00376                 // check space
00377                 if (freeVariableIndex > targetDescription->variablesSize)
00378                         throw TranslatableError(varPos, ERROR_NOT_ENOUGH_SPACE);
00379 
00380                 if (temp.get())
00381                         return temp.release();
00382                 else
00383                         return NULL;
00384         }
00385 
00386         AssignmentNode *Compiler::parseVarDefInit(MemoryVectorNode* lValue)
00387         {
00388                 if (tokens.front() == Token::TOKEN_ASSIGN)
00389                 {
00390                         SourcePos pos = tokens.front().pos;
00391                         tokens.pop_front();
00392 
00393                         // try old style initialization 1,2,3
00394                         std::auto_ptr<Node> rValue(parseTupleVector(true));
00395                         if (rValue.get() == NULL)
00396                         {
00397                                 // no -> other type of initialization
00398                                 rValue.reset(parseBinaryOrExpression());
00399                         }
00400 
00401                         if (lValue->getVectorSize() == Node::E_NOVAL)
00402                         {
00403                                 // infere the variable's size based on the initilization
00404                                 lValue->arraySize = rValue->getVectorSize();
00405                         }
00406 
00407                         std::auto_ptr<AssignmentNode> assign(new AssignmentNode(pos));
00408                         assign->children.push_back(lValue);
00409                         assign->children.push_back(rValue.release());
00410                         return assign.release();
00411                 }
00412 
00413                 return NULL;
00414         }
00415         
00416 
00418         Node* Compiler::parseAssignment()
00419         {
00420                 expect(Token::TOKEN_STRING_LITERAL);
00421                 
00422                 static const Token::Type compoundBinaryAssignment[] = { Token::TOKEN_OP_ADD_EQUAL, Token::TOKEN_OP_NEG_EQUAL,
00423                                                            Token::TOKEN_OP_MULT_EQUAL, Token::TOKEN_OP_DIV_EQUAL, Token::TOKEN_OP_MOD_EQUAL,
00424                                                            Token::TOKEN_OP_BIT_AND_EQUAL, Token::TOKEN_OP_BIT_OR_EQUAL, Token::TOKEN_OP_BIT_XOR_EQUAL,
00425                                                            Token::TOKEN_OP_SHIFT_LEFT_EQUAL, Token::TOKEN_OP_SHIFT_RIGHT_EQUAL};
00426 
00427                 // parse left value
00428                 std::auto_ptr<Node> lValue(parseBinaryOrExpression());
00429                 
00430                 // parse right value
00431                 if (tokens.front() == Token::TOKEN_ASSIGN)
00432                 {
00433                         std::auto_ptr<AssignmentNode> assignment(new AssignmentNode(tokens.front().pos));
00434                         tokens.pop_front();
00435                         
00436                         assignment->children.push_back(lValue.release());
00437                         assignment->children.push_back(parseBinaryOrExpression());
00438                         return assignment.release();
00439                 }
00440                 else if ((tokens.front() == Token::TOKEN_OP_PLUS_PLUS) || (tokens.front() == Token::TOKEN_OP_MINUS_MINUS))
00441                 {
00442                         SourcePos pos = tokens.front().pos;
00443                         Compiler::Token op = tokens.front();
00444                         tokens.pop_front();
00445 
00446                         std::auto_ptr<UnaryArithmeticAssignmentNode> assignment(
00447                                                 new UnaryArithmeticAssignmentNode(
00448                                                         pos,
00449                                                         op,
00450                                                         lValue.release()));
00451 
00452                         return assignment.release();
00453                 }
00454                 else if (IS_ONE_OF(compoundBinaryAssignment))
00455                 {
00456                         SourcePos pos = tokens.front().pos;
00457                         Compiler::Token op = tokens.front();
00458                         tokens.pop_front();
00459 
00460                         std::auto_ptr<ArithmeticAssignmentNode> assignment(
00461                                                 ArithmeticAssignmentNode::fromArithmeticAssignmentToken(
00462                                                         pos,
00463                                                         op,
00464                                                         lValue.release(),
00465                                                         parseBinaryOrExpression()));
00466 
00467                         return assignment.release();
00468                 }
00469                 else
00470                         throw TranslatableError(tokens.front().pos, ERROR_EXPECTING_ASSIGNMENT).arg(tokens.front().toWString());
00471                 
00472                 return NULL;
00473         }
00474 
00476         Node* Compiler::parseIfWhen(bool edgeSensitive)
00477         {
00478                 const Token::Type elseEndTypes[] = { Token::TOKEN_STR_else, Token::TOKEN_STR_elseif, Token::TOKEN_STR_end };
00479                 
00480                 std::auto_ptr<IfWhenNode> ifNode(new IfWhenNode(tokens.front().pos));
00481                 
00482                 // eat "if" / "when"
00483                 ifNode->edgeSensitive = edgeSensitive;
00484                 tokens.pop_front();
00485                 
00486                 // condition
00487                 ifNode->children.push_back(parseOr());
00488                 
00489                 // then keyword
00490                 if (edgeSensitive)
00491                         expect(Token::TOKEN_STR_do);
00492                 else
00493                         expect(Token::TOKEN_STR_then);
00494                 tokens.pop_front();
00495                 
00496                 // parse true condition
00497                 ifNode->children.push_back(new BlockNode(tokens.front().pos));
00498                 while (!IS_ONE_OF(elseEndTypes))
00499                         ifNode->children[1]->children.push_back(parseBlockStatement());
00500                 
00501                 /*// parse false condition (only for if)
00502                 if (!edgeSensitive && (tokens.front() == Token::TOKEN_STR_else))
00503                 {
00504                         tokens.pop_front();
00505                         
00506                         ifNode->children.push_back(new BlockNode(tokens.front().pos));
00507                         while (tokens.front() != Token::TOKEN_STR_end)
00508                                 ifNode->children[2]->children.push_back(parseBlockStatement());
00509                 }*/
00510                 
00511                 // parse false condition (only for if)
00512                 if (!edgeSensitive)
00513                 {
00514                         if (tokens.front() == Token::TOKEN_STR_else)
00515                         {
00516                                 tokens.pop_front();
00517                                 
00518                                 ifNode->children.push_back(new BlockNode(tokens.front().pos));
00519                                 while (tokens.front() != Token::TOKEN_STR_end)
00520                                         ifNode->children[2]->children.push_back(parseBlockStatement());
00521                         }
00522                         // if elseif, queue new if directly after and return before parsing trailing end
00523                         if (tokens.front() == Token::TOKEN_STR_elseif)
00524                         {
00525                                 ifNode->children.push_back(parseIfWhen(false));
00526                                 return ifNode.release();
00527                         }
00528                 }
00529                 
00530                 // end keyword
00531                 ifNode->endLine = tokens.front().pos.row;
00532                 expect(Token::TOKEN_STR_end);
00533                 tokens.pop_front();
00534                 
00535                 return ifNode.release();
00536         }
00537         
00539         Node* Compiler::parseFor()
00540         {
00541                 // eat "for"
00542                 SourcePos whilePos = tokens.front().pos;
00543                 tokens.pop_front();
00544                 
00545                 // variable
00546                 std::auto_ptr<MemoryVectorNode> variable(parseVariable());
00547                 MemoryVectorNode* variableRef = variable.get();         // used to create copies
00548                 SourcePos varPos = variable->sourcePos;
00549                 
00550                 // in keyword
00551                 expect(Token::TOKEN_STR_in);
00552                 tokens.pop_front();
00553                 
00554                 // range start index
00555                 int rangeStartIndex = expectInt16LiteralOrConstant();
00556                 SourcePos rangeStartIndexPos = tokens.front().pos;
00557                 tokens.pop_front();
00558                 
00559                 // : keyword
00560                 expect(Token::TOKEN_COLON);
00561                 tokens.pop_front();
00562                 
00563                 // range end index
00564                 int rangeEndIndex = expectInt16LiteralOrConstant();
00565                 SourcePos rangeEndIndexPos = tokens.front().pos;
00566                 tokens.pop_front();
00567                 
00568                 // check for step
00569                 int step = 1;
00570                 if (tokens.front() == Token::TOKEN_STR_step)
00571                 {
00572                         tokens.pop_front();
00573                         step = expectInt16LiteralOrConstant();
00574                         if (step == 0)
00575                                 throw TranslatableError(tokens.front().pos, ERROR_FOR_NULL_STEPS);
00576                         tokens.pop_front();
00577                 }
00578                 
00579                 // check conditions
00580                 if (step > 0)
00581                 {
00582                         if (rangeStartIndex > rangeEndIndex)
00583                                 throw TranslatableError(rangeStartIndexPos, ERROR_FOR_START_HIGHER_THAN_END);
00584                 }
00585                 else
00586                 {
00587                         if (rangeStartIndex < rangeEndIndex)
00588                                 throw TranslatableError(rangeStartIndexPos, ERROR_FOR_START_LOWER_THAN_END);
00589                 }
00590                 
00591                 // do keyword
00592                 expect(Token::TOKEN_STR_do);
00593                 tokens.pop_front();
00594                 
00595                 // create enclosing block and initial variable state
00596                 std::auto_ptr<BlockNode> blockNode(new BlockNode(whilePos));
00597                 std::auto_ptr<AssignmentNode> assignment(new AssignmentNode(rangeStartIndexPos));
00598                 assignment->children.push_back(variable.release());
00599                 assignment->children.push_back(new TupleVectorNode(rangeStartIndexPos, rangeStartIndex));
00600                 blockNode->children.push_back(assignment.release());
00601                 
00602                 // create while and condition
00603                 WhileNode* whileNode = new WhileNode(whilePos);
00604                 blockNode->children.push_back(whileNode);
00605                 BinaryArithmeticNode* comparisonNode = new BinaryArithmeticNode(whilePos);
00606                 comparisonNode->children.push_back(variableRef->deepCopy());
00607                 if (rangeStartIndex <= rangeEndIndex)
00608                         comparisonNode->op = ASEBA_OP_SMALLER_EQUAL_THAN;
00609                 else
00610                         comparisonNode->op = ASEBA_OP_BIGGER_EQUAL_THAN;
00611                 comparisonNode->children.push_back(new TupleVectorNode(rangeEndIndexPos, rangeEndIndex));
00612                 whileNode->children.push_back(comparisonNode);
00613                 
00614                 // block and end keyword
00615                 whileNode->children.push_back(new BlockNode(tokens.front().pos));
00616                 while (tokens.front() != Token::TOKEN_STR_end)
00617                         whileNode->children[1]->children.push_back(parseBlockStatement());
00618                 
00619                 // increment variable
00620                 AssignmentNode* assignmentNode = new AssignmentNode(varPos);
00621                 whileNode->children[1]->children.push_back(assignmentNode);
00622                 assignmentNode->children.push_back(variableRef->deepCopy());
00623                 assignmentNode->children.push_back(new BinaryArithmeticNode(varPos, ASEBA_OP_ADD, variableRef->deepCopy(), new TupleVectorNode(varPos, step)));
00624                 
00625                 tokens.pop_front();
00626                 
00627                 return blockNode.release();
00628         }
00629         
00631         Node* Compiler::parseWhile()
00632         {
00633                 std::auto_ptr<WhileNode> whileNode(new WhileNode(tokens.front().pos));
00634                 
00635                 // eat "while"
00636                 tokens.pop_front();
00637                 
00638                 // condition
00639                 whileNode->children.push_back(parseOr());
00640                 
00641                 // do keyword
00642                 expect(Token::TOKEN_STR_do);
00643                 tokens.pop_front();
00644                 
00645                 // block and end keyword
00646                 whileNode->children.push_back(new BlockNode(tokens.front().pos));
00647                 while (tokens.front() != Token::TOKEN_STR_end)
00648                         whileNode->children[1]->children.push_back(parseBlockStatement());
00649                 
00650                 tokens.pop_front();
00651                 
00652                 return whileNode.release();
00653         }
00654         
00656         Node* Compiler::parseOnEvent()
00657         {
00658                 SourcePos pos = tokens.front().pos;
00659                 tokens.pop_front();
00660                 
00661                 const unsigned eventId = expectAnyEventId();
00662                 if (implementedEvents.find(eventId) != implementedEvents.end())
00663                         throw TranslatableError(tokens.front().pos, ERROR_EVENT_ALREADY_IMPL).arg(eventName(eventId));
00664                 implementedEvents.insert(eventId);
00665                 
00666                 tokens.pop_front();
00667                 
00668                 return new EventDeclNode(pos, eventId);
00669         }
00670         
00672         Node* Compiler::parseEmit()
00673         {
00674                 SourcePos pos = tokens.front().pos;
00675                 tokens.pop_front();
00676                 
00677                 std::auto_ptr<EmitNode> emitNode(new EmitNode(pos));
00678                 
00679                 // event id
00680                 emitNode->eventId = expectGlobalEventId();
00681                 tokens.pop_front();
00682                 
00683                 // event argument
00684                 unsigned eventSize = commonDefinitions->events[emitNode->eventId].value;
00685                 if (eventSize > 0)
00686                 {
00687                         std::auto_ptr<Node> preNode(parseBinaryOrExpression());
00688 
00689                         // allocate memory?
00690                         if (!dynamic_cast<MemoryVectorNode*>(preNode.get()) || preNode->getVectorAddr() == Node::E_NOVAL)
00691                         {
00692                                 preNode.reset(allocateTemporaryVariable(pos, preNode.release()));
00693                         }
00694 
00695                         //allocateTemporaryVariable(pos)
00696                         emitNode->arrayAddr = preNode->getVectorAddr();
00697                         emitNode->arraySize = preNode->getVectorSize();
00698                         emitNode->children.push_back(preNode.release());
00699 
00700                         if (emitNode->arraySize != eventSize)
00701                                 throw TranslatableError(pos, ERROR_EVENT_WRONG_ARG_SIZE).arg(commonDefinitions->events[emitNode->eventId].name).arg(eventSize).arg(emitNode->arraySize);
00702                 }
00703                 else
00704                 {
00705                         emitNode->arrayAddr = 0;
00706                         emitNode->arraySize = 0;
00707                 }
00708                 
00709                 return emitNode.release();
00710         }
00711         
00713         Node* Compiler::parseSubDecl()
00714         {
00715                 const SourcePos pos = tokens.front().pos;
00716                 tokens.pop_front();
00717                 
00718                 expect(Token::TOKEN_STRING_LITERAL);
00719                 
00720                 const std::wstring& name = tokens.front().sValue;
00721                 const SubroutineReverseTable::const_iterator it = subroutineReverseTable.find(name);
00722                 if (it != subroutineReverseTable.end())
00723                         throw TranslatableError(tokens.front().pos, ERROR_SUBROUTINE_ALREADY_DEF).arg(name);
00724                 
00725                 const unsigned subroutineId = subroutineTable.size();
00726                 subroutineTable.push_back(SubroutineDescriptor(name, 0, pos.row));
00727                 subroutineReverseTable[name] = subroutineId;
00728                 
00729                 tokens.pop_front();
00730                 
00731                 return new SubDeclNode(pos, subroutineId);
00732         }
00733         
00735         Node* Compiler::parseCallSub()
00736         {
00737                 const SourcePos pos = tokens.front().pos;
00738                 tokens.pop_front();
00739                 
00740                 expect(Token::TOKEN_STRING_LITERAL);
00741                 
00742                 const std::wstring& name = tokens.front().sValue;
00743                 const SubroutineReverseTable::const_iterator it(findSubroutine(name, pos));
00744                 
00745                 tokens.pop_front();
00746                 
00747                 return new CallSubNode(pos, it->second);
00748         }
00749         
00751         Node* Compiler::parseOr()
00752         {
00753                 std::auto_ptr<Node> node(parseAnd());
00754                 
00755                 while (tokens.front() == Token::TOKEN_OP_OR)
00756                 {
00757                         SourcePos pos = tokens.front().pos;
00758                         tokens.pop_front();
00759                         Node *subExpression = parseAnd();
00760                         node.reset(new BinaryArithmeticNode(pos, ASEBA_OP_OR, node.release(), subExpression));
00761                 }
00762                 
00763                 return node.release();
00764         }
00765         
00767         Node* Compiler::parseAnd()
00768         {
00769                 std::auto_ptr<Node> node(parseNot());
00770                 
00771                 while (tokens.front() == Token::TOKEN_OP_AND)
00772                 {
00773                         SourcePos pos = tokens.front().pos;
00774                         tokens.pop_front();
00775                         Node *subExpression = parseNot();
00776                         node.reset(new BinaryArithmeticNode(pos, ASEBA_OP_AND, node.release(), subExpression));
00777                 }
00778                 
00779                 return node.release();
00780         }
00781         
00783         Node* Compiler::parseNot()
00784         {
00785                 SourcePos pos = tokens.front().pos;
00786                 
00787                 // eat all trailing not
00788                 bool odd = false;
00789                 while (tokens.front() == Token::TOKEN_OP_NOT)
00790                 {
00791                         odd = !odd;
00792                         tokens.pop_front();
00793                 }
00794                 
00795                 if (odd)
00796                         return new UnaryArithmeticNode(pos, ASEBA_UNARY_OP_NOT, parseCondition());
00797                 else
00798                         return parseCondition();
00799                 /*
00800                 
00801                 std::auto_ptr<BinaryArithmeticNode> expression(parseCondition());
00802                 
00803                 // recurse on parenthesis
00804                 if (tokens.front() == Token::TOKEN_PAR_OPEN)
00805                 {
00806                         tokens.pop_front();
00807                         
00808                         expression.reset(parseOr());
00809                         
00810                         expect(Token::TOKEN_PAR_CLOSE);
00811                         tokens.pop_front();
00812                 }
00813                 else
00814                 {
00815                         expression.reset(parseCondition());
00816                 }
00817                 // apply de Morgan to remove the not
00818                 if (odd)
00819                         expression->deMorganNotRemoval();
00820                 
00821                 return expression.release();
00822                 */
00823         }
00824         
00826         Node* Compiler::parseCondition()
00827         {
00828                 /*const Token::Type conditionTypes[] = { Token::TOKEN_OP_EQUAL, Token::TOKEN_OP_NOT_EQUAL, Token::TOKEN_OP_BIGGER, Token::TOKEN_OP_BIGGER_EQUAL, Token::TOKEN_OP_SMALLER, Token::TOKEN_OP_SMALLER_EQUAL };
00829                 
00830                 std::auto_ptr<Node> leftExprNode(parseBinaryOrExpression());
00831                 
00832                 EXPECT_ONE_OF(conditionTypes);
00833                 
00834                 Token::Type op = tokens.front();
00835                 SourcePos pos = tokens.front().pos;
00836                 tokens.pop_front();
00837                 Node *rightExprNode = parseBinaryOrExpression();
00838                 return BinaryArithmeticNode::fromComparison(pos, op, leftExprNode.release(), rightExprNode);*/
00839                 
00840                 const Token::Type conditionTypes[] = { Token::TOKEN_OP_EQUAL, Token::TOKEN_OP_NOT_EQUAL, Token::TOKEN_OP_BIGGER, Token::TOKEN_OP_BIGGER_EQUAL, Token::TOKEN_OP_SMALLER, Token::TOKEN_OP_SMALLER_EQUAL };
00841                 
00842                 std::auto_ptr<Node> node(parseBinaryOrExpression());
00843                 
00844                 while (IS_ONE_OF(conditionTypes))
00845                 {
00846                         Token::Type op = tokens.front();
00847                         SourcePos pos = tokens.front().pos;
00848                         tokens.pop_front();
00849                         Node *subExpression = parseBinaryOrExpression();
00850                         node.reset(BinaryArithmeticNode::fromComparison(pos, op, node.release(), subExpression));
00851                 }
00852                 
00853                 return node.release();
00854         }
00855         
00857         Node *Compiler::parseBinaryOrExpression()
00858         {
00859                 std::auto_ptr<Node> node(parseBinaryXorExpression());
00860                 
00861                 while (tokens.front() == Token::TOKEN_OP_BIT_OR)
00862                 {
00863                         SourcePos pos = tokens.front().pos;
00864                         tokens.pop_front();
00865                         Node *subExpression = parseBinaryXorExpression();
00866                         node.reset(new BinaryArithmeticNode(pos, ASEBA_OP_BIT_OR, node.release(), subExpression));
00867                 }
00868                 
00869                 return node.release();
00870         }
00871         
00873         Node *Compiler::parseBinaryXorExpression()
00874         {
00875                 std::auto_ptr<Node> node(parseBinaryAndExpression());
00876                 
00877                 while (tokens.front() == Token::TOKEN_OP_BIT_XOR)
00878                 {
00879                         SourcePos pos = tokens.front().pos;
00880                         tokens.pop_front();
00881                         Node *subExpression = parseBinaryAndExpression();
00882                         node.reset(new BinaryArithmeticNode(pos, ASEBA_OP_BIT_XOR, node.release(), subExpression));
00883                 }
00884                 
00885                 return node.release();
00886         }
00887         
00889         Node *Compiler::parseBinaryAndExpression()
00890         {
00891                 std::auto_ptr<Node> node(parseShiftExpression());
00892                 
00893                 while (tokens.front() == Token::TOKEN_OP_BIT_AND)
00894                 {
00895                         SourcePos pos = tokens.front().pos;
00896                         tokens.pop_front();
00897                         Node *subExpression = parseShiftExpression();
00898                         node.reset(new BinaryArithmeticNode(pos, ASEBA_OP_BIT_AND, node.release(), subExpression));
00899                 }
00900                 
00901                 return node.release();
00902         }
00903         
00905         Node *Compiler::parseShiftExpression()
00906         {
00907                 const Token::Type opTypes[] = { Token::TOKEN_OP_SHIFT_LEFT, Token::TOKEN_OP_SHIFT_RIGHT };
00908                 
00909                 std::auto_ptr<Node> node(parseAddExpression());
00910                 
00911                 while (IS_ONE_OF(opTypes))
00912                 {
00913                         Token::Type op = tokens.front();
00914                         SourcePos pos = tokens.front().pos;
00915                         tokens.pop_front();
00916                         Node *subExpression = parseAddExpression();
00917                         node.reset(BinaryArithmeticNode::fromShiftExpression(pos, op, node.release(), subExpression));
00918                 }
00919                 
00920                 return node.release();
00921         }
00922         
00924         Node *Compiler::parseAddExpression()
00925         {
00926                 const Token::Type opTypes[] = { Token::TOKEN_OP_ADD, Token::TOKEN_OP_NEG };
00927                 
00928                 std::auto_ptr<Node> node(parseMultExpression());
00929                 
00930                 while (IS_ONE_OF(opTypes))
00931                 {
00932                         Token::Type op = tokens.front();
00933                         SourcePos pos = tokens.front().pos;
00934                         tokens.pop_front();
00935                         Node *subExpression = parseMultExpression();
00936                         node.reset(BinaryArithmeticNode::fromAddExpression(pos, op, node.release(), subExpression));
00937                 }
00938                 
00939                 return node.release();
00940         }
00941         
00943         Node *Compiler::parseMultExpression()
00944         {
00945                 const Token::Type opTypes[] = { Token::TOKEN_OP_MULT, Token::TOKEN_OP_DIV, Token::TOKEN_OP_MOD };
00946                 
00947                 std::auto_ptr<Node> node(parseUnaryExpression());
00948                 
00949                 while (IS_ONE_OF(opTypes))
00950                 {
00951                         Token::Type op = tokens.front();
00952                         SourcePos pos = tokens.front().pos;
00953                         tokens.pop_front();
00954                         Node *subExpression = parseUnaryExpression();
00955                         node.reset(BinaryArithmeticNode::fromMultExpression(pos, op, node.release(), subExpression));
00956                 }
00957                 
00958                 return node.release();
00959         }
00960         
00962         Node *Compiler::parseUnaryExpression()
00963         {
00964                 const Token::Type acceptableTypes[] = { Token::TOKEN_PAR_OPEN, Token::TOKEN_BRACKET_OPEN, Token::TOKEN_OP_NEG, Token::TOKEN_OP_BIT_NOT, Token::TOKEN_STR_abs, Token::TOKEN_STRING_LITERAL, Token::TOKEN_INT_LITERAL };
00965                 
00966                 EXPECT_ONE_OF(acceptableTypes);
00967                 SourcePos pos = tokens.front().pos;
00968                 
00969                 switch (tokens.front())
00970                 {
00971                         case Token::TOKEN_PAR_OPEN:
00972                         {
00973                                 tokens.pop_front();
00974                                 
00975                                 std::auto_ptr<Node> expression(parseOr());
00976                                 
00977                                 expect(Token::TOKEN_PAR_CLOSE);
00978                                 tokens.pop_front();
00979                                 
00980                                 return expression.release();
00981                         }
00982 
00983                         case Token::TOKEN_BRACKET_OPEN:
00984                         {
00985                                 return parseTupleVector();
00986                         }
00987                         
00988                         case Token::TOKEN_OP_NEG:
00989                         {
00990                                 tokens.pop_front();
00991                                 
00992                                 return new UnaryArithmeticNode(pos, ASEBA_UNARY_OP_SUB, parseUnaryExpression());
00993                         }
00994                         
00995                         case Token::TOKEN_OP_BIT_NOT:
00996                         {
00997                                 tokens.pop_front();
00998                                 
00999                                 return new UnaryArithmeticNode(pos, ASEBA_UNARY_OP_BIT_NOT, parseUnaryExpression());
01000                         };
01001                         
01002                         case Token::TOKEN_STR_abs:
01003                         {
01004                                 tokens.pop_front();
01005                                 
01006                                 return new UnaryArithmeticNode(pos, ASEBA_UNARY_OP_ABS, parseUnaryExpression());
01007                         }
01008                         
01009                         case Token::TOKEN_INT_LITERAL:
01010                         {
01011                                 // immediate
01012                                 std::auto_ptr<TupleVectorNode> arrayCtor(new TupleVectorNode(pos, expectUInt16Literal()));
01013                                 tokens.pop_front();
01014                                 return arrayCtor.release();
01015                         }
01016                         
01017                         case Token::TOKEN_STRING_LITERAL:
01018                         {
01019                                 return parseConstantAndVariable();
01020                         }
01021                         
01022                         default: internalCompilerError(); return NULL;
01023                 }
01024         }
01025 
01027         TupleVectorNode* Compiler::parseTupleVector(bool compatibility)
01028         {
01029                 if (!compatibility)
01030                 {
01031                         expect(Token::TOKEN_BRACKET_OPEN);
01032                         tokens.pop_front();
01033                 }
01034                 else
01035                 {
01036                         // check if 2nd token is a comma
01037                         if ( !(
01038                                 (tokens.size() >= 2 && tokens[1] == Token::TOKEN_COMMA) ||
01039                                 (tokens.size() >= 3 && tokens[0] == Token::TOKEN_OP_NEG && tokens[2] == Token::TOKEN_COMMA)
01040                                 )
01041                         )
01042                         {
01043                                 // no
01044                                 return NULL;
01045                         }
01046                 }
01047 
01048                 SourcePos varPos = tokens.front().pos;
01049                 std::auto_ptr<TupleVectorNode> arrayCtor(new TupleVectorNode(varPos));
01050 
01051                 do
01052                 {
01053                         if (tokens.front() == Token::TOKEN_BRACKET_OPEN)
01054                         {
01055                                 // nested tuples
01056                                 arrayCtor->children.push_back(parseTupleVector());
01057                         }
01058                         else
01059                         {
01060                                 arrayCtor->children.push_back(parseBinaryOrExpression());
01061                         }
01062 
01063                         if (tokens.front() != Token::TOKEN_COMMA)
01064                                 break;
01065                         else
01066                                 tokens.pop_front();
01067                 }
01068                 while (1);
01069 
01070                 if (!compatibility)
01071                 {
01072                         expect(Token::TOKEN_BRACKET_CLOSE);
01073                         tokens.pop_front();
01074                 }
01075 
01076                 return arrayCtor.release();
01077         }
01078 
01079         Node* Compiler::parseConstantAndVariable()
01080         {
01081                 expect(Token::TOKEN_STRING_LITERAL);
01082                 std::wstring varName = tokens.front().sValue;
01083                 if (constantExists(varName))
01084                 {
01085                         std::auto_ptr<TupleVectorNode> arrayCtor(new TupleVectorNode(tokens.front().pos));
01086                         arrayCtor->addImmediateValue(expectConstant());
01087                         tokens.pop_front();
01088                         return arrayCtor.release();
01089                 }
01090                 else
01091                 {
01092                         return parseVariable();
01093                 }
01094         }
01095 
01096         MemoryVectorNode* Compiler::parseVariable()
01097         {
01098                 expect(Token::TOKEN_STRING_LITERAL);
01099                 std::wstring varName = tokens.front().sValue;
01100                 SourcePos varPos = tokens.front().pos;
01101                 VariablesMap::const_iterator varIt(findVariable(varName, varPos));
01102 
01103                 std::auto_ptr<MemoryVectorNode> vector(
01104                                         new MemoryVectorNode(
01105                                                 varPos,
01106                                                 varIt->second.first,
01107                                                 varIt->second.second,
01108                                                 varName));
01109 
01110                 // check if it is a const array access
01111                 tokens.pop_front();
01112                 if (tokens.front() == Token::TOKEN_BRACKET_OPEN)
01113                 {
01114                         SourcePos pos = tokens.front().pos;
01115                         tokens.pop_front();
01116 
01117                         int start;
01118                         std::auto_ptr<Node> startIndex(tryParsingConstantExpression(pos, start));
01119 
01120                         if (startIndex.get() == NULL)
01121                         {
01122                                 // constant index
01123                                 std::auto_ptr<TupleVectorNode> index(new TupleVectorNode(pos));
01124                                 index->addImmediateValue(start);
01125 
01126                                 // do we have array subscript?
01127                                 if (tokens.front() == Token::TOKEN_COLON)
01128                                 {
01129                                         pos = tokens.front().pos;
01130                                         tokens.pop_front();
01131 
01132                                         int end;
01133                                         std::auto_ptr<Node> endIndex(tryParsingConstantExpression(pos, end));
01134 
01135                                         if (endIndex.get() != NULL)
01136                                                 throw TranslatableError(pos, ERROR_INDEX_EXPECTING_CONSTANT);
01137 
01138                                         // check if second index is within bounds
01139                                         if (end < start)
01140                                                 throw TranslatableError(tokens.front().pos, ERROR_INDEX_WRONG_END);
01141 
01142                                         index->addImmediateValue(end);
01143                                 }
01144 
01145                                 vector->children.push_back(index.release());
01146                         }
01147                         else
01148                         {
01149                                 // general expression as index
01150                                 vector->children.push_back(startIndex.release());
01151                         }
01152 
01153                         expect(Token::TOKEN_BRACKET_CLOSE);
01154                         tokens.pop_front();
01155                 }
01156 
01157                 return vector.release();
01158         }
01159 
01160         unsigned Compiler::parseVariableDefSize()
01161         {
01162                 unsigned result = 0;
01163 
01164                 if (tokens.front() == Token::TOKEN_BRACKET_OPEN)
01165                 {
01166                         SourcePos pos = tokens.front().pos;
01167                         tokens.pop_front();
01168 
01169                         if (tokens.front() == Token::TOKEN_BRACKET_CLOSE)
01170                         {
01171                                 result = Node::E_NOVAL;
01172                         }
01173                         else
01174                         {
01175                                 result = expectConstantExpression(pos, parseBinaryOrExpression());
01176 
01177                                 if (result < 0)
01178                                         // what??
01179                                         throw TranslatableError(pos, ERROR_SIZE_IS_NEGATIVE).arg(result);
01180                                 else if (result == 0)
01181                                         throw TranslatableError(pos, ERROR_SIZE_IS_NULL);
01182 
01183                                 expect(Token::TOKEN_BRACKET_CLOSE);
01184                         }
01185                         tokens.pop_front();
01186                 }
01187                 else
01188                         // not an array
01189                         result = 1;
01190 
01191                 return result;
01192         }
01193 
01197         Node* Compiler::tryParsingConstantExpression(SourcePos pos, int& constantResult)
01198         {
01199                 std::auto_ptr<Node> tree(parseBinaryOrExpression());
01200 
01201                 try
01202                 {
01203                         constantResult = expectConstantExpression(pos, tree->deepCopy());
01204                         tree.reset();
01205                         return NULL;
01206                 }
01207                 catch (TranslatableError error)
01208                 {
01209                         // oops, tree cannot be resolved to a constant, return it
01210                         return tree.release();
01211                 }
01212         }
01213 
01217         int Compiler::expectConstantExpression(SourcePos pos, Node* tree)
01218         {
01219                 int result = 0;
01220 
01221                 // create a temporary "var = expr" tree
01222                 // used to access the facility offered by the AssignmentNode (size check,...)
01223                 std::auto_ptr<Node> tempTree1(new AssignmentNode(pos));
01224                 tempTree1->children.push_back(new MemoryVectorNode(pos, 0, 1, L"fake"));
01225                 tempTree1->children.push_back(tree);
01226 
01227                 //tempTree1->children.push_back(parseBinaryOrExpression());
01228 
01229                 //unsigned indent = 0;
01230                 //std::cerr << "Tree before expanding" << std::endl;
01231                 //tempTree1->dump(std::wcerr, indent);
01232 
01233                 std::auto_ptr<Node> tempTree2(tempTree1->expandToAsebaTree(NULL));
01234 
01235                 //std::cerr << "Tree after expanding" << std::endl;
01236                 //tempTree2->dump(std::wcerr, indent);
01237 
01238                 tempTree1.release();    // tree already deleted by expandToAsebaTree()
01239                 tempTree2->optimize(NULL);
01240 
01241                 //std::cerr << "Tree after optimization" << std::endl;
01242                 //tempTree2->dump(std::wcerr, indent);
01243                 //std::cerr << std::endl;
01244 
01245                 // valid optimization?
01246                 if ( !tempTree2.get() || tempTree2->children.size() == 0 )
01247                         throw TranslatableError(pos, ERROR_NOT_CONST_EXPR);
01248                 AssignmentNode* assignment = dynamic_cast<AssignmentNode*>(tempTree2->children[0]);
01249                 if ( !assignment || assignment->children.size() != 2 )
01250                         throw TranslatableError(pos, ERROR_NOT_CONST_EXPR);
01251 
01252                 // resolve to an ImmediateNode?
01253                 ImmediateNode* immediate = dynamic_cast<ImmediateNode*>(assignment->children[1]);
01254                 if (immediate)
01255                         result = immediate->value;
01256                 else
01257                         throw TranslatableError(pos, ERROR_NOT_CONST_EXPR);
01258 
01259                 // delete the tree
01260                 tempTree2.reset();
01261 
01262                 return result;
01263         }
01264         
01266         Node* Compiler::parseFunctionCall()
01267         {
01268                 SourcePos pos = tokens.front().pos;
01269                 tokens.pop_front();
01270                 
01271                 expect(Token::TOKEN_STRING_LITERAL);
01272                 
01273                 std::wstring funcName = tokens.front().sValue;
01274                 FunctionsMap::const_iterator funcIt(findFunction(funcName, pos));
01275                 
01276                 const TargetDescription::NativeFunction &function = targetDescription->nativeFunctions[funcIt->second];
01277                 std::auto_ptr<CallNode> callNode(new CallNode(pos, funcIt->second));
01278                 
01279                 tokens.pop_front();
01280                 
01281                 expect(Token::TOKEN_PAR_OPEN);
01282                 tokens.pop_front();
01283                 
01284                 if (function.parameters.size() == 0)
01285                 {
01286                         if (tokens.front() != Token::TOKEN_PAR_CLOSE)
01287                                 throw TranslatableError(tokens.front().pos, ERROR_FUNCTION_HAS_NO_ARG).arg(funcName);
01288                         tokens.pop_front();
01289                 }
01290                 else
01291                 {
01292                         // count the number of template parameters and build array
01293                         int minTemplateId = 0;
01294                         for (unsigned i = 0; i < function.parameters.size(); i++)
01295                                 minTemplateId = std::min(function.parameters[i].size, minTemplateId);
01296                         std::valarray<int> templateParameters(-1, -minTemplateId);
01297                         
01298                         // trees for arguments
01299                         for (unsigned i = 0; i < function.parameters.size(); i++)
01300                         {
01301                                 // check if it is an argument
01302                                 if (tokens.front() == Token::TOKEN_PAR_CLOSE)
01303                                         throw TranslatableError(tokens.front().pos, ERROR_FUNCTION_NO_ENOUGH_ARG).arg(funcName).arg((unsigned int)function.parameters.size()).arg(i);
01304                                 
01305                                 // we need to fill those two variables
01306                                 unsigned varAddr;
01307                                 unsigned varSize;
01308                                 SourcePos varPos = tokens.front().pos;
01309 
01310                                 std::auto_ptr<Node> preNode(parseBinaryOrExpression());
01311                                 // get the address and size
01312                                 varAddr = preNode->getVectorAddr();
01313                                 varSize = preNode->getVectorSize();
01314 
01315                                 // allocate memory?
01316                                 if (!dynamic_cast<MemoryVectorNode*>(preNode.get()) || varAddr == Node::E_NOVAL)
01317                                 {
01318                                         preNode.reset(allocateTemporaryVariable(pos, preNode.release()));
01319                                         varAddr = preNode->getVectorAddr();
01320                                         callNode->children.push_back(preNode.release());
01321                                 }
01322                                 
01323                                 // check if variable size is correct
01324                                 if (function.parameters[i].size > 0)
01325                                 {
01326                                         if (varSize != (unsigned)function.parameters[i].size)
01327                                                 throw TranslatableError(varPos, ERROR_FUNCTION_WRONG_ARG_SIZE).arg(i).arg(function.parameters[i].name).arg(funcName).arg(varSize).arg(function.parameters[i].size);
01328                                 }
01329                                 else if (function.parameters[i].size < 0)
01330                                 {
01331                                         int templateIndex = -function.parameters[i].size - 1;
01332                                         if (templateParameters[templateIndex] < 0)
01333                                         {
01334                                                 // template not initialised, store
01335                                                 templateParameters[templateIndex] = varSize;
01336                                         }
01337                                         else if ((unsigned)templateParameters[templateIndex] != varSize)
01338                                         {
01339                                                 throw TranslatableError(varPos, ERROR_FUNCTION_WRONG_ARG_SIZE_TEMPLATE).arg(i).arg(function.parameters[i].name).arg(funcName).arg(varSize).arg(templateParameters[templateIndex]);
01340                                         }
01341                                 }
01342                                 else
01343                                 {
01344                                         // any size, store variable size
01345                                         callNode->argumentsAddr.push_back(varSize);
01346                                 }
01347                                 
01348                                 // store variable address
01349                                 callNode->argumentsAddr.push_back(varAddr);
01350                                 
01351                                 // parse comma or end parenthesis
01352                                 if (i + 1 == function.parameters.size())
01353                                 {
01354                                         if (tokens.front() == Token::TOKEN_COMMA)
01355                                                 throw TranslatableError(tokens.front().pos, ERROR_FUNCTION_TOO_MANY_ARG).arg(funcName).arg((unsigned int)function.parameters.size());
01356                                         else
01357                                                 expect(Token::TOKEN_PAR_CLOSE);
01358                                 }
01359                                 else
01360                                 {
01361                                         if (tokens.front() == Token::TOKEN_PAR_CLOSE)
01362                                                 throw TranslatableError(tokens.front().pos, ERROR_FUNCTION_NO_ENOUGH_ARG).arg(funcName).arg((unsigned int)function.parameters.size()).arg(i + 1);
01363                                         else
01364                                                 expect(Token::TOKEN_COMMA);
01365                                 }
01366                                 tokens.pop_front();
01367                         } // for
01368                         
01369                         // store template parameters size when initialized
01370                         for (unsigned i = 0; i < templateParameters.size(); i++)
01371                                 if (templateParameters[i] >= 0)
01372                                         callNode->argumentsAddr.push_back(templateParameters[i]);
01373                 } // if
01374                 
01375                 // return the node for the function call
01376                 return callNode.release();
01377         }
01378 }; // Aseba


aseba
Author(s): Stéphane Magnenat
autogenerated on Thu Jan 2 2014 11:17:16