moved kdeaccessibility kdeaddons kdeadmin kdeartwork kdebindings kdeedu kdegames...
[kdeedu.git] / kturtle / src / parser.cpp
blob48427d4f876ad8a146dff6038b9fc77f52d31d4c
1 /*
2 Copyright (C) 2003 by Walter Schreppers
3 Copyright (C) 2004 by Cies Breijs
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of version 2 of the GNU General Public
7 License as published by the Free Software Foundation.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 // This file is originally written by Walter Scheppers, but allmost
20 // allmost every aspect of it is heavily changed by Cies Breijs.
23 #include <qstringlist.h>
25 #include <kdebug.h>
26 #include <klocale.h>
28 #include "parser.h"
31 Parser::Parser(QTextIStream& in)
33 lexer = new Lexer(in);
34 tree = new TreeNode();
37 Parser::~Parser()
39 delete lexer;
42 void Parser::parse()
44 tree = Program(); // the first node that keeps the lexer running till finished/error
47 void Parser::getToken()
49 currentToken = lexer->lex(); // stores a Token, obtained though the lexer, in 'currentToken'
50 row = currentToken.start.row; // these will have to leave eventually, all should be passed on by the Token
51 col = currentToken.start.col;
52 kdDebug(0)<<"Parser::getToken(), got a token: '"<<currentToken.look<<"', @ ("<<currentToken.start.row<<", "<<currentToken.start.col<<") - ("<<currentToken.end.row<<", "<<currentToken.end.col<<"), tok-number:"<<currentToken.type<<endl;
55 TreeNode* Parser::Program()
57 Token emptyToken;
58 emptyToken.type = tokNotSet;
59 emptyToken.look = "";
60 emptyToken.start.row = 0;
61 emptyToken.start.col = 0;
62 emptyToken.end.row = 0;
63 emptyToken.end.col = 0;
65 TreeNode* program = new TreeNode(emptyToken, programNode, "program");
66 TreeNode* block = new TreeNode(emptyToken, blockNode, "block");
68 getToken();
70 // this is the main parse loop
71 kdDebug(0)<<"Parser::Program(): entering main parse loop..."<<endl;
72 while (currentToken.type != tokEOF) // currentToken.type returns the type of the currentToken
74 kdDebug(0)<<"Parser::Program(), [main parse loop]: looking for next statement..."<<endl;
75 block->appendChild( Statement() );
76 while (currentToken.type == tokEOL) getToken(); // newlines between statements are allowed
77 // runs statement related code, stores the returned TreeNode* in the nodetree
78 // note: Statement() allways gets a new Token with getToken() before it returns
80 program->appendChild(block);
81 kdDebug(0)<<"Parser::Program(): leaving main parse loop..."<<endl;
83 return program;
86 void Parser::matchToken(int expectedToken)
88 if (currentToken.type == expectedToken)
90 getToken(); // get a new token
91 return;
94 switch (expectedToken)
96 case tokEOL:
97 Error(currentToken, i18n("Unexpected intruction after the '%1' command, please use only one instuction per line").arg(preservedToken.look), 1010);
98 break;
100 case tokBegin:
101 Error(preservedToken, i18n("Expected '['"), 1010);
102 break;
104 case tokTo:
105 Error(currentToken, i18n("Expected 'to' after the '%1' command").arg(preservedToken.look), 1010);
106 break;
108 case tokAssign:
109 Error(currentToken, i18n("Expected '=' after the '%1' command").arg(preservedToken.look), 1010);
110 break;
112 case tokEnd:
113 Error(currentToken, i18n("Expected ']' after the '%1' command").arg(preservedToken.look), 1010);
114 break;
116 case tokUnknown:
117 Error(preservedToken, i18n("Expected a name after the '%1' command").arg(preservedToken.look), 1010);
118 break;
120 default:
121 Error(currentToken, i18n("UNDEFINED ERROR NR %1: please sent this Logo script to the KTurtle developers").arg(expectedToken), 1010);
122 break;
127 void Parser::appendParameters(TreeNode* node)
129 node->appendChild( Expression() ); // append the first papameter
130 while (currentToken.type == tokComma)
132 matchToken(tokComma); // push through the comma
133 if (currentToken.type == tokEOL) return; // catch forgotten expressions, like "go 10, "
134 node->appendChild( Expression() );
139 TreeNode* Parser::getId()
141 TreeNode* n = new TreeNode(currentToken, idNode);
142 n->setLook(currentToken.look);
143 matchToken(tokUnknown); // Id's are ofcouse not yet known
144 return n;
149 TreeNode* Parser::FunctionCall(Token maybeFunctionCall)
151 kdDebug(0)<<"Parser::FunctionCall() [using identifier: '"<<maybeFunctionCall.look<<"']"<<endl;
152 TreeNode* fcall = new TreeNode(maybeFunctionCall, functionCallNode);
154 TreeNode* paramList = new TreeNode(currentToken, idListNode, "idlist");
155 // if (currentToken.type != tokEOL && currentToken.type != tokEOF)
156 if (currentToken.type == tokNumber ||
157 currentToken.type == tokString ||
158 currentToken.type == tokUnknown) // only if there is a possible parameter given after the call...
160 TreeNode* expr = Expression();
161 if (expr->getType() == Unknown) Error(currentToken, i18n("Expected an expression"), 1020);
162 else paramList->appendChild(expr);
163 while (currentToken.type == tokComma)
165 matchToken(tokComma);
166 expr = Expression();
167 if (expr->getType() == Unknown) Error(currentToken, i18n("Expected an expression"), 1020);
168 else paramList->appendChild(expr);
171 fcall->appendChild(paramList);
173 return fcall;
177 TreeNode* Parser::Factor()
179 TreeNode* node;
180 Token rememberedToken = currentToken;
181 switch (currentToken.type)
183 case tokBraceOpen:
184 matchToken(tokBraceOpen);
185 node = Expression();
186 matchToken(tokBraceClose);
187 break;
189 case tokUnknown:
190 node = getId();
191 if (learnedFunctionList.contains(rememberedToken.look) > 0) // is function call
193 delete node;
194 node = FunctionCall(rememberedToken);
195 node->setType(funcReturnNode); // expect returned value on stack
197 break;
199 case tokString:
200 node = new TreeNode(currentToken, constantNode);
201 { // extra scope to localize the QString 'str'
202 QString str = currentToken.look;
203 if ( currentToken.look.endsWith("\"") )
205 // cut off the quotes and store the value
206 str.remove(0, 1).truncate( currentToken.look.length() - 2 );
208 else // problems but we need to keep it moving
210 str.remove(0, 1); // cut off the first quote only
211 Error(currentToken, i18n("String text not properly delimited with a ' \" ' (double quote)"), 1060);
213 node->setValue(str);
215 matchToken(tokString);
216 break;
218 case tokNumber:
219 node = new TreeNode(currentToken, constantNode);
220 node->setValue(currentToken.value);
221 matchToken(tokNumber);
222 break;
224 case tokRun:
225 node = ExternalRun();
226 break;
228 case tokInputWindow:
229 node = InputWindow();
230 break;
232 case tokRandom:
233 node = Random();
234 break;
236 case tokEOL:
237 node = new TreeNode(currentToken, Unknown);
238 break;
240 default:
241 QString s = currentToken.look;
242 if ( s.isEmpty() || currentToken.type == tokEOF )
244 Error(currentToken, i18n("INTERNAL ERROR NR %1: please sent this Logo script to KTurtle developers").arg(1), 1020);
245 // if this error occurs the see the Parser::Repeat for the good solution using 'preservedToken'
247 else
249 Error(currentToken, i18n("Cannot understand '%1', expected an expression after the '%2' command").arg(s).arg(preservedToken.look), 1020);
251 node = new TreeNode(currentToken, Unknown);
252 getToken();
253 break;
255 return node;
259 TreeNode* Parser::signedFactor()
261 // see if there is a tokPlus, tokMinus or tokNot infront of the factor
262 TreeNode* node;
263 switch (currentToken.type)
265 case tokPlus:
266 matchToken(tokPlus);
267 return Factor();
268 break;
270 case tokMinus:
271 preservedToken = currentToken;
272 matchToken(tokMinus);
273 node = Factor();
274 if (node->getType() == constantNode)
276 // in case of just a constant (-3) situation
277 Value num = node->getValue();
278 num.setNumber( -num.Number() );
279 node->setValue(num);
280 return node;
282 else
284 // in case of a variable or other situation (-a)
285 TreeNode* minus = new TreeNode(preservedToken, minusNode);
286 minus->appendChild(node);
287 return minus;
289 break;
291 case tokNot:
292 preservedToken = currentToken;
293 matchToken(tokNot);
294 node = Factor();
295 { // extra scope needed to localize not_Node
296 TreeNode* not_Node = new TreeNode(preservedToken, notNode);
297 not_Node->appendChild(node);
298 return not_Node;
300 break;
302 default:
303 // fall-through safety
304 return Factor();
305 break;
311 TreeNode* Parser::Term()
313 TreeNode* termNode = signedFactor();
314 TreeNode* pos = termNode;
315 TreeNode* left = NULL;
316 TreeNode* right = NULL;
318 while ( (currentToken.type == tokMul) || (currentToken.type == tokDev) || (currentToken.type == tokAnd) )
320 // while is is a multiplicative operator do...
321 left = pos;
322 pos = new TreeNode(currentToken, Unknown);
323 pos->appendChild(left);
325 switch (currentToken.type)
327 case tokMul:
328 matchToken(tokMul);
329 right = signedFactor();
330 pos->setType(mulNode);
331 break;
333 case tokDev:
334 matchToken(tokDev);
335 right = signedFactor();
336 pos->setType(divNode);
337 break;
339 case tokAnd:
340 matchToken(tokAnd);
341 right = signedFactor();
342 pos->setType(andNode);
343 break;
345 default:
346 Error(currentToken, i18n("Expected '*' or '/'"), 1030);
347 getToken();
348 return pos;
349 break;
351 if (right != NULL) pos->appendChild(right);
352 termNode = pos;
354 return termNode;
358 bool Parser::isAddOp(Token t)
360 return ( (t.type == tokPlus) ||
361 (t.type == tokMinus) ||
362 (t.type == tokGt) ||
363 (t.type == tokGe) ||
364 (t.type == tokLt) ||
365 (t.type == tokLe) ||
366 (t.type == tokEq) ||
367 (t.type == tokNe) ||
369 (t.type == tokOr) ||
370 (t.type == tokGe) );
374 /*---------------------------------------------------------------*/
375 /* Parse and Translate an Expression */
376 TreeNode* Parser::Expression()
378 TreeNode* retExp = Term(); // preset the base-TreeNode as it eventually will be returned
379 TreeNode* pos = retExp;
380 TreeNode* left = NULL;
381 TreeNode* right = NULL;
383 while ( isAddOp(currentToken) )
385 left = pos;
386 pos = new TreeNode(currentToken, Unknown);
387 pos->appendChild(left);
388 switch (currentToken.type)
390 case tokPlus:
391 matchToken(tokPlus);
392 right = Term();
393 pos->setType(addNode);
394 break;
396 case tokMinus:
397 matchToken(tokMinus);
398 right = Term();
399 pos->setType(subNode);
400 break;
402 case tokGt:
403 matchToken(tokGt);
404 right = Term();
405 pos->setType(nodeGT);
406 break;
408 case tokLt:
409 matchToken(tokLt);
410 right = Term();
411 pos->setType(nodeLT);
412 break;
414 case tokGe:
415 matchToken(tokGe);
416 right = Term();
417 pos->setType(nodeGE);
418 break;
420 case tokLe:
421 matchToken(tokLe);
422 right = Term();
423 pos->setType(nodeLE);
424 break;
426 case tokEq:
427 matchToken(tokEq);
428 right = Term();
429 pos->setType(nodeEQ);
430 break;
432 case tokNe:
433 matchToken(tokNe);
434 right = Term();
435 pos->setType(nodeNE);
436 break;
438 case tokOr:
439 matchToken(tokOr);
440 right = Term();
441 pos->setType(orNode);
442 break;
444 default:
445 Error(currentToken, i18n("Expected '*' or '/'"), 1040);
446 getToken();
447 return pos;
448 break;
450 if (right != NULL) pos->appendChild(right);
451 retExp = pos;
453 return retExp;
457 TreeNode* Parser::Assignment(Token t)
459 TreeNode* node = new TreeNode(t, assignNode);
460 matchToken(tokAssign); // match the '='
462 // the child is the expression or RHV of assignment
463 TreeNode* expr = NULL;
464 // if (currentToken.type == tokUnknown) expr = Other(); // in case of an functioncall
465 // else expr = Expression(); -------> fuctioncalls get caught in Expression() and co.
467 expr = Expression();
469 node->appendChild(expr);
471 return node;
475 TreeNode* Parser::Statement()
477 kdDebug(0)<<"Parser::Statement()"<<endl;
478 while (currentToken.type == tokEOL) getToken(); // statements can allways start on newlines
479 switch (currentToken.type)
481 case tokLearn : return Learn(); break;
483 case tokIf : return If(); break;
484 case tokFor : return For(); break;
485 case tokForEach : return ForEach(); break;
486 case tokWhile : return While(); break;
487 case tokRun : return ExternalRun(); break;
488 case tokReturn : return Return(); break;
489 case tokBreak : return Break(); break;
490 case tokUnknown : return Other(); break; //assignment or function call
492 case tokClear : return Clear(); break;
493 case tokGo : return Go(); break;
494 case tokGoX : return GoX(); break;
495 case tokGoY : return GoY(); break;
496 case tokForward : return Forward(); break;
497 case tokBackward : return Backward(); break;
498 case tokDirection : return Direction(); break;
499 case tokTurnLeft : return TurnLeft(); break;
500 case tokTurnRight : return TurnRight(); break;
501 case tokCenter : return Center(); break;
502 case tokSetPenWidth : return SetPenWidth(); break;
503 case tokPenUp : return PenUp(); break;
504 case tokPenDown : return PenDown(); break;
505 case tokSetFgColor : return SetFgColor(); break;
506 case tokSetBgColor : return SetBgColor(); break;
507 case tokResizeCanvas : return ResizeCanvas(); break;
508 case tokSpriteShow : return SpriteShow(); break;
509 case tokSpriteHide : return SpriteHide(); break;
510 case tokSpritePress : return SpritePress(); break;
511 case tokSpriteChange : return SpriteChange(); break;
513 case tokPrint : return Print(); break;
514 case tokInputWindow : return InputWindow(); break;
515 case tokMessage : return Message(); break;
516 case tokFontType : return FontType(); break;
517 case tokFontSize : return FontSize(); break;
518 case tokRepeat : return Repeat(); break;
519 case tokRandom : return Random(); break;
520 case tokWait : return Wait(); break;
521 case tokWrapOn : return WrapOn(); break;
522 case tokWrapOff : return WrapOff(); break;
523 case tokReset : return Reset(); break;
525 case tokEOF : return EndOfFile(); break;
527 case tokEnd : Error(currentToken, i18n("Cannot understand ']'"), 1050);
528 getToken();
529 return new TreeNode(currentToken, Unknown);
530 break;
532 case tokBegin : Error(currentToken, i18n("Cannot understand '['"), 1050);
533 getToken();
534 return new TreeNode(currentToken, Unknown);
535 break;
537 default : break;
539 if (currentToken.type != tokEnd)
541 Error(currentToken, i18n("Cannot understand '%1'").arg(currentToken.look), 1060);
544 getToken();
545 return new TreeNode(currentToken, Unknown); // fall-though for unknowns
549 TreeNode* Parser::Block()
551 TreeNode* block = new TreeNode(currentToken, blockNode, "block");
553 while (currentToken.type == tokEOL) getToken(); // skip newlines
554 matchToken(tokBegin);
555 while (currentToken.type == tokEOL) getToken(); // skip newlines
556 while ( (currentToken.type != tokEnd) && (currentToken.type != tokEOF) )
558 block->appendChild( Statement() );
559 while (currentToken.type == tokEOL) getToken(); // blocks can have newlines between their statements
561 matchToken(tokEnd);
562 return block;
567 // Turtle Funktions
570 // Functions that take NO arguments
572 TreeNode* Parser::Clear()
574 TreeNode* node = new TreeNode(currentToken, ClearNode);
575 preservedToken = currentToken;
576 getToken();
577 matchToken(tokEOL);
578 return node;
581 TreeNode* Parser::Center()
583 TreeNode* node = new TreeNode(currentToken, CenterNode);
584 preservedToken = currentToken;
585 getToken();
586 matchToken(tokEOL);
587 return node;
590 TreeNode* Parser::PenUp()
592 TreeNode* node = new TreeNode(currentToken, PenUpNode);
593 preservedToken = currentToken;
594 getToken();
595 matchToken(tokEOL);
596 return node;
599 TreeNode* Parser::PenDown()
601 TreeNode* node = new TreeNode(currentToken, PenDownNode);
602 preservedToken = currentToken;
603 getToken();
604 matchToken(tokEOL);
605 return node;
608 TreeNode* Parser::SpriteShow()
610 TreeNode* node = new TreeNode(currentToken, SpriteShowNode);
611 preservedToken = currentToken;
612 getToken();
613 matchToken(tokEOL);
614 return node;
617 TreeNode* Parser::SpriteHide()
619 TreeNode* node = new TreeNode(currentToken, SpriteHideNode);
620 preservedToken = currentToken;
621 getToken();
622 matchToken(tokEOL);
623 return node;
626 TreeNode* Parser::SpritePress()
628 TreeNode* node = new TreeNode(currentToken, SpritePressNode);
629 preservedToken = currentToken;
630 getToken();
631 matchToken(tokEOL);
632 return node;
635 TreeNode* Parser::WrapOn()
637 TreeNode* node = new TreeNode(currentToken, WrapOnNode);
638 preservedToken = currentToken;
639 getToken();
640 matchToken(tokEOL);
641 return node;
644 TreeNode* Parser::WrapOff()
646 TreeNode* node = new TreeNode(currentToken, WrapOffNode);
647 preservedToken = currentToken;
648 getToken();
649 matchToken(tokEOL);
650 return node;
653 TreeNode* Parser::Reset()
655 TreeNode* node = new TreeNode(currentToken, ResetNode);
656 preservedToken = currentToken;
657 getToken();
658 matchToken(tokEOL);
659 return node;
665 // Functions that take 1 arguments
667 TreeNode* Parser::GoX()
669 TreeNode* node = new TreeNode(currentToken, GoXNode);
670 preservedToken = currentToken;
671 getToken();
672 appendParameters(node);
673 matchToken(tokEOL);
674 return node;
678 TreeNode* Parser::GoY()
680 TreeNode* node = new TreeNode(currentToken, GoYNode);
681 preservedToken = currentToken;
682 getToken();
683 appendParameters(node);
684 matchToken(tokEOL);
685 return node;
689 TreeNode* Parser::Forward()
691 TreeNode* node = new TreeNode(currentToken, ForwardNode);
692 preservedToken = currentToken;
693 getToken();
694 appendParameters(node);
695 matchToken(tokEOL);
696 return node;
700 TreeNode* Parser::Backward()
702 TreeNode* node = new TreeNode(currentToken, BackwardNode);
703 preservedToken = currentToken;
704 getToken();
705 appendParameters(node);
706 matchToken(tokEOL);
707 return node;
710 TreeNode* Parser::Direction()
712 TreeNode* node = new TreeNode(currentToken, DirectionNode);
713 preservedToken = currentToken;
714 getToken();
715 appendParameters(node);
716 matchToken(tokEOL);
717 return node;
720 TreeNode* Parser::TurnLeft()
722 TreeNode* node = new TreeNode(currentToken, TurnLeftNode);
723 preservedToken = currentToken;
724 getToken();
725 appendParameters(node);
726 matchToken(tokEOL);
727 return node;
730 TreeNode* Parser::TurnRight()
732 TreeNode* node = new TreeNode(currentToken, TurnRightNode);
733 preservedToken = currentToken;
734 getToken();
735 appendParameters(node);
736 matchToken(tokEOL);
737 return node;
740 TreeNode* Parser::SetPenWidth()
742 TreeNode* node = new TreeNode(currentToken, SetPenWidthNode);
743 preservedToken = currentToken;
744 getToken();
745 appendParameters(node);
746 matchToken(tokEOL);
747 return node;
750 TreeNode* Parser::Message()
752 TreeNode* node = new TreeNode(currentToken, MessageNode);
753 preservedToken = currentToken;
754 getToken();
755 appendParameters(node);
756 matchToken(tokEOL);
757 return node;
760 TreeNode* Parser::InputWindow()
762 TreeNode* node = new TreeNode(currentToken, InputWindowNode);
763 preservedToken = currentToken;
764 getToken();
765 node->appendChild( Expression() );
766 // matchToken(tokEOL); this command can return values so can be used as expression/parameter
767 return node;
770 TreeNode* Parser::SpriteChange()
772 TreeNode* node = new TreeNode(currentToken, SpriteChangeNode);
773 preservedToken = currentToken;
774 getToken();
775 appendParameters(node);
776 matchToken(tokEOL);
777 return node;
780 TreeNode* Parser::FontType()
782 TreeNode* node = new TreeNode(currentToken, FontTypeNode);
783 preservedToken = currentToken;
784 getToken();
785 appendParameters(node);
786 matchToken(tokEOL);
787 return node;
790 TreeNode* Parser::FontSize()
792 TreeNode* node = new TreeNode(currentToken, FontSizeNode);
793 preservedToken = currentToken;
794 getToken();
795 appendParameters(node);
796 matchToken(tokEOL);
797 return node;
800 TreeNode* Parser::Wait()
802 TreeNode* node = new TreeNode(currentToken, WaitNode);
803 preservedToken = currentToken;
804 getToken();
805 appendParameters(node);
806 matchToken(tokEOL);
807 return node;
810 TreeNode* Parser::ExternalRun()
812 TreeNode* node = new TreeNode(currentToken, runNode);
813 preservedToken = currentToken;
814 getToken();
815 node->appendChild( Expression() );
816 // matchToken(tokEOL); this command can return values so can be used as expression/parameter
817 return node;
822 // Functions that take 2 arguments
824 TreeNode* Parser::Go()
826 TreeNode* node = new TreeNode(currentToken, GoNode);
827 preservedToken = currentToken;
828 getToken();
829 appendParameters(node);
830 matchToken(tokEOL);
831 return node;
834 TreeNode* Parser::ResizeCanvas()
836 TreeNode* node = new TreeNode(currentToken, ResizeCanvasNode);
837 preservedToken = currentToken;
838 getToken();
839 appendParameters(node);
840 matchToken(tokEOL);
841 return node;
844 TreeNode* Parser::Random()
846 TreeNode* node = new TreeNode(currentToken, RandomNode);
847 preservedToken = currentToken;
848 getToken();
849 appendParameters(node);
850 // matchToken(tokEOL); this command can return values so can be used as expression/parameter
851 return node;
857 // Functions that take 3 arguments
859 TreeNode* Parser::SetFgColor()
861 TreeNode* node = new TreeNode(currentToken, SetFgColorNode);
862 preservedToken = currentToken;
863 getToken();
864 appendParameters(node);
865 matchToken(tokEOL);
866 return node;
869 TreeNode* Parser::SetBgColor()
871 TreeNode* node = new TreeNode(currentToken, SetBgColorNode);
872 preservedToken = currentToken;
873 getToken();
874 appendParameters(node);
875 matchToken(tokEOL);
876 return node;
882 // Weirdo's (learn, execution controllers, print, and Other()s)
884 TreeNode* Parser::Learn()
886 preservedToken = currentToken;
887 matchToken(tokLearn); // skip the 'dummy' command
888 TreeNode* func = new TreeNode(currentToken, functionNode);
889 getToken(); // get the token after the function's name
891 TreeNode* idList = new TreeNode(currentToken, idListNode, "idlist");
892 if (currentToken.type != tokBegin)
894 if (currentToken.type == tokUnknown) idList->appendChild( getId() );
895 else
897 Error(currentToken, "Expected a parameter name or a '[' after the learn command.", 3030);
898 getToken(); // this recovers from the error
901 while (currentToken.type == tokComma)
903 matchToken(tokComma);
904 idList->appendChild( getId() );
907 func->appendChild(idList);
909 func->appendChild( Block() ); // do the Block() thing
911 learnedFunctionList.append( func->getLook() );
913 return func;
917 TreeNode* Parser::If()
919 TreeNode* node = new TreeNode(currentToken, ifNode);
920 preservedToken = currentToken;
921 matchToken(tokIf);
923 node->appendChild( Expression() );
925 if (currentToken.type == tokDo) getToken(); // skip dummy word 'do'
927 if (currentToken.type == tokBegin) node->appendChild( Block() ); // if followed by a block
928 else node->appendChild( Statement() ); // if followed by single statement
930 if (currentToken.type == tokElse) // else part
932 matchToken(tokElse);
934 if (currentToken.type == tokDo) getToken(); // next word
936 if(currentToken.type == tokBegin) node->appendChild( Block() ); // else is followed by block
937 else node->appendChild( Statement() );
940 return node;
944 TreeNode* Parser::While()
946 TreeNode* node = new TreeNode(currentToken, whileNode);
947 preservedToken = currentToken;
948 matchToken(tokWhile);
949 node->appendChild( Expression() );
950 node->appendChild( Block() );
951 return node;
955 TreeNode* Parser::For()
957 TreeNode* fNode = new TreeNode(currentToken, forNode);
958 preservedToken = currentToken;
959 matchToken(tokFor);
960 fNode->appendChild( getId() ); // loop id
961 matchToken(tokAssign);
963 fNode->appendChild( Expression() ); // start value expression
964 matchToken(tokTo);
965 fNode->appendChild( Expression() ); // stop value expression
967 if (currentToken.type == tokStep)
969 matchToken(tokStep);
970 fNode->appendChild( Expression() ); //step expression
973 while (currentToken.type == tokEOL) getToken(); // newlines are allowed
974 if (currentToken.type == tokBegin) fNode->appendChild( Block() ); // for followed by a block
975 else fNode->appendChild( Statement() ); // while followed by single statement
977 return fNode;
981 TreeNode* Parser::Repeat()
983 TreeNode* node = new TreeNode(currentToken, RepeatNode);
984 preservedToken = currentToken; // preserve token, else Match() will make sure it gets lost
985 matchToken(tokRepeat);
986 node->appendChild( Expression() );
987 node->appendChild( Block() );
988 return node;
993 TreeNode* Parser::ForEach()
995 TreeNode* fNode = new TreeNode(currentToken, forEachNode);
996 preservedToken = currentToken;
997 matchToken(tokForEach);
999 fNode->appendChild( Expression() );
1000 matchToken(tokIn);
1001 fNode->appendChild( Expression() );
1003 if (currentToken.type == tokBegin) fNode->appendChild( Block() ); // for followed by a block
1004 else fNode->appendChild( Statement() ); // while followed by single statement
1006 return fNode;
1009 TreeNode* Parser::Print()
1011 TreeNode* node = new TreeNode(currentToken, printNode);
1012 preservedToken = currentToken; // preserve token, else Match() will make sure it gets lost
1013 getToken();
1014 if (currentToken.type == tokEOL) return node; // print called without expressions
1015 node->appendChild( Expression() ); // first expression
1016 // following strings or expressions
1017 while (currentToken.type == tokComma)
1019 getToken(); // the comma
1020 node->appendChild( Expression() );
1022 matchToken(tokEOL);
1023 return node;
1026 TreeNode* Parser::Return()
1028 TreeNode* ret = new TreeNode(currentToken, returnNode);
1029 matchToken(tokReturn);
1031 ret->appendChild( Expression() );
1033 return ret;
1036 TreeNode* Parser::Break()
1038 TreeNode* brk = new TreeNode(currentToken, breakNode);
1039 matchToken(tokBreak);
1041 return brk;
1044 TreeNode* Parser::EndOfFile()
1046 TreeNode* node = new TreeNode(currentToken, EndOfFileNode);
1047 return node;
1050 TreeNode* Parser::Other()
1052 // this is either an assignment or a function call!
1053 kdDebug(0)<<"Parser::Other()"<<endl;
1054 Token rememberedToken = currentToken; // preserve token, else Match() will make sure it gets lost
1055 matchToken(tokUnknown);
1057 if (currentToken.type == tokAssign) return Assignment(rememberedToken);
1058 else if (learnedFunctionList.contains(rememberedToken.look) > 0)
1060 TreeNode* node;
1061 node = FunctionCall(rememberedToken);
1062 // node->setType(funcReturnNode);
1063 return node;
1066 Error(rememberedToken, i18n("'%1' is neither a Logo command nor a learned command.").arg(rememberedToken.look), 1020);
1067 TreeNode* errNode = new TreeNode(rememberedToken, Unknown);
1069 // skip the rest of the line
1070 while (currentToken.type != tokEOL) getToken();
1072 return errNode;
1076 void Parser::Error(Token& t, const QString& s, uint code)
1078 emit ErrorMsg(t, s, code);
1082 #include "parser.moc"