File indexing completed on 2024-12-08 03:32:04

0001 /*
0002     SPDX-FileCopyrightText: 2003-2006 Cies Breijs <cies AT kde DOT nl>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "parser.h"
0008 
0009 #include <QDebug>
0010 
0011 #include <KLocalizedString>
0012 
0013 
0014 Parser::~Parser()
0015 {
0016 }
0017 
0018 void Parser::initialize(Tokenizer* _tokenizer, ErrorList* _errorList)
0019 {
0020     tokenizer    = _tokenizer;
0021     errorList    = _errorList;
0022 
0023     rootNode     = new TreeNode(new Token(Token::Root, QStringLiteral("root"), 0, 0, 0, 0));
0024     currentScope = rootNode;
0025     newScope     = nullptr;
0026     finished     = false;
0027 
0028     nextToken();
0029 }
0030 
0031 void Parser::parse()
0032 {
0033     if (finished) return;
0034 
0035 //  //qDebug() << "Parser::parse() -- main parse loop called";
0036     TreeNode* resultNode = parseStatement();  // parse the next statement
0037     if (resultNode == nullptr) {  // no statement was found
0038         addError(i18n("Expected a command, instead got '%1'", currentToken->look()), *currentToken, 0);
0039         return;
0040     }
0041 
0042     if (resultNode->token()->type() == Token::ScopeClose ||
0043         resultNode->token()->type() == Token::EndOfInput) {
0044         delete resultNode;
0045     } else {
0046         currentScope->appendChild(resultNode);
0047     }
0048 
0049     if (newScope != nullptr) {
0050         currentScope = newScope;
0051         newScope = nullptr;
0052     }
0053 }
0054 
0055 void Parser::nextToken()
0056 {
0057     // get the next relevant token, and store it in currentToken
0058 
0059     // skip spaces and comments:
0060     currentToken = tokenizer->getToken();
0061 //  //qDebug() << "########### got token: " << currentToken->look();
0062 
0063     while (currentToken->type() == Token::WhiteSpace ||
0064            currentToken->type() == Token::Comment) {
0065         delete currentToken;
0066         currentToken = tokenizer->getToken();
0067 //      //qDebug() << "########### got token: " << currentToken->look();
0068     }
0069 
0070     if (currentToken->type() == Token::Error)
0071         addError(i18n("Could not understand '%1'", currentToken->look()), *currentToken, 100);
0072 
0073 //  QString out = QString("Parser::nextToken(): \"%5\" [%6] @ (%1,%2)-(%3,%4)")
0074 //      .arg(currentToken->startRow())
0075 //      .arg(currentToken->startCol())
0076 //      .arg(currentToken->endRow())
0077 //      .arg(currentToken->endCol())
0078 //      .arg(currentToken->look())
0079 //      .arg(currentToken->type());
0080 //  //qDebug() << "Parser::nextToken():" << currentToken->look() << " [" << currentToken->type() << "]   on line" << currentToken->startRow();
0081     if (currentToken->type() == Token::EndOfInput)
0082         finished = true;
0083 }
0084 
0085 
0086 bool Parser::skipToken(int expectedTokenType)
0087 {
0088     // if the expectedTokenType matches the currentToken's type, dispose the currentToken and get a new one
0089     if (currentToken->type() == expectedTokenType) {
0090         delete currentToken;
0091         nextToken();
0092         return true;
0093     }
0094     return false;
0095 }
0096 
0097 bool Parser::skipToken(int expectedTokenType, Token& byToken)
0098 {
0099     // TODO have byToken, and "errorHappenedHereToken"
0100     //TODO: Translate the following QStrings?
0101 
0102     if (skipToken(expectedTokenType)) return true;
0103 
0104     switch (expectedTokenType) {
0105         case Token::ArgumentSeparator:
0106             addError(i18n("A comma was expected here..."), byToken, 0);
0107             break;
0108         case Token::EndOfInput:
0109             addError(i18n("Did not expect '%1', instead expected the line to end after %2",
0110                     currentToken->look(),
0111                     byToken.look()),
0112                byToken, 0);
0113             break;
0114         case Token::Assign:
0115             addError(i18n("Expected an assignment, '=', after the variable '%1'",
0116                     byToken.look()), byToken, 0);
0117             break;
0118         case Token::ParenthesisClose:
0119             addError(i18n("Did not expect '%1', instead expected a closing parenthesis, ')'",
0120                     currentToken->look()), byToken, 0);
0121             break;
0122         case Token::To:
0123             addError(i18n("Expected 'to' after 'for'"), byToken, 0);
0124             break;
0125         case Token::FunctionCall:
0126             addError(i18n("Expected a name for a command after 'learn' command"), byToken, 0);
0127             break;
0128     }
0129 
0130     return false;
0131 }
0132 
0133 
0134 void Parser::addError(const QString& s, const Token& t, int code)
0135 {
0136 //  if (m_testing)
0137 //      //qDebug() << "ERR> " << qPrintable(s) << " (parse error)";
0138     errorList->addError(s, t, code);
0139 }
0140 
0141 void Parser::printTree() const
0142 {
0143     const char* prefix = m_testing ? "NTR> " : "";
0144     const auto str{rootNode->toString().split(QLatin1Char('\n'), Qt::SkipEmptyParts)};
0145     for (const QString &line : str) {
0146         qDebug() << prefix << qPrintable(line.trimmed());
0147     }
0148 }
0149 
0150 
0151 
0152 TreeNode* Parser::parseStatement()
0153 {
0154     // in addition to whitespace and comments (skipped by nextToken()), also skip newlines before statements
0155     while (currentToken->type() == Token::EndOfLine) {
0156         delete currentToken;
0157         nextToken();
0158     }
0159 
0160     if (finished)
0161         return new TreeNode(currentToken);  // TODO check if all scopes are closed before returning + throw error
0162 
0163     switch (currentToken->type()) {
0164 
0165 //BEGIN GENERATED parser_statements_cpp CODE
0166 
0167 /* The code between the line that start with "//BEGIN GENERATED" and "//END GENERATED"
0168  * is generated by "generate.rb" according to the definitions specified in
0169  * "definitions.rb". Please make all changes in the "definitions.rb" file, since all
0170  * all change you make here will be overwritten the next time "generate.rb" is run.
0171  * Thanks for looking at the code!
0172  */
0173 
0174         case Token::Variable            : return parseVariable();
0175         case Token::FunctionCall        : return parseFunctionCall();
0176         case Token::ScopeOpen           : return parseScopeOpen();
0177         case Token::ScopeClose          : return parseScopeClose();
0178         case Token::Exit                : return parseExit();
0179         case Token::If                  : return parseIf();
0180         case Token::Repeat              : return parseRepeat();
0181         case Token::While               : return parseWhile();
0182         case Token::For                 : return parseFor();
0183         case Token::Break               : return parseBreak();
0184         case Token::Return              : return parseReturn();
0185         case Token::Wait                : return parseWait();
0186         case Token::Assert              : return parseAssert();
0187         case Token::Learn               : return parseLearn();
0188         case Token::Reset               : return parseReset();
0189         case Token::Clear               : return parseClear();
0190         case Token::Center              : return parseCenter();
0191         case Token::Go                  : return parseGo();
0192         case Token::GoX                 : return parseGoX();
0193         case Token::GoY                 : return parseGoY();
0194         case Token::Forward             : return parseForward();
0195         case Token::Backward            : return parseBackward();
0196         case Token::Direction           : return parseDirection();
0197         case Token::TurnLeft            : return parseTurnLeft();
0198         case Token::TurnRight           : return parseTurnRight();
0199         case Token::PenWidth            : return parsePenWidth();
0200         case Token::PenUp               : return parsePenUp();
0201         case Token::PenDown             : return parsePenDown();
0202         case Token::PenColor            : return parsePenColor();
0203         case Token::CanvasColor         : return parseCanvasColor();
0204         case Token::CanvasSize          : return parseCanvasSize();
0205         case Token::SpriteShow          : return parseSpriteShow();
0206         case Token::SpriteHide          : return parseSpriteHide();
0207         case Token::Print               : return parsePrint();
0208         case Token::FontSize            : return parseFontSize();
0209         case Token::Random              : return parseRandom();
0210         case Token::GetX                : return parseGetX();
0211         case Token::GetY                : return parseGetY();
0212         case Token::Message             : return parseMessage();
0213         case Token::Ask                 : return parseAsk();
0214         case Token::Pi                  : return parsePi();
0215         case Token::Tan                 : return parseTan();
0216         case Token::Sin                 : return parseSin();
0217         case Token::Cos                 : return parseCos();
0218         case Token::ArcTan              : return parseArcTan();
0219         case Token::ArcSin              : return parseArcSin();
0220         case Token::ArcCos              : return parseArcCos();
0221         case Token::Sqrt                : return parseSqrt();
0222         case Token::Round               : return parseRound();
0223         case Token::GetDirection        : return parseGetDirection();
0224         case Token::Mod                 : return parseMod();
0225 
0226 //END GENERATED parser_statements_cpp CODE
0227         case Token::Error       : return new TreeNode(currentToken);
0228         default : {
0229             //Token type is something else...
0230             ////qDebug() << "Parser::parseStatement(): I don't know this Token type.";
0231             ////qDebug() << "Look: " << currentToken->look() << " type: " << currentToken->type();
0232             addError(i18n("You cannot put '%1' here.", currentToken->look()), *currentToken, 0);
0233             finished = true;
0234             return new TreeNode(currentToken);
0235         }
0236     }
0237 }
0238 
0239 
0240 TreeNode* Parser::parseFactor()
0241 {
0242 //  //qDebug() << "Parser::parseFactor()";
0243     Token* rememberedToken;
0244     TreeNode* node;
0245     switch (currentToken->type()) {
0246         case Token::ParenthesisOpen:
0247             rememberedToken = currentToken;
0248             nextToken();
0249             node = parseExpression();
0250             skipToken(Token::ParenthesisClose, *rememberedToken);
0251             break;
0252 
0253         case Token::FunctionCall:
0254             node = parseFunctionCall();
0255             break;
0256 
0257         case Token::Variable:
0258             node = new TreeNode(currentToken);
0259             nextToken();
0260             break;
0261 
0262         case Token::String:
0263             node = new TreeNode(currentToken);
0264             { // extra scope to localize the QString 'str'
0265                 QString str = currentToken->look();
0266                 if (!currentToken->look().endsWith(QLatin1Char('\"'))) {
0267                     str += QLatin1String("\"");
0268                     addError(i18n("Text string was not properly closed, expected a double quote, ' \" ', to close the string."), *currentToken, 0);
0269                 }
0270                 node->value()->setString(str.mid(1, str.length() - 2));
0271             }
0272             nextToken();
0273             break;
0274 
0275         case Token::Number:
0276             node = new TreeNode(currentToken);
0277             {
0278                 bool ok = true;
0279                 double num = currentToken->look().toDouble(&ok);
0280                 if (ok) {
0281                     node->value()->setNumber(num);
0282                     nextToken();
0283                 } else {
0284                     qCritical("Parser::parseFactor(): could not parse a number");
0285                 }
0286             }
0287             break;
0288 
0289         case Token::True:
0290             node = new TreeNode(currentToken);
0291             node->value()->setBool(true);
0292             nextToken();
0293             break;
0294 
0295         case Token::False:
0296             node = new TreeNode(currentToken);
0297             node->value()->setBool(false);
0298             nextToken();
0299             break;
0300 
0301 //      case Token::Run:
0302 //          node = ExternalRun();
0303 //          break;
0304 // 
0305 //      case tokInputWindow:
0306 //          node = InputWindow();
0307 //          break;
0308 // 
0309 //      case tokRandom:
0310 //          node = Random();
0311 //          break;
0312 // 
0313 //      case Token::EndOfLine:
0314 //          node = new TreeNode(currentToken);
0315 //          break;
0316 
0317 
0318             default:
0319                 // TODO maybe precheck if this is a statement that returns something
0320                 node = parseStatement();
0321                 break;
0322 
0323 
0324 //      default:
0325 //          QString s = currentToken->look();
0326 //          if ( s.isEmpty() || currentToken->type() == Token::EndOfInput )
0327 //          {
0328 // //               Error(currentToken, i18n("INTERNAL ERROR NR %1: please sent this Logo script to KTurtle developers").arg(1), 1020);
0329 //              // if this error occurs the see the Parser::Repeat for the good solution using 'preservedToken'
0330 //          }
0331 //          else
0332 //          {
0333 // //               Error(currentToken, i18n("Cannot understand '%1', expected an expression after the '%2' command").arg(s).arg(preservedToken->look()), 1020);
0334 //          }
0335 //          node = new TreeNode(currentToken);
0336 //          nextToken();
0337 //          break;
0338     }
0339     return node;
0340 }
0341 
0342 
0343 TreeNode* Parser::parseSignedFactor()
0344 {
0345 //  //qDebug() << "Parser::parseSignedFactor()";
0346     // see if there is a plus, minus or 'not' in front of a factor
0347     Token* rememberedToken;
0348     TreeNode* node;
0349     switch (currentToken->type()) {
0350         case Token::Addition:
0351             nextToken();
0352             return parseFactor();
0353             break;
0354 
0355         case Token::Subtraction:
0356             rememberedToken = currentToken;
0357             nextToken();
0358             node = parseFactor();
0359             if (node->token()->type() == Token::Number) {
0360                 // in case of just a constant (-3) situation
0361                 node->value()->setNumber(-1 * node->value()->number());
0362                 return node;
0363             } else {
0364                 // in case of a variable or other situation (-$a)
0365                 TreeNode* minusNode = new TreeNode(rememberedToken);
0366                 minusNode->appendChild(node);
0367                 return minusNode;
0368             }
0369             break;
0370 
0371         case Token::Not:
0372             rememberedToken = currentToken;
0373             nextToken();
0374             node = parseFactor();
0375             { // extra scope needed to localize not_Node
0376                 TreeNode* notNode = new TreeNode(rememberedToken);
0377                 notNode->appendChild(node);
0378                 return notNode;
0379             }
0380             break;
0381 
0382         default:
0383             // no 'sign', no problem; just had to check if there was any... continue with the real work:
0384             return parseFactor();
0385             break;
0386     }
0387 }
0388 
0389 
0390 
0391 TreeNode* Parser::parseTerm()
0392 {
0393 //  //qDebug() << "Parser::parseTerm()";
0394     TreeNode* termNode = parseSignedFactor();
0395     TreeNode* pos = termNode;
0396     TreeNode* left = nullptr;
0397     TreeNode* right = nullptr;
0398 
0399     while ( (currentToken->type() == Token::Multiplication) ||
0400             (currentToken->type() == Token::Division) ||
0401             (currentToken->type() == Token::Power)  ) {
0402         // while we find a multiplicative operator do...
0403         left = pos;
0404         pos = new TreeNode(currentToken);
0405         pos->appendChild(left);
0406         nextToken();
0407         right = parseSignedFactor();
0408         if (right != nullptr)
0409             pos->appendChild(right);
0410         termNode = pos;
0411     }
0412     return termNode;
0413 }
0414 
0415 
0416 TreeNode* Parser::parseExpression()
0417 {
0418 //  //qDebug() << "Parser::parseExpression()";
0419     TreeNode* expressionNode = parseTerm();
0420     TreeNode* pos = expressionNode;
0421     TreeNode* left = nullptr;
0422     TreeNode* right = nullptr;
0423 
0424     Token* prevToken = nullptr;
0425 
0426     while ((currentToken->type() == Token::Addition) ||
0427            (currentToken->type() == Token::Subtraction) ||
0428            (currentToken->type() == Token::GreaterThan) ||
0429            (currentToken->type() == Token::GreaterOrEquals) ||
0430            (currentToken->type() == Token::LessThan) ||
0431            (currentToken->type() == Token::LessOrEquals) ||
0432            (currentToken->type() == Token::Equals) ||
0433            (currentToken->type() == Token::NotEquals) ||
0434            (currentToken->type() == Token::Or) ||
0435            (currentToken->type() == Token::And)) {
0436         left = pos;
0437         pos = new TreeNode(currentToken);
0438         pos->appendChild(left);
0439         prevToken = currentToken;
0440         nextToken();
0441         
0442         if(prevToken->type() == Token::And ||
0443            prevToken->type() == Token::Or)
0444             right = parseExpression();
0445         else
0446             right = parseTerm();
0447         if (right != nullptr) pos->appendChild(right);
0448         expressionNode = pos;
0449     }
0450     return expressionNode;
0451 }
0452 
0453 
0454 
0455 void Parser::appendArguments(TreeNode* node)
0456 {
0457     // appends the nodes of arguments to the node, does not do any type/quantity checking.
0458     // this because it's also used for the user defined 'functionCall' where we don't know type nor quantity
0459     // we also don't know if this node is (part of) an argument itself
0460     if (currentToken->type() == Token::EndOfLine ||
0461         currentToken->type() == Token::EndOfInput ||
0462         currentToken->type() == Token::ArgumentSeparator ||
0463         currentToken->type() == Token::ParenthesisClose ||
0464         currentToken->type() == Token::ScopeOpen ||
0465         currentToken->type() == Token::ScopeClose) return;
0466     node->appendChild(parseExpression()); // append the first parameter
0467     while (skipToken(Token::ArgumentSeparator)) {  // pushes through the comma
0468         if (currentToken->type() == Token::EndOfLine ||
0469             currentToken->type() == Token::EndOfInput)
0470             return; // catch forgotten expressions (go 10,)
0471         node->appendChild(parseExpression());
0472     }
0473 }
0474 
0475 
0476 
0477 //BEGIN GENERATED parser_cpp CODE
0478 
0479 /* The code between the line that start with "//BEGIN GENERATED" and "//END GENERATED"
0480  * is generated by "generate.rb" according to the definitions specified in
0481  * "definitions.rb". Please make all changes in the "definitions.rb" file, since all
0482  * all change you make here will be overwritten the next time "generate.rb" is run.
0483  * Thanks for looking at the code!
0484  */
0485 
0486 TreeNode* Parser::parseVariable() {
0487     // This is called to the variable is the first token on a line.
0488     // There has to be an assignment token right after it...
0489     TreeNode* variableNode = new TreeNode(currentToken);
0490     nextToken();
0491     Token* remeberedToken = new Token(*currentToken);
0492     skipToken(Token::Assign, *variableNode->token());
0493     TreeNode* assignNode = new TreeNode(remeberedToken);
0494     assignNode->appendChild(variableNode);      // the LHV; the symbol
0495     assignNode->appendChild(parseExpression()); // the RHV; the expression
0496     return assignNode;
0497 }
0498 
0499 TreeNode* Parser::parseFunctionCall() {
0500     TreeNode* node = new TreeNode(currentToken);
0501     node->token()->setType(Token::FunctionCall);
0502     nextToken();
0503     appendArguments(node);
0504     return node;
0505 }
0506 TreeNode* Parser::parseScopeOpen() {
0507 
0508     TreeNode* scopeNode = new TreeNode(new Token(Token::Scope, QStringLiteral("{...}"), currentToken->startRow(), currentToken->startCol(), 0, 0));
0509     delete currentToken;
0510     nextToken();
0511     // cannot change the currentScope to this scope cauz we still have to work in the currentScope
0512     // so we set the newScope, which the currentScope will become after parsing the current statement
0513     newScope = scopeNode;
0514     return scopeNode;
0515 }
0516 TreeNode* Parser::parseScopeClose() {
0517 
0518     TreeNode* node = new TreeNode(currentToken);
0519     int endRow = currentToken->endRow();
0520     int endCol = currentToken->endCol();
0521     nextToken();
0522     while (currentToken->type() == Token::EndOfLine) {  // allow newlines before else
0523         delete currentToken;
0524         nextToken();
0525     }
0526     if (currentScope->parent() && 
0527         currentScope->parent()->token()->type() == Token::If && 
0528         currentToken->type() == Token::Else) {
0529         currentScope->parent()->appendChild(parseElse());
0530     }
0531     if (currentScope != rootNode) {
0532         // find the parent scope of this scope, and make it current
0533         TreeNode* parentScope = currentScope;
0534         do {
0535             parentScope = parentScope->parent();
0536         } while (parentScope != rootNode && parentScope->token()->type() != Token::Scope);
0537         currentScope->token()->setEndRow(endRow);
0538         currentScope->token()->setEndCol(endCol);
0539         currentScope = parentScope;
0540     }
0541     return node;
0542 }
0543 TreeNode* Parser::parseExit() {
0544 
0545     TreeNode* node = new TreeNode(currentToken);
0546     nextToken();
0547     skipToken(Token::EndOfLine, *node->token());
0548     return node;
0549 }
0550 TreeNode* Parser::parseIf() {
0551 
0552     TreeNode* node = new TreeNode(currentToken);
0553     nextToken();
0554     node->appendChild(parseExpression());
0555     if (currentToken->type() == Token::ScopeOpen) {
0556         node->appendChild(parseScopeOpen());  // if followed by a scope
0557     }
0558     return node;
0559 }
0560 TreeNode* Parser::parseElse() {
0561 
0562     nextToken();
0563     if (currentToken->type() == Token::ScopeOpen) {
0564         return parseScopeOpen();  // if followed by a scope
0565     }
0566     return parseStatement();    // if followed by single statement
0567 }
0568 TreeNode* Parser::parseRepeat() {
0569 
0570     TreeNode* node = new TreeNode(currentToken);
0571     nextToken();
0572     node->appendChild(parseExpression());
0573     if (currentToken->type() == Token::ScopeOpen) {
0574         node->appendChild(parseScopeOpen());  // if followed by a scope
0575     } else {
0576         node->appendChild(parseStatement());  // if followed by single statement
0577     }
0578     return node;
0579 }
0580 TreeNode* Parser::parseWhile() {
0581 
0582     TreeNode* node = new TreeNode(currentToken);
0583     nextToken();
0584     node->appendChild(parseExpression());
0585     if (currentToken->type() == Token::ScopeOpen) {
0586         node->appendChild(parseScopeOpen());  // if followed by a scope
0587     } else {
0588         node->appendChild(parseStatement());  // if followed by single statement
0589     }
0590     return node;
0591 }
0592 TreeNode* Parser::parseFor() {
0593 
0594     TreeNode* node = new TreeNode(currentToken);
0595     nextToken();
0596     Token* firstToken = currentToken;
0597     nextToken();
0598     if (firstToken->type() == Token::Variable && currentToken->type() == Token::Assign) {
0599         node->token()->setType(Token::ForTo);
0600         node->appendChild(new TreeNode(firstToken));
0601         nextToken();
0602         node->appendChild(parseExpression());
0603         skipToken(Token::To, *node->token());
0604         node->appendChild(parseExpression());
0605         if (currentToken->type() == Token::Step) {
0606             nextToken();
0607             node->appendChild(parseExpression());
0608         } else {
0609             TreeNode* step = new TreeNode(new Token(Token::Number, QStringLiteral("1"), 0,0,0,0));
0610             step->setValue(Value(1.0));
0611             node->appendChild(step);
0612         }
0613 //  } else if (currentToken->type() == Token::In) {
0614 //      // @TODO something for a for-in loop
0615     } else {
0616         addError(i18n("'for' was called wrongly"), *node->token(), 0);
0617         finished = true;  // abort after this error
0618         return node;
0619     }
0620 
0621     if (currentToken->type() == Token::ScopeOpen) {
0622         node->appendChild(parseScopeOpen());  // if followed by a scope
0623     } else {
0624         node->appendChild(parseStatement());  // if followed by single statement
0625     }
0626 
0627     return node;
0628 }
0629 TreeNode* Parser::parseBreak() {
0630 
0631     TreeNode* node = new TreeNode(currentToken);
0632     nextToken();
0633     skipToken(Token::EndOfLine, *node->token());
0634     return node;
0635 }
0636 TreeNode* Parser::parseReturn() {
0637 
0638     TreeNode* node = new TreeNode(currentToken);
0639     nextToken();
0640     appendArguments(node);
0641     skipToken(Token::EndOfLine, *node->token());
0642     return node;
0643 }
0644 TreeNode* Parser::parseWait() {
0645 
0646     TreeNode* node = new TreeNode(currentToken);
0647     nextToken();
0648     appendArguments(node);
0649     skipToken(Token::EndOfLine, *node->token());
0650     return node;
0651 }
0652 TreeNode* Parser::parseAssert() {
0653 
0654     TreeNode* node = new TreeNode(currentToken);
0655     nextToken();
0656     appendArguments(node);
0657     skipToken(Token::EndOfLine, *node->token());
0658     return node;
0659 }
0660 TreeNode* Parser::parseLearn() {
0661 
0662     TreeNode* node = new TreeNode(currentToken);
0663     nextToken();
0664     node->appendChild(new TreeNode(new Token(*currentToken)));
0665     skipToken(Token::FunctionCall, *node->token());
0666     
0667     TreeNode* argumentList = new TreeNode(new Token(Token::ArgumentList, QStringLiteral("arguments"), 0, 0, 0, 0));
0668     while (currentToken->type() == Token::Variable) {
0669         // cannot just call appendArguments here because we're only appending Token::Variable tokens
0670         argumentList->appendChild(new TreeNode(currentToken));
0671         nextToken();
0672         if (currentToken->type() != Token::ArgumentSeparator) break;
0673         nextToken();
0674     }
0675     node->appendChild(argumentList);
0676     
0677     //Skip all the following EndOfLine's
0678     while (currentToken->type() == Token::EndOfLine) {
0679         delete currentToken;
0680         nextToken();
0681     }
0682 
0683     if (currentToken->type() == Token::ScopeOpen) {
0684         node->appendChild(parseScopeOpen());  // if followed by a scope
0685     } else {
0686         addError(i18n("Expected a scope after the 'learn' command"), *node->token(), 0);
0687     }
0688     return node;
0689 }
0690 TreeNode* Parser::parseReset() {
0691 
0692     TreeNode* node = new TreeNode(currentToken);
0693     nextToken();
0694     skipToken(Token::EndOfLine, *node->token());
0695     return node;
0696 }
0697 TreeNode* Parser::parseClear() {
0698 
0699     TreeNode* node = new TreeNode(currentToken);
0700     nextToken();
0701     skipToken(Token::EndOfLine, *node->token());
0702     return node;
0703 }
0704 TreeNode* Parser::parseCenter() {
0705 
0706     TreeNode* node = new TreeNode(currentToken);
0707     nextToken();
0708     skipToken(Token::EndOfLine, *node->token());
0709     return node;
0710 }
0711 TreeNode* Parser::parseGo() {
0712 
0713     TreeNode* node = new TreeNode(currentToken);
0714     nextToken();
0715     appendArguments(node);
0716     skipToken(Token::EndOfLine, *node->token());
0717     return node;
0718 }
0719 TreeNode* Parser::parseGoX() {
0720 
0721     TreeNode* node = new TreeNode(currentToken);
0722     nextToken();
0723     appendArguments(node);
0724     skipToken(Token::EndOfLine, *node->token());
0725     return node;
0726 }
0727 TreeNode* Parser::parseGoY() {
0728 
0729     TreeNode* node = new TreeNode(currentToken);
0730     nextToken();
0731     appendArguments(node);
0732     skipToken(Token::EndOfLine, *node->token());
0733     return node;
0734 }
0735 TreeNode* Parser::parseForward() {
0736 
0737     TreeNode* node = new TreeNode(currentToken);
0738     nextToken();
0739     appendArguments(node);
0740     skipToken(Token::EndOfLine, *node->token());
0741     return node;
0742 }
0743 TreeNode* Parser::parseBackward() {
0744 
0745     TreeNode* node = new TreeNode(currentToken);
0746     nextToken();
0747     appendArguments(node);
0748     skipToken(Token::EndOfLine, *node->token());
0749     return node;
0750 }
0751 TreeNode* Parser::parseDirection() {
0752 
0753     TreeNode* node = new TreeNode(currentToken);
0754     nextToken();
0755     appendArguments(node);
0756     skipToken(Token::EndOfLine, *node->token());
0757     return node;
0758 }
0759 TreeNode* Parser::parseTurnLeft() {
0760 
0761     TreeNode* node = new TreeNode(currentToken);
0762     nextToken();
0763     appendArguments(node);
0764     skipToken(Token::EndOfLine, *node->token());
0765     return node;
0766 }
0767 TreeNode* Parser::parseTurnRight() {
0768 
0769     TreeNode* node = new TreeNode(currentToken);
0770     nextToken();
0771     appendArguments(node);
0772     skipToken(Token::EndOfLine, *node->token());
0773     return node;
0774 }
0775 TreeNode* Parser::parsePenWidth() {
0776 
0777     TreeNode* node = new TreeNode(currentToken);
0778     nextToken();
0779     appendArguments(node);
0780     skipToken(Token::EndOfLine, *node->token());
0781     return node;
0782 }
0783 TreeNode* Parser::parsePenUp() {
0784 
0785     TreeNode* node = new TreeNode(currentToken);
0786     nextToken();
0787     skipToken(Token::EndOfLine, *node->token());
0788     return node;
0789 }
0790 TreeNode* Parser::parsePenDown() {
0791 
0792     TreeNode* node = new TreeNode(currentToken);
0793     nextToken();
0794     skipToken(Token::EndOfLine, *node->token());
0795     return node;
0796 }
0797 TreeNode* Parser::parsePenColor() {
0798 
0799     TreeNode* node = new TreeNode(currentToken);
0800     nextToken();
0801     appendArguments(node);
0802     skipToken(Token::EndOfLine, *node->token());
0803     return node;
0804 }
0805 
0806 TreeNode* Parser::parseCanvasColor() {
0807     TreeNode* node = new TreeNode(currentToken);
0808     nextToken();
0809     appendArguments(node);
0810     skipToken(Token::EndOfLine, *node->token());
0811     return node;
0812 }
0813 
0814 TreeNode* Parser::parseCanvasSize() {
0815     TreeNode* node = new TreeNode(currentToken);
0816     nextToken();
0817     appendArguments(node);
0818     skipToken(Token::EndOfLine, *node->token());
0819     return node;
0820 }
0821 
0822 TreeNode* Parser::parseSpriteShow() {
0823     TreeNode* node = new TreeNode(currentToken);
0824     nextToken();
0825     skipToken(Token::EndOfLine, *node->token());
0826     return node;
0827 }
0828 TreeNode* Parser::parseSpriteHide() {
0829 
0830     TreeNode* node = new TreeNode(currentToken);
0831     nextToken();
0832     skipToken(Token::EndOfLine, *node->token());
0833     return node;
0834 }
0835 TreeNode* Parser::parsePrint() {
0836 
0837     TreeNode* node = new TreeNode(currentToken);
0838     nextToken();
0839     appendArguments(node);
0840     skipToken(Token::EndOfLine, *node->token());
0841     return node;
0842 }
0843 TreeNode* Parser::parseFontSize() {
0844 
0845     TreeNode* node = new TreeNode(currentToken);
0846     nextToken();
0847     appendArguments(node);
0848     skipToken(Token::EndOfLine, *node->token());
0849     return node;
0850 }
0851 TreeNode* Parser::parseRandom() {
0852 
0853     TreeNode* node = new TreeNode(currentToken);
0854     nextToken();
0855     appendArguments(node);
0856     skipToken(Token::EndOfLine, *node->token());
0857     return node;
0858 }
0859 TreeNode* Parser::parseGetX() {
0860 
0861     TreeNode* node = new TreeNode(currentToken);
0862     nextToken();
0863     skipToken(Token::EndOfLine, *node->token());
0864     return node;
0865 }
0866 TreeNode* Parser::parseGetY() {
0867 
0868     TreeNode* node = new TreeNode(currentToken);
0869     nextToken();
0870     skipToken(Token::EndOfLine, *node->token());
0871     return node;
0872 }
0873 TreeNode* Parser::parseMessage() {
0874 
0875     TreeNode* node = new TreeNode(currentToken);
0876     nextToken();
0877     appendArguments(node);
0878     skipToken(Token::EndOfLine, *node->token());
0879     return node;
0880 }
0881 TreeNode* Parser::parseAsk() {
0882 
0883     TreeNode* node = new TreeNode(currentToken);
0884     nextToken();
0885     appendArguments(node);
0886     skipToken(Token::EndOfLine, *node->token());
0887     return node;
0888 }
0889 TreeNode* Parser::parsePi() {
0890 
0891     TreeNode* node = new TreeNode(currentToken);
0892     nextToken();
0893     skipToken(Token::EndOfLine, *node->token());
0894     return node;
0895 }
0896 TreeNode* Parser::parseTan() {
0897 
0898     TreeNode* node = new TreeNode(currentToken);
0899     nextToken();
0900     appendArguments(node);
0901     skipToken(Token::EndOfLine, *node->token());
0902     return node;
0903 }
0904 TreeNode* Parser::parseSin() {
0905 
0906     TreeNode* node = new TreeNode(currentToken);
0907     nextToken();
0908     appendArguments(node);
0909     skipToken(Token::EndOfLine, *node->token());
0910     return node;
0911 }
0912 TreeNode* Parser::parseCos() {
0913 
0914     TreeNode* node = new TreeNode(currentToken);
0915     nextToken();
0916     appendArguments(node);
0917     skipToken(Token::EndOfLine, *node->token());
0918     return node;
0919 }
0920 TreeNode* Parser::parseArcTan() {
0921 
0922     TreeNode* node = new TreeNode(currentToken);
0923     nextToken();
0924     appendArguments(node);
0925     skipToken(Token::EndOfLine, *node->token());
0926     return node;
0927 }
0928 TreeNode* Parser::parseArcSin() {
0929 
0930     TreeNode* node = new TreeNode(currentToken);
0931     nextToken();
0932     appendArguments(node);
0933     skipToken(Token::EndOfLine, *node->token());
0934     return node;
0935 }
0936 TreeNode* Parser::parseArcCos() {
0937 
0938     TreeNode* node = new TreeNode(currentToken);
0939     nextToken();
0940     appendArguments(node);
0941     skipToken(Token::EndOfLine, *node->token());
0942     return node;
0943 }
0944 TreeNode* Parser::parseSqrt() {
0945 
0946     TreeNode* node = new TreeNode(currentToken);
0947     nextToken();
0948     appendArguments(node);
0949     skipToken(Token::EndOfLine, *node->token());
0950     return node;
0951 }
0952 TreeNode* Parser::parseRound() {
0953 
0954     TreeNode* node = new TreeNode(currentToken);
0955     nextToken();
0956     appendArguments(node);
0957     skipToken(Token::EndOfLine, *node->token());
0958     return node;
0959 }
0960 TreeNode* Parser::parseGetDirection() {
0961 
0962     TreeNode* node = new TreeNode(currentToken);
0963     nextToken();
0964     skipToken(Token::EndOfLine, *node->token());
0965     return node;
0966 }
0967 TreeNode* Parser::parseMod() {
0968 
0969     TreeNode* node = new TreeNode(currentToken);
0970     nextToken();
0971     appendArguments(node);
0972     skipToken(Token::EndOfLine, *node->token());
0973     return node;
0974 }
0975 
0976 //END GENERATED parser_cpp CODE
0977 
0978 
0979