parser.cxx

changeset 41
47e686c96d8f
parent 40
9e4f785501db
child 42
5cd91fd1526c
equal deleted inserted replaced
40:9e4f785501db 41:47e686c96d8f
52 #include "variables.h" 52 #include "variables.h"
53 53
54 #define MUST_TOPLEVEL if (g_CurMode != MODE_TOPLEVEL) \ 54 #define MUST_TOPLEVEL if (g_CurMode != MODE_TOPLEVEL) \
55 ParserError ("%s-statements may only be defined at top level!", token.chars()); 55 ParserError ("%s-statements may only be defined at top level!", token.chars());
56 56
57 #define MUST_NOT_TOPLEVEL if (g_CurMode != MODE_TOPLEVEL) \ 57 #define MUST_NOT_TOPLEVEL if (g_CurMode == MODE_TOPLEVEL) \
58 ParserError ("%s-statements may not be defined at top level!", token.chars()); 58 ParserError ("%s-statements may not be defined at top level!", token.chars());
59 59
60 int g_NumStates = 0; 60 int g_NumStates = 0;
61 int g_NumEvents = 0; 61 int g_NumEvents = 0;
62 int g_CurMode = MODE_TOPLEVEL; 62 int g_CurMode = MODE_TOPLEVEL;
170 continue; 170 continue;
171 } 171 }
172 172
173 // Label 173 // Label
174 if (!PeekNext().compare (":")) { 174 if (!PeekNext().compare (":")) {
175 MUST_NOT_TOPLEVEL
176
175 if (IsKeyword (token)) 177 if (IsKeyword (token))
176 ParserError ("label name `%s` conflicts with keyword\n", token.chars()); 178 ParserError ("label name `%s` conflicts with keyword\n", token.chars());
177 if (FindCommand (token)) 179 if (FindCommand (token))
178 ParserError ("label name `%s` conflicts with command name\n", token.chars()); 180 ParserError ("label name `%s` conflicts with command name\n", token.chars());
179 if (FindGlobalVariable (token)) 181 if (FindGlobalVariable (token))
184 continue; 186 continue;
185 } 187 }
186 188
187 // Goto 189 // Goto
188 if (!token.icompare ("goto")) { 190 if (!token.icompare ("goto")) {
191 MUST_NOT_TOPLEVEL
192
189 // Get the name of the label 193 // Get the name of the label
190 MustNext (); 194 MustNext ();
191 195
192 // Find the mark this goto statement points to 196 // Find the mark this goto statement points to
193 unsigned int m = w->FindMark (MARKTYPE_LABEL, token); 197 unsigned int m = w->FindMark (MARKTYPE_LABEL, token);
201 continue; 205 continue;
202 } 206 }
203 207
204 // If 208 // If
205 if (!token.icompare ("if")) { 209 if (!token.icompare ("if")) {
210 MUST_NOT_TOPLEVEL
211 PushBlockStack ();
212
206 // Condition 213 // Condition
207 MustNext ("("); 214 MustNext ("(");
208 215
209 // Read the expression and write it. Store it to memory too for else statements. 216 // Read the expression and write it. Store it to memory too for else statements.
210 MustNext (); 217 MustNext ();
212 w->WriteBuffer (c); 219 w->WriteBuffer (c);
213 220
214 MustNext (")"); 221 MustNext (")");
215 MustNext ("{"); 222 MustNext ("{");
216 223
224 // Add a mark - to here temporarily - and add a reference to it.
225 // Upon a closing brace, the mark will be adjusted.
226 unsigned int marknum = w->AddMark (MARKTYPE_IF, "");
227
217 // Use DH_IFNOTGOTO - if the expression is not true, we goto the mark 228 // Use DH_IFNOTGOTO - if the expression is not true, we goto the mark
218 // we just defined - and this mark will be at the end of the block. 229 // we just defined - and this mark will be at the end of the block.
219 AddBlockMark (w, DH_IFNOTGOTO); 230 w->Write<word> (DH_IFNOTGOTO);
231 w->AddReference (marknum);
232
233 // Store it in the block stack
234 blockstack[g_BlockStackCursor].mark1 = marknum;
235 blockstack[g_BlockStackCursor].type = BLOCKTYPE_IF;
236 continue;
237 }
238
239 // While
240 if (!token.compare ("while")) {
241 printf ("begin while loop\n");
242 MUST_NOT_TOPLEVEL
243 PushBlockStack ();
244
245 // While loops need two marks - one at the start of the loop and one at the
246 // end. The condition is checked at the very start of the loop, if it fails,
247 // we use goto to skip to the end of the loop. At the end, we loop back to
248 // the beginning with a go-to statement.
249 unsigned int mark1 = w->AddMark (MARKTYPE_INTERNAL, ""); // start
250 unsigned int mark2 = w->AddMark (MARKTYPE_INTERNAL, ""); // end
251
252 // Condition
253 MustNext ("(");
254 MustNext ();
255 DataBuffer* expr = ParseExpression (TYPE_INT);
256 MustNext (")");
257
258 MustNext ("{");
259
260 // Write condition
261 w->WriteBuffer (expr);
262
263 // Instruction to go to the end if it fails
264 w->Write<word> (DH_IFNOTGOTO);
265 w->AddReference (mark2);
266
267 // Store the needed stuff
268 blockstack[g_BlockStackCursor].mark1 = mark1;
269 blockstack[g_BlockStackCursor].mark2 = mark2;
270 blockstack[g_BlockStackCursor].type = BLOCKTYPE_WHILE;
220 continue; 271 continue;
221 } 272 }
222 273
223 if (!token.compare ("}")) { 274 if (!token.compare ("}")) {
224 // Closing brace 275 // Closing brace
225 276
226 // If we're in the block stack, we're descending down from it now 277 // If we're in the block stack, we're descending down from it now
227 if (g_BlockStackCursor > 0) { 278 if (g_BlockStackCursor > 0) {
228 // Adjust its closing mark so that it's here. 279 BlockInformation* info = &blockstack[g_BlockStackCursor];
229 unsigned int marknum = blockstack[g_BlockStackCursor]; 280 switch (info->type) {
230 if (marknum != MAX_MARKS) 281 case BLOCKTYPE_IF:
231 w->MoveMark (marknum); 282 printf ("end if\n");
232 w->AddMark (MARKTYPE_INTERNAL, ""); 283 // Adjust the closing mark.
284 w->MoveMark (info->mark1);
285 break;
286 case BLOCKTYPE_WHILE:
287 printf ("end while loop\n");
288
289 // Write down the instruction to go back to the start of the loop
290 w->Write (DH_GOTO);
291 w->AddReference (info->mark1);
292
293 // Move the closing mark here since we're at the end of the while loop
294 w->MoveMark (info->mark2);
295
296 // Offset it by 4 since the parser doesn't like having marks directly afte refs
297 w->OffsetMark (info->mark2, sizeof (word)*2);
298 }
299
300 // Descend down the stack
233 g_BlockStackCursor--; 301 g_BlockStackCursor--;
234 continue; 302 continue;
235 } 303 }
236 304
237 int dataheader = (g_CurMode == MODE_EVENT) ? DH_ENDEVENT : 305 int dataheader = (g_CurMode == MODE_EVENT) ? DH_ENDEVENT :
553 retbuf->Write<word> (var->index); 621 retbuf->Write<word> (var->index);
554 622
555 return retbuf; 623 return retbuf;
556 } 624 }
557 625
558 void ScriptReader::AddBlockMark (ObjWriter* w, word dataheader) { 626 void ScriptReader::PushBlockStack () {
559 // Add a mark - to here temporarily - and add a reference to it. 627 BlockInformation* info = &blockstack[g_BlockStackCursor];
560 // Upon a closing brace, the mark will be adjusted. 628 info->type = 0;
561 unsigned int marknum = w->AddMark (MARKTYPE_IF, ""); 629 info->mark1 = 0;
562 630 info->mark2 = 0;
563 // Write the header and store reference to the mark
564 w->Write<word> (dataheader);
565 w->AddReference (marknum);
566
567 // Store it in the block stack
568 g_BlockStackCursor++; 631 g_BlockStackCursor++;
569 blockstack[g_BlockStackCursor] = marknum; 632 }
570 }

mercurial