91 PushScope(); |
91 PushScope(); |
92 |
92 |
93 while (mLexer->GetNext()) |
93 while (mLexer->GetNext()) |
94 { |
94 { |
95 // Check if else is potentically valid |
95 // Check if else is potentically valid |
96 if (TokenIs (tkElse) && mCanElse == false) |
96 if (TokenIs (TK_Else) && mCanElse == false) |
97 Error ("else without preceding if"); |
97 Error ("else without preceding if"); |
98 |
98 |
99 if (TokenIs (tkElse) == false) |
99 if (TokenIs (TK_Else) == false) |
100 mCanElse = false; |
100 mCanElse = false; |
101 |
101 |
102 switch (mLexer->GetToken()->type) |
102 switch (mLexer->GetToken()->type) |
103 { |
103 { |
104 case tkState: |
104 case TK_State: |
105 ParseStateBlock(); |
105 ParseStateBlock(); |
106 break; |
106 break; |
107 |
107 |
108 case tkEvent: |
108 case TK_Event: |
109 ParseEventBlock(); |
109 ParseEventBlock(); |
110 break; |
110 break; |
111 |
111 |
112 case tkMainloop: |
112 case TK_Mainloop: |
113 ParseMainloop(); |
113 ParseMainloop(); |
114 break; |
114 break; |
115 |
115 |
116 case tkOnenter: |
116 case TK_Onenter: |
117 case tkOnexit: |
117 case TK_Onexit: |
118 ParseOnEnterExit(); |
118 ParseOnEnterExit(); |
119 break; |
119 break; |
120 |
120 |
121 case tkVar: |
121 case TK_Var: |
122 ParseVar(); |
122 ParseVar(); |
123 break; |
123 break; |
124 |
124 |
125 case tkGoto: |
125 case TK_Goto: |
126 ParseGoto(); |
126 ParseGoto(); |
127 break; |
127 break; |
128 |
128 |
129 case tkIf: |
129 case TK_If: |
130 ParseIf(); |
130 ParseIf(); |
131 break; |
131 break; |
132 |
132 |
133 case tkElse: |
133 case TK_Else: |
134 ParseElse(); |
134 ParseElse(); |
135 break; |
135 break; |
136 |
136 |
137 case tkWhile: |
137 case TK_While: |
138 ParseWhileBlock(); |
138 ParseWhileBlock(); |
139 break; |
139 break; |
140 |
140 |
141 case tkFor: |
141 case TK_For: |
142 ParseForBlock(); |
142 ParseForBlock(); |
143 break; |
143 break; |
144 |
144 |
145 case tkDo: |
145 case TK_Do: |
146 ParseDoBlock(); |
146 ParseDoBlock(); |
147 break; |
147 break; |
148 |
148 |
149 case tkSwitch: |
149 case TK_Switch: |
150 ParseSwitchBlock(); |
150 ParseSwitchBlock(); |
151 break; |
151 break; |
152 |
152 |
153 case tkCase: |
153 case TK_Case: |
154 ParseSwitchCase(); |
154 ParseSwitchCase(); |
155 break; |
155 break; |
156 |
156 |
157 case tkDefault: |
157 case TK_Default: |
158 ParseSwitchDefault(); |
158 ParseSwitchDefault(); |
159 break; |
159 break; |
160 |
160 |
161 case tkBreak: |
161 case TK_Break: |
162 ParseBreak(); |
162 ParseBreak(); |
163 break; |
163 break; |
164 |
164 |
165 case tkContinue: |
165 case TK_Continue: |
166 ParseContinue(); |
166 ParseContinue(); |
167 break; |
167 break; |
168 |
168 |
169 case tkBraceEnd: |
169 case TK_BraceEnd: |
170 ParseBlockEnd(); |
170 ParseBlockEnd(); |
171 break; |
171 break; |
172 |
172 |
173 case tkEventdef: |
173 case TK_Eventdef: |
174 ParseEventdef(); |
174 ParseEventdef(); |
175 break; |
175 break; |
176 |
176 |
177 case tkFuncdef: |
177 case TK_Funcdef: |
178 ParseFuncdef(); |
178 ParseFuncdef(); |
179 break; |
179 break; |
180 |
180 |
181 case tkSemicolon: |
181 case TK_Semicolon: |
182 break; |
182 break; |
183 |
183 |
184 default: |
184 default: |
185 { |
185 { |
186 // Check for labels |
186 // Check for labels |
187 Lexer::Token next; |
187 Lexer::Token next; |
188 |
188 |
189 if (TokenIs (tkSymbol) && |
189 if (TokenIs (TK_Symbol) && |
190 mLexer->PeekNext (&next) && |
190 mLexer->PeekNext (&next) && |
191 next.type == tkColon) |
191 next.type ==TK_Colon) |
192 { |
192 { |
193 ParseLabel(); |
193 ParseLabel(); |
194 break; |
194 break; |
195 } |
195 } |
196 |
196 |
254 // ============================================================================ |
254 // ============================================================================ |
255 // |
255 // |
256 void BotscriptParser::ParseStateBlock() |
256 void BotscriptParser::ParseStateBlock() |
257 { |
257 { |
258 CheckToplevel(); |
258 CheckToplevel(); |
259 mLexer->MustGetNext (tkString); |
259 mLexer->MustGetNext (TK_String); |
260 String statename = GetTokenString(); |
260 String statename = GetTokenString(); |
261 |
261 |
262 // State name must be a word. |
262 // State name must be a word. |
263 if (statename.FirstIndexOf (" ") != -1) |
263 if (statename.FirstIndexOf (" ") != -1) |
264 Error ("state name must be a single word, got `%1`", statename); |
264 Error ("state name must be a single word, got `%1`", statename); |
267 // encountered it, then mark down that we have it. |
267 // encountered it, then mark down that we have it. |
268 if (-statename == "statespawn") |
268 if (-statename == "statespawn") |
269 mStateSpawnDefined = true; |
269 mStateSpawnDefined = true; |
270 |
270 |
271 // Must end in a colon |
271 // Must end in a colon |
272 mLexer->MustGetNext (tkColon); |
272 mLexer->MustGetNext (TK_Colon); |
273 |
273 |
274 // write the previous state's onenter and |
274 // write the previous state's onenter and |
275 // mainloop buffers to file now |
275 // mainloop buffers to file now |
276 if (mCurrentState.IsEmpty() == false) |
276 if (mCurrentState.IsEmpty() == false) |
277 writeMemberBuffers(); |
277 writeMemberBuffers(); |
289 // ============================================================================ |
289 // ============================================================================ |
290 // |
290 // |
291 void BotscriptParser::ParseEventBlock() |
291 void BotscriptParser::ParseEventBlock() |
292 { |
292 { |
293 CheckToplevel(); |
293 CheckToplevel(); |
294 mLexer->MustGetNext (tkString); |
294 mLexer->MustGetNext (TK_String); |
295 |
295 |
296 EventDefinition* e = FindEventByName (GetTokenString()); |
296 EventDefinition* e = FindEventByName (GetTokenString()); |
297 |
297 |
298 if (e == null) |
298 if (e == null) |
299 Error ("bad event, got `%1`\n", GetTokenString()); |
299 Error ("bad event, got `%1`\n", GetTokenString()); |
300 |
300 |
301 mLexer->MustGetNext (tkBraceStart); |
301 mLexer->MustGetNext (TK_BraceStart); |
302 mCurrentMode = PARSERMODE_Event; |
302 mCurrentMode = PARSERMODE_Event; |
303 buffer()->WriteDWord (DH_Event); |
303 buffer()->WriteDWord (DH_Event); |
304 buffer()->WriteDWord (e->number); |
304 buffer()->WriteDWord (e->number); |
305 mNumEvents++; |
305 mNumEvents++; |
306 } |
306 } |
308 // ============================================================================ |
308 // ============================================================================ |
309 // |
309 // |
310 void BotscriptParser::ParseMainloop() |
310 void BotscriptParser::ParseMainloop() |
311 { |
311 { |
312 CheckToplevel(); |
312 CheckToplevel(); |
313 mLexer->MustGetNext (tkBraceStart); |
313 mLexer->MustGetNext (TK_BraceStart); |
314 |
314 |
315 mCurrentMode = PARSERMODE_MainLoop; |
315 mCurrentMode = PARSERMODE_MainLoop; |
316 mMainLoopBuffer->WriteDWord (DH_MainLoop); |
316 mMainLoopBuffer->WriteDWord (DH_MainLoop); |
317 } |
317 } |
318 |
318 |
319 // ============================================================================ |
319 // ============================================================================ |
320 // |
320 // |
321 void BotscriptParser::ParseOnEnterExit() |
321 void BotscriptParser::ParseOnEnterExit() |
322 { |
322 { |
323 CheckToplevel(); |
323 CheckToplevel(); |
324 bool onenter = (TokenIs (tkOnenter)); |
324 bool onenter = (TokenIs (TK_Onenter)); |
325 mLexer->MustGetNext (tkBraceStart); |
325 mLexer->MustGetNext (TK_BraceStart); |
326 |
326 |
327 mCurrentMode = onenter ? PARSERMODE_Onenter : PARSERMODE_Onexit; |
327 mCurrentMode = onenter ? PARSERMODE_Onenter : PARSERMODE_Onexit; |
328 buffer()->WriteDWord (onenter ? DH_OnEnter : DH_OnExit); |
328 buffer()->WriteDWord (onenter ? DH_OnEnter : DH_OnExit); |
329 } |
329 } |
330 |
330 |
333 void BotscriptParser::ParseVar() |
333 void BotscriptParser::ParseVar() |
334 { |
334 { |
335 Variable* var = new Variable; |
335 Variable* var = new Variable; |
336 var->origin = mLexer->DescribeCurrentPosition(); |
336 var->origin = mLexer->DescribeCurrentPosition(); |
337 var->isarray = false; |
337 var->isarray = false; |
338 const bool isconst = mLexer->GetNext (tkConst); |
338 const bool isconst = mLexer->GetNext (TK_Const); |
339 mLexer->MustGetAnyOf ({tkInt, tkStr, tkVoid}); |
339 mLexer->MustGetAnyOf ({TK_Int,TK_Str,TK_Void}); |
340 |
340 |
341 DataType vartype = (TokenIs (tkInt)) ? TYPE_Int : |
341 DataType vartype = (TokenIs (TK_Int)) ? TYPE_Int : |
342 (TokenIs (tkStr)) ? TYPE_String : |
342 (TokenIs (TK_Str)) ? TYPE_String : |
343 TYPE_Bool; |
343 TYPE_Bool; |
344 |
344 |
345 mLexer->MustGetNext (tkSymbol); |
345 mLexer->MustGetNext (TK_Symbol); |
346 String name = GetTokenString(); |
346 String name = GetTokenString(); |
347 |
347 |
348 if (mLexer->GetNext (tkBracketStart)) |
348 if (mLexer->GetNext (TK_BracketStart)) |
349 { |
349 { |
350 mLexer->MustGetNext (tkBracketEnd); |
350 mLexer->MustGetNext (TK_BracketEnd); |
351 var->isarray = true; |
351 var->isarray = true; |
352 |
352 |
353 if (isconst) |
353 if (isconst) |
354 Error ("arrays cannot be const"); |
354 Error ("arrays cannot be const"); |
355 } |
355 } |
369 { |
369 { |
370 var->writelevel = WRITE_Mutable; |
370 var->writelevel = WRITE_Mutable; |
371 } |
371 } |
372 else |
372 else |
373 { |
373 { |
374 mLexer->MustGetNext (tkAssign); |
374 mLexer->MustGetNext (TK_Assign); |
375 Expression expr (this, mLexer, vartype); |
375 Expression expr (this, mLexer, vartype); |
376 |
376 |
377 // If the expression was constexpr, we know its value and thus |
377 // If the expression was constexpr, we know its value and thus |
378 // can store it in the variable. |
378 // can store it in the variable. |
379 if (expr.GetResult()->IsConstexpr()) |
379 if (expr.GetResult()->IsConstexpr()) |
407 SCOPE(0).globalVariables << var; |
407 SCOPE(0).globalVariables << var; |
408 else |
408 else |
409 SCOPE(0).localVariables << var; |
409 SCOPE(0).localVariables << var; |
410 |
410 |
411 SuggestHighestVarIndex (IsInGlobalState(), var->index); |
411 SuggestHighestVarIndex (IsInGlobalState(), var->index); |
412 mLexer->MustGetNext (tkSemicolon); |
412 mLexer->MustGetNext (TK_Semicolon); |
413 Print ("Declared %3 variable #%1 $%2\n", var->index, var->name, IsInGlobalState() ? "global" : "state-local"); |
413 Print ("Declared %3 variable #%1 $%2\n", var->index, var->name, IsInGlobalState() ? "global" : "state-local"); |
414 } |
414 } |
415 |
415 |
416 // ============================================================================ |
416 // ============================================================================ |
417 // |
417 // |
418 void BotscriptParser::ParseGoto() |
418 void BotscriptParser::ParseGoto() |
419 { |
419 { |
420 CheckNotToplevel(); |
420 CheckNotToplevel(); |
421 |
421 |
422 // Get the name of the label |
422 // Get the name of the label |
423 mLexer->MustGetNext (tkSymbol); |
423 mLexer->MustGetNext (TK_Symbol); |
424 |
424 |
425 // Find the mark this goto statement points to |
425 // Find the mark this goto statement points to |
426 String target = GetTokenString(); |
426 String target = GetTokenString(); |
427 ByteMark* mark = buffer()->FindMarkByName (target); |
427 ByteMark* mark = buffer()->FindMarkByName (target); |
428 |
428 |
436 } |
436 } |
437 |
437 |
438 // Add a reference to the mark. |
438 // Add a reference to the mark. |
439 buffer()->WriteDWord (DH_Goto); |
439 buffer()->WriteDWord (DH_Goto); |
440 buffer()->AddReference (mark); |
440 buffer()->AddReference (mark); |
441 mLexer->MustGetNext (tkSemicolon); |
441 mLexer->MustGetNext (TK_Semicolon); |
442 } |
442 } |
443 |
443 |
444 // ============================================================================ |
444 // ============================================================================ |
445 // |
445 // |
446 void BotscriptParser::ParseIf() |
446 void BotscriptParser::ParseIf() |
447 { |
447 { |
448 CheckNotToplevel(); |
448 CheckNotToplevel(); |
449 PushScope(); |
449 PushScope(); |
450 |
450 |
451 // Condition |
451 // Condition |
452 mLexer->MustGetNext (tkParenStart); |
452 mLexer->MustGetNext (TK_ParenStart); |
453 |
453 |
454 // Read the expression and write it. |
454 // Read the expression and write it. |
455 DataBuffer* c = ParseExpression (TYPE_Int); |
455 DataBuffer* c = ParseExpression (TYPE_Int); |
456 buffer()->MergeAndDestroy (c); |
456 buffer()->MergeAndDestroy (c); |
457 |
457 |
458 mLexer->MustGetNext (tkParenEnd); |
458 mLexer->MustGetNext (TK_ParenEnd); |
459 mLexer->MustGetNext (tkBraceStart); |
459 mLexer->MustGetNext (TK_BraceStart); |
460 |
460 |
461 // Add a mark - to here temporarily - and add a reference to it. |
461 // Add a mark - to here temporarily - and add a reference to it. |
462 // Upon a closing brace, the mark will be adjusted. |
462 // Upon a closing brace, the mark will be adjusted. |
463 ByteMark* mark = buffer()->AddMark (""); |
463 ByteMark* mark = buffer()->AddMark (""); |
464 |
464 |
475 // ============================================================================ |
475 // ============================================================================ |
476 // |
476 // |
477 void BotscriptParser::ParseElse() |
477 void BotscriptParser::ParseElse() |
478 { |
478 { |
479 CheckNotToplevel(); |
479 CheckNotToplevel(); |
480 mLexer->MustGetNext (tkBraceStart); |
480 mLexer->MustGetNext (TK_BraceStart); |
481 PushScope (eNoReset); |
481 PushScope (eNoReset); |
482 |
482 |
483 if (SCOPE (0).type != SCOPE_If) |
483 if (SCOPE (0).type != SCOPE_If) |
484 Error ("else without preceding if"); |
484 Error ("else without preceding if"); |
485 |
485 |
509 // the beginning with a go-to statement. |
509 // the beginning with a go-to statement. |
510 ByteMark* mark1 = buffer()->AddMark (""); // start |
510 ByteMark* mark1 = buffer()->AddMark (""); // start |
511 ByteMark* mark2 = buffer()->AddMark (""); // end |
511 ByteMark* mark2 = buffer()->AddMark (""); // end |
512 |
512 |
513 // Condition |
513 // Condition |
514 mLexer->MustGetNext (tkParenStart); |
514 mLexer->MustGetNext (TK_ParenStart); |
515 DataBuffer* expr = ParseExpression (TYPE_Int); |
515 DataBuffer* expr = ParseExpression (TYPE_Int); |
516 mLexer->MustGetNext (tkParenEnd); |
516 mLexer->MustGetNext (TK_ParenEnd); |
517 mLexer->MustGetNext (tkBraceStart); |
517 mLexer->MustGetNext (TK_BraceStart); |
518 |
518 |
519 // write condition |
519 // write condition |
520 buffer()->MergeAndDestroy (expr); |
520 buffer()->MergeAndDestroy (expr); |
521 |
521 |
522 // Instruction to go to the end if it fails |
522 // Instruction to go to the end if it fails |
535 { |
535 { |
536 CheckNotToplevel(); |
536 CheckNotToplevel(); |
537 PushScope(); |
537 PushScope(); |
538 |
538 |
539 // Initializer |
539 // Initializer |
540 mLexer->MustGetNext (tkParenStart); |
540 mLexer->MustGetNext (TK_ParenStart); |
541 DataBuffer* init = ParseStatement(); |
541 DataBuffer* init = ParseStatement(); |
542 |
542 |
543 if (init == null) |
543 if (init == null) |
544 Error ("bad statement for initializer of for"); |
544 Error ("bad statement for initializer of for"); |
545 |
545 |
546 mLexer->MustGetNext (tkSemicolon); |
546 mLexer->MustGetNext (TK_Semicolon); |
547 |
547 |
548 // Condition |
548 // Condition |
549 DataBuffer* cond = ParseExpression (TYPE_Int); |
549 DataBuffer* cond = ParseExpression (TYPE_Int); |
550 |
550 |
551 if (cond == null) |
551 if (cond == null) |
552 Error ("bad statement for condition of for"); |
552 Error ("bad statement for condition of for"); |
553 |
553 |
554 mLexer->MustGetNext (tkSemicolon); |
554 mLexer->MustGetNext (TK_Semicolon); |
555 |
555 |
556 // Incrementor |
556 // Incrementor |
557 DataBuffer* incr = ParseStatement(); |
557 DataBuffer* incr = ParseStatement(); |
558 |
558 |
559 if (incr == null) |
559 if (incr == null) |
560 Error ("bad statement for incrementor of for"); |
560 Error ("bad statement for incrementor of for"); |
561 |
561 |
562 mLexer->MustGetNext (tkParenEnd); |
562 mLexer->MustGetNext (TK_ParenEnd); |
563 mLexer->MustGetNext (tkBraceStart); |
563 mLexer->MustGetNext (TK_BraceStart); |
564 |
564 |
565 // First, write out the initializer |
565 // First, write out the initializer |
566 buffer()->MergeAndDestroy (init); |
566 buffer()->MergeAndDestroy (init); |
567 |
567 |
568 // Init two marks |
568 // Init two marks |
609 // casemark3: ... |
609 // casemark3: ... |
610 // mark1: // end mark |
610 // mark1: // end mark |
611 |
611 |
612 CheckNotToplevel(); |
612 CheckNotToplevel(); |
613 PushScope(); |
613 PushScope(); |
614 mLexer->MustGetNext (tkParenStart); |
614 mLexer->MustGetNext (TK_ParenStart); |
615 buffer()->MergeAndDestroy (ParseExpression (TYPE_Int)); |
615 buffer()->MergeAndDestroy (ParseExpression (TYPE_Int)); |
616 mLexer->MustGetNext (tkParenEnd); |
616 mLexer->MustGetNext (TK_ParenEnd); |
617 mLexer->MustGetNext (tkBraceStart); |
617 mLexer->MustGetNext (TK_BraceStart); |
618 SCOPE (0).type = SCOPE_Switch; |
618 SCOPE (0).type = SCOPE_Switch; |
619 SCOPE (0).mark1 = buffer()->AddMark (""); // end mark |
619 SCOPE (0).mark1 = buffer()->AddMark (""); // end mark |
620 SCOPE (0).buffer1 = null; // default header |
620 SCOPE (0).buffer1 = null; // default header |
621 } |
621 } |
622 |
622 |
628 if (SCOPE (0).type != SCOPE_Switch) |
628 if (SCOPE (0).type != SCOPE_Switch) |
629 Error ("case label outside switch"); |
629 Error ("case label outside switch"); |
630 |
630 |
631 // Get a literal value for the case block. Zandronum does not support |
631 // Get a literal value for the case block. Zandronum does not support |
632 // expressions here. |
632 // expressions here. |
633 mLexer->MustGetNext (tkNumber); |
633 mLexer->MustGetNext (TK_Number); |
634 int num = mLexer->GetToken()->text.ToLong(); |
634 int num = mLexer->GetToken()->text.ToLong(); |
635 mLexer->MustGetNext (tkColon); |
635 mLexer->MustGetNext (TK_Colon); |
636 |
636 |
637 for (const CaseInfo& info : SCOPE(0).cases) |
637 for (const CaseInfo& info : SCOPE(0).cases) |
638 if (info.number == num) |
638 if (info.number == num) |
639 Error ("multiple case %1 labels in one switch", num); |
639 Error ("multiple case %1 labels in one switch", num); |
640 |
640 |
663 Error ("default label outside switch"); |
663 Error ("default label outside switch"); |
664 |
664 |
665 if (SCOPE (0).buffer1 != null) |
665 if (SCOPE (0).buffer1 != null) |
666 Error ("multiple default labels in one switch"); |
666 Error ("multiple default labels in one switch"); |
667 |
667 |
668 mLexer->MustGetNext (tkColon); |
668 mLexer->MustGetNext (TK_Colon); |
669 |
669 |
670 // The default header is buffered into buffer1, since |
670 // The default header is buffered into buffer1, since |
671 // it has to be the last of the case headers |
671 // it has to be the last of the case headers |
672 // |
672 // |
673 // Since the expression is pushed into the switch |
673 // Since the expression is pushed into the switch |
710 { |
710 { |
711 Error ("unexpected `break`"); |
711 Error ("unexpected `break`"); |
712 } break; |
712 } break; |
713 } |
713 } |
714 |
714 |
715 mLexer->MustGetNext (tkSemicolon); |
715 mLexer->MustGetNext (TK_Semicolon); |
716 } |
716 } |
717 |
717 |
718 // ============================================================================ |
718 // ============================================================================ |
719 // |
719 // |
720 void BotscriptParser::ParseContinue() |
720 void BotscriptParser::ParseContinue() |
721 { |
721 { |
722 mLexer->MustGetNext (tkSemicolon); |
722 mLexer->MustGetNext (TK_Semicolon); |
723 |
723 |
724 int curs; |
724 int curs; |
725 bool found = false; |
725 bool found = false; |
726 |
726 |
727 // Fall through the scope until we find a loop block |
727 // Fall through the scope until we find a loop block |
790 break; |
790 break; |
791 } |
791 } |
792 |
792 |
793 case SCOPE_Do: |
793 case SCOPE_Do: |
794 { |
794 { |
795 mLexer->MustGetNext (tkWhile); |
795 mLexer->MustGetNext (TK_While); |
796 mLexer->MustGetNext (tkParenStart); |
796 mLexer->MustGetNext (TK_ParenStart); |
797 DataBuffer* expr = ParseExpression (TYPE_Int); |
797 DataBuffer* expr = ParseExpression (TYPE_Int); |
798 mLexer->MustGetNext (tkParenEnd); |
798 mLexer->MustGetNext (TK_ParenEnd); |
799 mLexer->MustGetNext (tkSemicolon); |
799 mLexer->MustGetNext (TK_Semicolon); |
800 |
800 |
801 // If the condition runs true, go back to the start. |
801 // If the condition runs true, go back to the start. |
802 buffer()->MergeAndDestroy (expr); |
802 buffer()->MergeAndDestroy (expr); |
803 buffer()->WriteDWord (DH_IfGoto); |
803 buffer()->WriteDWord (DH_IfGoto); |
804 buffer()->AddReference (SCOPE (0).mark1); |
804 buffer()->AddReference (SCOPE (0).mark1); |
859 // Data header must be written before mode is changed because |
859 // Data header must be written before mode is changed because |
860 // onenter and mainloop go into special buffers, and we want |
860 // onenter and mainloop go into special buffers, and we want |
861 // the closing data headers into said buffers too. |
861 // the closing data headers into said buffers too. |
862 buffer()->WriteDWord (dataheader); |
862 buffer()->WriteDWord (dataheader); |
863 mCurrentMode = PARSERMODE_TopLevel; |
863 mCurrentMode = PARSERMODE_TopLevel; |
864 mLexer->GetNext (tkSemicolon); |
864 mLexer->GetNext (TK_Semicolon); |
865 } |
865 } |
866 |
866 |
867 // ============================================================================ |
867 // ============================================================================ |
868 // |
868 // |
869 void BotscriptParser::ParseLabel() |
869 void BotscriptParser::ParseLabel() |
888 |
888 |
889 // Not found in unmarked lists, define it now |
889 // Not found in unmarked lists, define it now |
890 if (mark == null) |
890 if (mark == null) |
891 buffer()->AddMark (labelName); |
891 buffer()->AddMark (labelName); |
892 |
892 |
893 mLexer->MustGetNext (tkColon); |
893 mLexer->MustGetNext (TK_Colon); |
894 } |
894 } |
895 |
895 |
896 // ============================================================================= |
896 // ============================================================================= |
897 // |
897 // |
898 void BotscriptParser::ParseEventdef() |
898 void BotscriptParser::ParseEventdef() |
899 { |
899 { |
900 EventDefinition* e = new EventDefinition; |
900 EventDefinition* e = new EventDefinition; |
901 |
901 |
902 mLexer->MustGetNext (tkNumber); |
902 mLexer->MustGetNext (TK_Number); |
903 e->number = GetTokenString().ToLong(); |
903 e->number = GetTokenString().ToLong(); |
904 mLexer->MustGetNext (tkColon); |
904 mLexer->MustGetNext (TK_Colon); |
905 mLexer->MustGetNext (tkSymbol); |
905 mLexer->MustGetNext (TK_Symbol); |
906 e->name = mLexer->GetToken()->text; |
906 e->name = mLexer->GetToken()->text; |
907 mLexer->MustGetNext (tkParenStart); |
907 mLexer->MustGetNext (TK_ParenStart); |
908 mLexer->MustGetNext (tkParenEnd); |
908 mLexer->MustGetNext (TK_ParenEnd); |
909 mLexer->MustGetNext (tkSemicolon); |
909 mLexer->MustGetNext (TK_Semicolon); |
910 AddEvent (e); |
910 AddEvent (e); |
911 } |
911 } |
912 |
912 |
913 // ============================================================================= |
913 // ============================================================================= |
914 // |
914 // |
916 { |
916 { |
917 CommandInfo* comm = new CommandInfo; |
917 CommandInfo* comm = new CommandInfo; |
918 comm->origin = mLexer->DescribeCurrentPosition(); |
918 comm->origin = mLexer->DescribeCurrentPosition(); |
919 |
919 |
920 // Return value |
920 // Return value |
921 mLexer->MustGetAnyOf ({tkInt, tkVoid, tkBool, tkStr}); |
921 mLexer->MustGetAnyOf ({TK_Int,TK_Void,TK_Bool,TK_Str}); |
922 comm->returnvalue = GetTypeByName (mLexer->GetToken()->text); // TODO |
922 comm->returnvalue = GetTypeByName (mLexer->GetToken()->text); // TODO |
923 assert (comm->returnvalue != -1); |
923 assert (comm->returnvalue != -1); |
924 |
924 |
925 // Number |
925 // Number |
926 mLexer->MustGetNext (tkNumber); |
926 mLexer->MustGetNext (TK_Number); |
927 comm->number = mLexer->GetToken()->text.ToLong(); |
927 comm->number = mLexer->GetToken()->text.ToLong(); |
928 mLexer->MustGetNext (tkColon); |
928 mLexer->MustGetNext (TK_Colon); |
929 |
929 |
930 // Name |
930 // Name |
931 mLexer->MustGetNext (tkSymbol); |
931 mLexer->MustGetNext (TK_Symbol); |
932 comm->name = mLexer->GetToken()->text; |
932 comm->name = mLexer->GetToken()->text; |
933 |
933 |
934 // Arguments |
934 // Arguments |
935 mLexer->MustGetNext (tkParenStart); |
935 mLexer->MustGetNext (TK_ParenStart); |
936 comm->minargs = 0; |
936 comm->minargs = 0; |
937 |
937 |
938 while (mLexer->PeekNextType (tkParenEnd) == false) |
938 while (mLexer->PeekNextType (TK_ParenEnd) == false) |
939 { |
939 { |
940 if (comm->args.IsEmpty() == false) |
940 if (comm->args.IsEmpty() == false) |
941 mLexer->MustGetNext (tkComma); |
941 mLexer->MustGetNext (TK_Comma); |
942 |
942 |
943 CommandArgument arg; |
943 CommandArgument arg; |
944 mLexer->MustGetAnyOf ({tkInt, tkBool, tkStr}); |
944 mLexer->MustGetAnyOf ({TK_Int,TK_Bool,TK_Str}); |
945 DataType type = GetTypeByName (mLexer->GetToken()->text); // TODO |
945 DataType type = GetTypeByName (mLexer->GetToken()->text); // TODO |
946 assert (type != -1 && type != TYPE_Void); |
946 assert (type != -1 && type != TYPE_Void); |
947 arg.type = type; |
947 arg.type = type; |
948 |
948 |
949 mLexer->MustGetNext (tkSymbol); |
949 mLexer->MustGetNext (TK_Symbol); |
950 arg.name = mLexer->GetToken()->text; |
950 arg.name = mLexer->GetToken()->text; |
951 |
951 |
952 // If this is an optional parameter, we need the default value. |
952 // If this is an optional parameter, we need the default value. |
953 if (comm->minargs < comm->args.Size() || mLexer->PeekNextType (tkAssign)) |
953 if (comm->minargs < comm->args.Size() || mLexer->PeekNextType (TK_Assign)) |
954 { |
954 { |
955 mLexer->MustGetNext (tkAssign); |
955 mLexer->MustGetNext (TK_Assign); |
956 |
956 |
957 switch (type) |
957 switch (type) |
958 { |
958 { |
959 case TYPE_Int: |
959 case TYPE_Int: |
960 case TYPE_Bool: |
960 case TYPE_Bool: |
961 mLexer->MustGetNext (tkNumber); |
961 mLexer->MustGetNext (TK_Number); |
962 break; |
962 break; |
963 |
963 |
964 case TYPE_String: |
964 case TYPE_String: |
965 Error ("string arguments cannot have default values"); |
965 Error ("string arguments cannot have default values"); |
966 |
966 |
989 DataBuffer* r = new DataBuffer (64); |
989 DataBuffer* r = new DataBuffer (64); |
990 |
990 |
991 if (mCurrentMode == PARSERMODE_TopLevel && comm->returnvalue == TYPE_Void) |
991 if (mCurrentMode == PARSERMODE_TopLevel && comm->returnvalue == TYPE_Void) |
992 Error ("command call at top level"); |
992 Error ("command call at top level"); |
993 |
993 |
994 mLexer->MustGetNext (tkParenStart); |
994 mLexer->MustGetNext (TK_ParenStart); |
995 mLexer->MustGetNext (tkAny); |
995 mLexer->MustGetNext (TK_Any); |
996 |
996 |
997 int curarg = 0; |
997 int curarg = 0; |
998 |
998 |
999 for (;;) |
999 for (;;) |
1000 { |
1000 { |
1001 if (TokenIs (tkParenEnd)) |
1001 if (TokenIs (TK_ParenEnd)) |
1002 { |
1002 { |
1003 if (curarg < comm->minargs) |
1003 if (curarg < comm->minargs) |
1004 Error ("too few arguments passed to %1\n\tusage is: %2", |
1004 Error ("too few arguments passed to %1\n\tusage is: %2", |
1005 comm->name, comm->GetSignature()); |
1005 comm->name, comm->GetSignature()); |
1006 |
1006 |
1010 if (curarg >= comm->args.Size()) |
1010 if (curarg >= comm->args.Size()) |
1011 Error ("too many arguments (%3) passed to %1\n\tusage is: %2", |
1011 Error ("too many arguments (%3) passed to %1\n\tusage is: %2", |
1012 comm->name, comm->GetSignature()); |
1012 comm->name, comm->GetSignature()); |
1013 |
1013 |
1014 r->MergeAndDestroy (ParseExpression (comm->args[curarg].type, true)); |
1014 r->MergeAndDestroy (ParseExpression (comm->args[curarg].type, true)); |
1015 mLexer->MustGetNext (tkAny); |
1015 mLexer->MustGetNext (TK_Any); |
1016 |
1016 |
1017 if (curarg < comm->minargs - 1) |
1017 if (curarg < comm->minargs - 1) |
1018 { |
1018 { |
1019 mLexer->TokenMustBe (tkComma); |
1019 mLexer->TokenMustBe (TK_Comma); |
1020 mLexer->MustGetNext (tkAny); |
1020 mLexer->MustGetNext (TK_Any); |
1021 } |
1021 } |
1022 else if (curarg < comm->args.Size() - 1) |
1022 else if (curarg < comm->args.Size() - 1) |
1023 { |
1023 { |
1024 // Can continue, but can terminate as well. |
1024 // Can continue, but can terminate as well. |
1025 if (TokenIs (tkParenEnd)) |
1025 if (TokenIs (TK_ParenEnd)) |
1026 { |
1026 { |
1027 curarg++; |
1027 curarg++; |
1028 break; |
1028 break; |
1029 } |
1029 } |
1030 else |
1030 else |
1031 { |
1031 { |
1032 mLexer->TokenMustBe (tkComma); |
1032 mLexer->TokenMustBe (TK_Comma); |
1033 mLexer->MustGetNext (tkAny); |
1033 mLexer->MustGetNext (TK_Any); |
1034 } |
1034 } |
1035 } |
1035 } |
1036 |
1036 |
1037 curarg++; |
1037 curarg++; |
1038 } |
1038 } |
1054 |
1054 |
1055 // ============================================================================ |
1055 // ============================================================================ |
1056 // |
1056 // |
1057 String BotscriptParser::ParseFloat() |
1057 String BotscriptParser::ParseFloat() |
1058 { |
1058 { |
1059 mLexer->TokenMustBe (tkNumber); |
1059 mLexer->TokenMustBe (TK_Number); |
1060 String floatstring = GetTokenString(); |
1060 String floatstring = GetTokenString(); |
1061 Lexer::Token tok; |
1061 Lexer::Token tok; |
1062 |
1062 |
1063 // Go after the decimal point |
1063 // Go after the decimal point |
1064 if (mLexer->PeekNext (&tok) && tok.type == tkDot) |
1064 if (mLexer->PeekNext (&tok) && tok.type ==TK_Dot) |
1065 { |
1065 { |
1066 mLexer->Skip(); |
1066 mLexer->Skip(); |
1067 mLexer->MustGetNext (tkNumber); |
1067 mLexer->MustGetNext (TK_Number); |
1068 floatstring += "."; |
1068 floatstring += "."; |
1069 floatstring += GetTokenString(); |
1069 floatstring += GetTokenString(); |
1070 } |
1070 } |
1071 |
1071 |
1072 return floatstring; |
1072 return floatstring; |
1076 // |
1076 // |
1077 // Parses an assignment operator. |
1077 // Parses an assignment operator. |
1078 // |
1078 // |
1079 AssignmentOperator BotscriptParser::ParseAssignmentOperator() |
1079 AssignmentOperator BotscriptParser::ParseAssignmentOperator() |
1080 { |
1080 { |
1081 const List<EToken> tokens = |
1081 const List<TokenType> tokens = |
1082 { |
1082 { |
1083 tkAssign, |
1083 TK_Assign, |
1084 tkAddAssign, |
1084 TK_AddAssign, |
1085 tkSubAssign, |
1085 TK_SubAssign, |
1086 tkMultiplyAssign, |
1086 TK_MultiplyAssign, |
1087 tkDivideAssign, |
1087 TK_DivideAssign, |
1088 tkModulusAssign, |
1088 TK_ModulusAssign, |
1089 tkDoublePlus, |
1089 TK_DoublePlus, |
1090 tkDoubleMinus, |
1090 TK_DoubleMinus, |
1091 }; |
1091 }; |
1092 |
1092 |
1093 mLexer->MustGetAnyOf (tokens); |
1093 mLexer->MustGetAnyOf (tokens); |
1094 |
1094 |
1095 switch (mLexer->GetTokenType()) |
1095 switch (mLexer->GetTokenType()) |
1096 { |
1096 { |
1097 case tkAssign: return ASSIGNOP_Assign; |
1097 case TK_Assign: return ASSIGNOP_Assign; |
1098 case tkAddAssign: return ASSIGNOP_Add; |
1098 case TK_AddAssign: return ASSIGNOP_Add; |
1099 case tkSubAssign: return ASSIGNOP_Subtract; |
1099 case TK_SubAssign: return ASSIGNOP_Subtract; |
1100 case tkMultiplyAssign: return ASSIGNOP_Multiply; |
1100 case TK_MultiplyAssign: return ASSIGNOP_Multiply; |
1101 case tkDivideAssign: return ASSIGNOP_Divide; |
1101 case TK_DivideAssign: return ASSIGNOP_Divide; |
1102 case tkModulusAssign: return ASSIGNOP_Modulus; |
1102 case TK_ModulusAssign: return ASSIGNOP_Modulus; |
1103 case tkDoublePlus: return ASSIGNOP_Increase; |
1103 case TK_DoublePlus: return ASSIGNOP_Increase; |
1104 case tkDoubleMinus: return ASSIGNOP_Decrease; |
1104 case TK_DoubleMinus: return ASSIGNOP_Decrease; |
1105 default: break; |
1105 default: break; |
1106 } |
1106 } |
1107 |
1107 |
1108 assert (false); |
1108 assert (false); |
1109 return (AssignmentOperator) 0; |
1109 return (AssignmentOperator) 0; |
1165 if (var->writelevel != WRITE_Mutable) |
1165 if (var->writelevel != WRITE_Mutable) |
1166 Error ("cannot alter read-only variable $%1", var->name); |
1166 Error ("cannot alter read-only variable $%1", var->name); |
1167 |
1167 |
1168 if (var->isarray) |
1168 if (var->isarray) |
1169 { |
1169 { |
1170 mLexer->MustGetNext (tkBracketStart); |
1170 mLexer->MustGetNext (TK_BracketStart); |
1171 Expression expr (this, mLexer, TYPE_Int); |
1171 Expression expr (this, mLexer, TYPE_Int); |
1172 expr.GetResult()->ConvertToBuffer(); |
1172 expr.GetResult()->ConvertToBuffer(); |
1173 arrayindex = expr.GetResult()->GetBuffer()->Clone(); |
1173 arrayindex = expr.GetResult()->GetBuffer()->Clone(); |
1174 mLexer->MustGetNext (tkBracketEnd); |
1174 mLexer->MustGetNext (TK_BracketEnd); |
1175 } |
1175 } |
1176 |
1176 |
1177 // Get an operator |
1177 // Get an operator |
1178 AssignmentOperator oper = ParseAssignmentOperator(); |
1178 AssignmentOperator oper = ParseAssignmentOperator(); |
1179 |
1179 |
1262 // ============================================================================ |
1262 // ============================================================================ |
1263 // |
1263 // |
1264 DataBuffer* BotscriptParser::ParseStatement() |
1264 DataBuffer* BotscriptParser::ParseStatement() |
1265 { |
1265 { |
1266 // If it's a variable, expect assignment. |
1266 // If it's a variable, expect assignment. |
1267 if (mLexer->GetNext (tkDollarSign)) |
1267 if (mLexer->GetNext (TK_DollarSign)) |
1268 { |
1268 { |
1269 mLexer->MustGetNext (tkSymbol); |
1269 mLexer->MustGetNext (TK_Symbol); |
1270 Variable* var = FindVariable (GetTokenString()); |
1270 Variable* var = FindVariable (GetTokenString()); |
1271 |
1271 |
1272 if (var == null) |
1272 if (var == null) |
1273 Error ("unknown variable $%1", var->name); |
1273 Error ("unknown variable $%1", var->name); |
1274 |
1274 |