TreeNode* Parser::If() { TreeNode* node = new TreeNode(currentToken, ifNode); preservedToken = currentToken; matchToken(tokIf); node->appendChild( Expression() ); if (currentToken.type == tokDo) getToken(); // skip dummy word 'do' if (currentToken.type == tokBegin) node->appendChild( Block() ); // if followed by a block else node->appendChild( Statement() ); // if followed by single statement while (currentToken.type == tokEOL) getToken(); // allow the else keyword to be on later lines if (currentToken.type == tokElse) // else part { matchToken(tokElse); while (currentToken.type == tokEOL) getToken(); if (currentToken.type == tokDo) getToken(); // next word if(currentToken.type == tokBegin) node->appendChild( Block() ); // else is followed by block else node->appendChild( Statement() ); } return node; }
TreeNode* Parser::Program() { Token emptyToken; emptyToken.type = tokNotSet; emptyToken.look = ""; emptyToken.start.row = 0; emptyToken.start.col = 0; emptyToken.end.row = 0; emptyToken.end.col = 0; TreeNode* program = new TreeNode(emptyToken, programNode, "program"); TreeNode* block = new TreeNode(emptyToken, blockNode, "block"); getToken(); // this is the main parse loop kdDebug(0)<<"Parser::Program(): entering main parse loop..."<<endl; while (currentToken.type != tokEOF) // currentToken.type returns the type of the currentToken { kdDebug(0)<<"Parser::Program(), [main parse loop]: looking for next statement..."<<endl; block->appendChild( Statement() ); while (currentToken.type == tokEOL) getToken(); // newlines between statements are allowed // runs statement related code, stores the returned TreeNode* in the nodetree // note: Statement() allways gets a new Token with getToken() before it returns } program->appendChild(block); kdDebug(0)<<"Parser::Program(): leaving main parse loop..."<<endl; return program; }
TreeNode* Parser::Learn() { preservedToken = currentToken; matchToken(tokLearn); // skip the 'dummy' command TreeNode* func = new TreeNode(currentToken, functionNode); getToken(); // get the token after the function's name TreeNode* idList = new TreeNode(currentToken, idListNode, "idlist"); if (currentToken.type != tokBegin) { if (currentToken.type == tokUnknown) idList->appendChild( getId() ); else { Error(currentToken, "Expected a parameter name or a '[' after the learn command.", 3030); getToken(); // this recovers from the error } while (currentToken.type == tokComma) { matchToken(tokComma); idList->appendChild( getId() ); } } func->appendChild(idList); learnedFunctionList.append( func->getLook() ); // publish the function func->appendChild( Block() ); return func; }
TreeNode* Parser::FunctionCall(Token maybeFunctionCall) { kdDebug(0)<<"Parser::FunctionCall() [using identifier: '"<<maybeFunctionCall.look<<"']"<<endl; TreeNode* fcall = new TreeNode(maybeFunctionCall, functionCallNode); TreeNode* paramList = new TreeNode(currentToken, idListNode, "idlist"); // if (currentToken.type != tokEOL && currentToken.type != tokEOF) if (currentToken.type == tokNumber || currentToken.type == tokString || currentToken.type == tokUnknown) // only if there is a possible parameter given after the call... { TreeNode* expr = Expression(); if (expr->getType() == Unknown) Error(currentToken, i18n("Expected an expression"), 1020); else paramList->appendChild(expr); while (currentToken.type == tokComma) { matchToken(tokComma); expr = Expression(); if (expr->getType() == Unknown) Error(currentToken, i18n("Expected an expression"), 1020); else paramList->appendChild(expr); } } fcall->appendChild(paramList); return fcall; }
TreeNode* Parser::Repeat() { TreeNode* node = new TreeNode(currentToken, RepeatNode); preservedToken = currentToken; // preserve token, else Match() will make sure it gets lost matchToken(tokRepeat); node->appendChild( Expression() ); node->appendChild( Block() ); return node; }
TreeNode* Parser::While() { TreeNode* node = new TreeNode(currentToken, whileNode); preservedToken = currentToken; matchToken(tokWhile); node->appendChild( Expression() ); node->appendChild( Block() ); return node; }
TreeNode* Parser::ForEach() { TreeNode* fNode = new TreeNode(currentToken, forEachNode); preservedToken = currentToken; matchToken(tokForEach); fNode->appendChild( Expression() ); matchToken(tokIn); fNode->appendChild( Expression() ); if (currentToken.type == tokBegin) fNode->appendChild( Block() ); // for followed by a block else fNode->appendChild( Statement() ); // while followed by single statement return fNode; }
TreeNode* Parser::Print() { TreeNode* node = new TreeNode(currentToken, printNode); preservedToken = currentToken; // preserve token, else Match() will make sure it gets lost getToken(); if (currentToken.type == tokEOL) return node; // print called without expressions node->appendChild( Expression() ); // first expression // following strings or expressions while (currentToken.type == tokComma) { getToken(); // the comma node->appendChild( Expression() ); } matchToken(tokEOL); return node; }
TreeNode* Parser::Term() { TreeNode* termNode = signedFactor(); TreeNode* pos = termNode; TreeNode* left = NULL; TreeNode* right = NULL; while ( (currentToken.type == tokMul) || (currentToken.type == tokDev) || (currentToken.type == tokAnd) ) { // while is is a multiplicative operator do... left = pos; pos = new TreeNode(currentToken, Unknown); pos->appendChild(left); switch (currentToken.type) { case tokMul: matchToken(tokMul); right = signedFactor(); pos->setType(mulNode); break; case tokDev: matchToken(tokDev); right = signedFactor(); pos->setType(divNode); break; case tokAnd: matchToken(tokAnd); right = signedFactor(); pos->setType(andNode); break; default: Error(currentToken, i18n("Expected '*' or '/'"), 1030); getToken(); return pos; break; } if (right != NULL) pos->appendChild(right); termNode = pos; } return termNode; }
TreeNode* Parser::ExternalRun() { TreeNode* node = new TreeNode(currentToken, runNode); preservedToken = currentToken; getToken(); node->appendChild( Expression() ); // matchToken(tokEOL); this command can return values so can be used as expression/parameter return node; }
TreeNode* Parser::Return() { TreeNode* ret = new TreeNode(currentToken, returnNode); matchToken(tokReturn); ret->appendChild( Expression() ); return ret; }
TreeNode* Parser::signedFactor() { // see if there is a tokPlus, tokMinus or tokNot infront of the factor TreeNode* node; switch (currentToken.type) { case tokPlus: matchToken(tokPlus); return Factor(); break; case tokMinus: preservedToken = currentToken; matchToken(tokMinus); node = Factor(); if (node->getType() == constantNode) { // in case of just a constant (-3) situation Value num = node->getValue(); num.setNumber( -num.Number() ); node->setValue(num); return node; } else { // in case of a variable or other situation (-a) TreeNode* minus = new TreeNode(preservedToken, minusNode); minus->appendChild(node); return minus; } break; case tokNot: preservedToken = currentToken; matchToken(tokNot); node = Factor(); { // extra scope needed to localize not_Node TreeNode* not_Node = new TreeNode(preservedToken, notNode); not_Node->appendChild(node); return not_Node; } break; default: // fall-through safety return Factor(); break; } }
TreeNode* Parser::Block() { TreeNode* block = new TreeNode(currentToken, blockNode, "block"); while (currentToken.type == tokEOL) getToken(); // skip newlines matchToken(tokBegin); while (currentToken.type == tokEOL) getToken(); // skip newlines while ( (currentToken.type != tokEnd) && (currentToken.type != tokEOF) ) { block->appendChild( Statement() ); while (currentToken.type == tokEOL) getToken(); // blocks can have newlines between their statements } matchToken(tokEnd); return block; }
TreeNode* Parser::Assignment(Token t) { TreeNode* node = new TreeNode(t, assignNode); matchToken(tokAssign); // match the '=' // the child is the expression or RHV of assignment TreeNode* expr = NULL; // if (currentToken.type == tokUnknown) expr = Other(); // in case of an functioncall // else expr = Expression(); -------> fuctioncalls get caught in Expression() and co. expr = Expression(); node->appendChild(expr); return node; }
TreeNode* Parser::For() { TreeNode* fNode = new TreeNode(currentToken, forNode); preservedToken = currentToken; matchToken(tokFor); fNode->appendChild( getId() ); // loop id matchToken(tokAssign); fNode->appendChild( Expression() ); // start value expression matchToken(tokTo); fNode->appendChild( Expression() ); // stop value expression if (currentToken.type == tokStep) { matchToken(tokStep); fNode->appendChild( Expression() ); //step expression } while (currentToken.type == tokEOL) getToken(); // newlines are allowed if (currentToken.type == tokBegin) fNode->appendChild( Block() ); // for followed by a block else fNode->appendChild( Statement() ); // while followed by single statement return fNode; }
/* Parse and Translate an Expression */ TreeNode* Parser::Expression() { TreeNode* retExp = Term(); // preset the base-TreeNode as it eventually will be returned TreeNode* pos = retExp; TreeNode* left = NULL; TreeNode* right = NULL; while ( isAddOp(currentToken) ) { left = pos; pos = new TreeNode(currentToken, Unknown); pos->appendChild(left); switch (currentToken.type) { case tokPlus: matchToken(tokPlus); right = Term(); pos->setType(addNode); break; case tokMinus: matchToken(tokMinus); right = Term(); pos->setType(subNode); break; case tokGt: matchToken(tokGt); right = Term(); pos->setType(nodeGT); break; case tokLt: matchToken(tokLt); right = Term(); pos->setType(nodeLT); break; case tokGe: matchToken(tokGe); right = Term(); pos->setType(nodeGE); break; case tokLe: matchToken(tokLe); right = Term(); pos->setType(nodeLE); break; case tokEq: matchToken(tokEq); right = Term(); pos->setType(nodeEQ); break; case tokNe: matchToken(tokNe); right = Term(); pos->setType(nodeNE); break; case tokOr: matchToken(tokOr); right = Term(); pos->setType(orNode); break; default: Error(currentToken, i18n("Expected '*' or '/'"), 1040); getToken(); return pos; break; } if (right != NULL) pos->appendChild(right); retExp = pos; } return retExp; }