parser.cxx

changeset 43
1b35c9985989
parent 42
5cd91fd1526c
child 44
6bbaebc472b5
equal deleted inserted replaced
42:5cd91fd1526c 43:1b35c9985989
70 // Main parser code. Begins read of the script file, checks the syntax of it 70 // Main parser code. Begins read of the script file, checks the syntax of it
71 // and writes the data to the object file via ObjWriter - which also takes care 71 // and writes the data to the object file via ObjWriter - which also takes care
72 // of necessary buffering so stuff is written in the correct order. 72 // of necessary buffering so stuff is written in the correct order.
73 void ScriptReader::BeginParse (ObjWriter* w) { 73 void ScriptReader::BeginParse (ObjWriter* w) {
74 while (Next()) { 74 while (Next()) {
75 // ============================================================
75 if (!token.icompare ("state")) { 76 if (!token.icompare ("state")) {
76 MUST_TOPLEVEL 77 MUST_TOPLEVEL
77 78
78 MustString (); 79 MustString ();
79 80
104 g_CurState = token; 105 g_CurState = token;
105 g_GotMainLoop = false; 106 g_GotMainLoop = false;
106 continue; 107 continue;
107 } 108 }
108 109
110 // ============================================================
109 if (!token.icompare ("event")) { 111 if (!token.icompare ("event")) {
110 MUST_TOPLEVEL 112 MUST_TOPLEVEL
111 113
112 // Event definition 114 // Event definition
113 MustString (); 115 MustString ();
124 w->Write<word> (e->number); 126 w->Write<word> (e->number);
125 g_NumEvents++; 127 g_NumEvents++;
126 continue; 128 continue;
127 } 129 }
128 130
131 // ============================================================
129 if (!token.icompare ("mainloop")) { 132 if (!token.icompare ("mainloop")) {
130 MUST_TOPLEVEL 133 MUST_TOPLEVEL
131 MustNext ("{"); 134 MustNext ("{");
132 135
133 // Mode must be set before dataheader is written here! 136 // Mode must be set before dataheader is written here!
134 g_CurMode = MODE_MAINLOOP; 137 g_CurMode = MODE_MAINLOOP;
135 w->Write (DH_MAINLOOP); 138 w->Write (DH_MAINLOOP);
136 continue; 139 continue;
137 } 140 }
138 141
142 // ============================================================
139 if (!token.icompare ("onenter") || !token.icompare ("onexit")) { 143 if (!token.icompare ("onenter") || !token.icompare ("onexit")) {
140 MUST_TOPLEVEL 144 MUST_TOPLEVEL
141 bool onenter = !token.compare ("onenter"); 145 bool onenter = !token.compare ("onenter");
142 MustNext ("{"); 146 MustNext ("{");
143 147
146 g_CurMode = onenter ? MODE_ONENTER : MODE_ONEXIT; 150 g_CurMode = onenter ? MODE_ONENTER : MODE_ONEXIT;
147 w->Write (onenter ? DH_ONENTER : DH_ONEXIT); 151 w->Write (onenter ? DH_ONENTER : DH_ONEXIT);
148 continue; 152 continue;
149 } 153 }
150 154
155 // ============================================================
151 if (!token.compare ("var")) { 156 if (!token.compare ("var")) {
152 // For now, only globals are supported 157 // For now, only globals are supported
153 if (g_CurMode != MODE_TOPLEVEL || g_CurState.len()) 158 if (g_CurMode != MODE_TOPLEVEL || g_CurState.len())
154 ParserError ("variables must only be global for now"); 159 ParserError ("variables must only be global for now");
155 160
168 173
169 MustNext (";"); 174 MustNext (";");
170 continue; 175 continue;
171 } 176 }
172 177
178 // ============================================================
173 // Label 179 // Label
174 if (!PeekNext().compare (":")) { 180 if (!PeekNext().compare (":")) {
175 MUST_NOT_TOPLEVEL 181 MUST_NOT_TOPLEVEL
176 182
177 if (IsKeyword (token)) 183 if (IsKeyword (token))
184 w->AddMark (MARKTYPE_LABEL, token); 190 w->AddMark (MARKTYPE_LABEL, token);
185 MustNext (":"); 191 MustNext (":");
186 continue; 192 continue;
187 } 193 }
188 194
195 // ============================================================
189 // Goto 196 // Goto
190 if (!token.icompare ("goto")) { 197 if (!token.icompare ("goto")) {
191 MUST_NOT_TOPLEVEL 198 MUST_NOT_TOPLEVEL
192 199
193 // Get the name of the label 200 // Get the name of the label
203 w->AddReference (m); 210 w->AddReference (m);
204 MustNext (";"); 211 MustNext (";");
205 continue; 212 continue;
206 } 213 }
207 214
215 // ============================================================
208 // If 216 // If
209 if (!token.icompare ("if")) { 217 if (!token.icompare ("if")) {
210 MUST_NOT_TOPLEVEL 218 MUST_NOT_TOPLEVEL
211 PushBlockStack (); 219 PushBlockStack ();
212 220
234 blockstack[g_BlockStackCursor].mark1 = marknum; 242 blockstack[g_BlockStackCursor].mark1 = marknum;
235 blockstack[g_BlockStackCursor].type = BLOCKTYPE_IF; 243 blockstack[g_BlockStackCursor].type = BLOCKTYPE_IF;
236 continue; 244 continue;
237 } 245 }
238 246
247 // ============================================================
239 // While 248 // While
240 if (!token.compare ("while")) { 249 if (!token.compare ("while")) {
241 MUST_NOT_TOPLEVEL 250 MUST_NOT_TOPLEVEL
242 PushBlockStack (); 251 PushBlockStack ();
243 252
268 blockstack[g_BlockStackCursor].mark2 = mark2; 277 blockstack[g_BlockStackCursor].mark2 = mark2;
269 blockstack[g_BlockStackCursor].type = BLOCKTYPE_WHILE; 278 blockstack[g_BlockStackCursor].type = BLOCKTYPE_WHILE;
270 continue; 279 continue;
271 } 280 }
272 281
282 // ============================================================
283 // For loop
284 if (!token.icompare ("for")) {
285 MUST_NOT_TOPLEVEL
286 PushBlockStack ();
287
288 // Initializer
289 MustNext ("(");
290 MustNext ();
291 DataBuffer* init = ParseStatement (w);
292 MustNext (";");
293
294 // Condition
295 MustNext ();
296 DataBuffer* cond = ParseExpression (TYPE_INT);
297 MustNext (";");
298
299 // Incrementor
300 MustNext ();
301 DataBuffer* incr = ParseStatement (w);
302 MustNext (")");
303 MustNext ("{");
304
305 // First, write out the initializer
306 w->WriteBuffer (init);
307
308 // Init two marks
309 int mark1 = w->AddMark (MARKTYPE_INTERNAL, "");
310 int mark2 = w->AddMark (MARKTYPE_INTERNAL, "");
311
312 // Add the condition
313 w->WriteBuffer (cond);
314 w->Write<long> (DH_IFNOTGOTO);
315 w->AddReference (mark2);
316
317 // Store the marks and incrementor
318 blockstack[g_BlockStackCursor].mark1 = mark1;
319 blockstack[g_BlockStackCursor].mark2 = mark2;
320 blockstack[g_BlockStackCursor].buffer1 = incr;
321 blockstack[g_BlockStackCursor].type = BLOCKTYPE_FOR;
322 continue;
323 }
324
325 // ============================================================
273 if (!token.compare ("}")) { 326 if (!token.compare ("}")) {
274 // Closing brace 327 // Closing brace
275 328
276 // If we're in the block stack, we're descending down from it now 329 // If we're in the block stack, we're descending down from it now
277 if (g_BlockStackCursor > 0) { 330 if (g_BlockStackCursor > 0) {
279 switch (info->type) { 332 switch (info->type) {
280 case BLOCKTYPE_IF: 333 case BLOCKTYPE_IF:
281 // Adjust the closing mark. 334 // Adjust the closing mark.
282 w->MoveMark (info->mark1); 335 w->MoveMark (info->mark1);
283 break; 336 break;
337 case BLOCKTYPE_FOR:
338 // Write the incrementor at the end of the loop block
339 w->WriteBuffer (info->buffer1);
340 // fall-thru
284 case BLOCKTYPE_WHILE: 341 case BLOCKTYPE_WHILE:
285 // Write down the instruction to go back to the start of the loop 342 // Write down the instruction to go back to the start of the loop
286 w->Write (DH_GOTO); 343 w->Write (DH_GOTO);
287 w->AddReference (info->mark1); 344 w->AddReference (info->mark1);
288 345
312 if (!PeekNext().compare (";")) 369 if (!PeekNext().compare (";"))
313 MustNext (";"); 370 MustNext (";");
314 continue; 371 continue;
315 } 372 }
316 373
317 // If it's a variable, expect assignment. 374 // ============================================================
318 if (ScriptVar* var = FindGlobalVariable (token)) { 375 // If nothing else, parse it as a statement (which is either
319 DataBuffer* b = ParseAssignment (var); 376 // assignment or expression)
320 MustNext (";"); 377 DataBuffer* b = ParseStatement (w);
321 w->WriteBuffer (b);
322 continue;
323 }
324
325 // If it's not a keyword, parse it as an expression.
326 DataBuffer* b = ParseExpression (TYPE_VOID);
327 w->WriteBuffer (b); 378 w->WriteBuffer (b);
328 MustNext (";"); 379 MustNext (";");
329 } 380 }
330 381
331 if (g_CurMode != MODE_TOPLEVEL) 382 if (g_CurMode != MODE_TOPLEVEL)
477 528
478 // Parse the right operand, 529 // Parse the right operand,
479 MustNext (); 530 MustNext ();
480 DataBuffer* rb = ParseExprValue (reqtype); 531 DataBuffer* rb = ParseExprValue (reqtype);
481 532
533 retbuf->Merge (lb);
482 retbuf->Merge (rb); 534 retbuf->Merge (rb);
483 retbuf->Merge (lb);
484 535
485 long dh = DataHeaderByOperator (NULL, oper); 536 long dh = DataHeaderByOperator (NULL, oper);
486 retbuf->Write<word> (dh); 537 retbuf->Write<word> (dh);
487 return retbuf; 538 return retbuf;
488 } 539 }
620 g_BlockStackCursor++; 671 g_BlockStackCursor++;
621 BlockInformation* info = &blockstack[g_BlockStackCursor]; 672 BlockInformation* info = &blockstack[g_BlockStackCursor];
622 info->type = 0; 673 info->type = 0;
623 info->mark1 = 0; 674 info->mark1 = 0;
624 info->mark2 = 0; 675 info->mark2 = 0;
625 } 676 info->buffer1 = NULL;
677 }
678
679 DataBuffer* ScriptReader::ParseStatement (ObjWriter* w) {
680 // If it's a variable, expect assignment.
681 if (ScriptVar* var = FindGlobalVariable (token)) {
682 DataBuffer* b = ParseAssignment (var);
683 return b;
684 }
685
686 // If it's not a keyword, parse it as an expression.
687 DataBuffer* b = ParseExpression (TYPE_VOID);
688 return b;
689 }

mercurial