parser.cxx

changeset 36
a8838b5f1213
parent 35
3d3f6ed40171
child 37
c349dca807f9
equal deleted inserted replaced
35:3d3f6ed40171 36:a8838b5f1213
60 str g_CurState = ""; 60 str g_CurState = "";
61 bool g_stateSpawnDefined = false; 61 bool g_stateSpawnDefined = false;
62 bool g_GotMainLoop = false; 62 bool g_GotMainLoop = false;
63 63
64 // ============================================================================ 64 // ============================================================================
65 // Main parser 65 // Main parser code. Begins read of the script file, checks the syntax of it
66 // and writes the data to the object file via ObjWriter - which also takes care
67 // of necessary buffering so stuff is written in the correct order.
66 void ScriptReader::BeginParse (ObjWriter* w) { 68 void ScriptReader::BeginParse (ObjWriter* w) {
67 while (Next()) { 69 while (Next()) {
70 printf ("BeginParse: token: `%s`\n", token.chars());
68 if (!token.icompare ("state")) { 71 if (!token.icompare ("state")) {
69 MUST_TOPLEVEL 72 MUST_TOPLEVEL
70 73
71 MustString (); 74 MustString ();
72 75
112 MustNext ("{"); 115 MustNext ("{");
113 116
114 g_CurMode = MODE_EVENT; 117 g_CurMode = MODE_EVENT;
115 118
116 w->Write (DH_EVENT); 119 w->Write (DH_EVENT);
117 w->Write<byte> (e->number); 120 w->Write<word> (e->number);
118 g_NumEvents++; 121 g_NumEvents++;
119 continue; 122 continue;
120 } 123 }
121 124
122 if (!token.icompare ("mainloop")) { 125 if (!token.icompare ("mainloop")) {
162 MustNext (";"); 165 MustNext (";");
163 continue; 166 continue;
164 } 167 }
165 168
166 if (!token.compare ("}")) { 169 if (!token.compare ("}")) {
170 printf ("parse closing brace\n");
167 // Closing brace 171 // Closing brace
168 int dataheader = (g_CurMode == MODE_EVENT) ? DH_ENDEVENT : 172 int dataheader = (g_CurMode == MODE_EVENT) ? DH_ENDEVENT :
169 (g_CurMode == MODE_MAINLOOP) ? DH_ENDMAINLOOP : 173 (g_CurMode == MODE_MAINLOOP) ? DH_ENDMAINLOOP :
170 (g_CurMode == MODE_ONENTER) ? DH_ENDONENTER : 174 (g_CurMode == MODE_ONENTER) ? DH_ENDONENTER :
171 (g_CurMode == MODE_ONEXIT) ? DH_ENDONEXIT : -1; 175 (g_CurMode == MODE_ONEXIT) ? DH_ENDONEXIT : -1;
172 176
173 if (dataheader == -1) 177 if (dataheader == -1)
174 ParserError ("unexpected `}`"); 178 ParserError ("unexpected `}`");
175 179
176 // Data header must be written before mode is changed because 180 // Data header must be written before mode is changed because
177 // onenter and mainloop go into buffers, and we want the closing 181 // onenter and mainloop go into special buffers, and we want
178 // data headers into said buffers too. 182 // the closing data headers into said buffers too.
179 w->Write (dataheader); 183 w->Write (dataheader);
180 g_CurMode = MODE_TOPLEVEL; 184 g_CurMode = MODE_TOPLEVEL;
181 185
182 if (!PeekNext().compare (";")) 186 if (!PeekNext().compare (";"))
183 MustNext (";"); 187 MustNext (";");
184 continue; 188 continue;
185 } 189 }
186 190
191 // If it's a variable, expect assignment.
192 if (ScriptVar* var = FindGlobalVariable (token)) {
193 DataBuffer* b = ParseAssignment (var);
194 printf ("current token after assignment: `%s`\n", token.chars());
195 MustNext (";");
196 w->WriteBuffer (b);
197 delete b;
198 continue;
199 }
200
187 // If it's not a keyword, parse it as an expression. 201 // If it's not a keyword, parse it as an expression.
202 printf ("token length: %d, first char: %c [%d]\n", token.len(), token.chars()[0], token.chars()[0]);
188 DataBuffer* b = ParseExpression (TYPE_VOID); 203 DataBuffer* b = ParseExpression (TYPE_VOID);
189 w->WriteBuffer (b); 204 w->WriteBuffer (b);
190 delete b; 205 delete b;
191 printf ("expression done!\n"); 206 printf ("expression done! current token is %s\n", token.chars());
192 MustThis (";"); 207 MustNext (";");
193 } 208 }
194 209
195 if (g_CurMode != MODE_TOPLEVEL) 210 if (g_CurMode != MODE_TOPLEVEL)
196 ParserError ("script did not end at top level; did you forget a `}`?"); 211 ParserError ("script did not end at top level; did you forget a `}`?");
197 212
205 // String table 220 // String table
206 w->WriteStringTable (); 221 w->WriteStringTable ();
207 } 222 }
208 223
209 // ============================================================================ 224 // ============================================================================
210 // Parses a given command 225 // Parses a command call
211 DataBuffer* ScriptReader::ParseCommand (CommandDef* comm) { 226 DataBuffer* ScriptReader::ParseCommand (CommandDef* comm) {
212 DataBuffer* r = new DataBuffer(64); 227 DataBuffer* r = new DataBuffer(64);
213 // If this was defined at top-level, we stop right at square one!
214 if (g_CurMode == MODE_TOPLEVEL) 228 if (g_CurMode == MODE_TOPLEVEL)
215 ParserError ("no commands allowed at top level!"); 229 ParserError ("command call at top level");
216 230
231 printf ("\n\n\n=====================================\nBEGIN PARSING COMMAND\n");
217 printf ("token: %s\n", token.chars()); 232 printf ("token: %s\n", token.chars());
218 MustNext ("("); 233 MustNext ("(");
234 MustNext ();
219 235
220 int curarg = 0; 236 int curarg = 0;
221 while (1) { 237 while (1) {
238 printf ("at argument %d\n", curarg);
239 printf ("next token: %s\n", token.chars());
240
222 if (!token.compare (")")) { 241 if (!token.compare (")")) {
223 printf ("closing command with token `%s`\n", token.chars()); 242 printf ("closing command with token `%s`\n", token.chars());
224 if (curarg < comm->numargs - 1) 243 if (curarg < comm->numargs - 1)
225 ParserError ("too few arguments passed to %s\n", comm->name.chars()); 244 ParserError ("too few arguments passed to %s\n", comm->name.chars());
226 break; 245 break;
227 curarg++; 246 curarg++;
228 } 247 }
229 printf ("prev token: %s\n", token.chars());
230 MustNext ();
231 printf ("next token: %s\n", token.chars());
232
233 // jump back to start
234 if (!token.compare (")"))
235 continue;
236 248
237 if (curarg >= comm->maxargs) 249 if (curarg >= comm->maxargs)
238 ParserError ("too many arguments passed to %s\n", comm->name.chars()); 250 ParserError ("too many arguments passed to %s\n", comm->name.chars());
239 251
240 r->Merge (ParseExpression (comm->argtypes[curarg])); 252 r->Merge (ParseExpression (comm->argtypes[curarg]));
253 MustNext ();
254 printf ("after expression, token is `%s`\n", token.chars());
241 255
242 if (curarg < comm->numargs - 1) { 256 if (curarg < comm->numargs - 1) {
243 MustThis (","); 257 MustThis (",");
258 MustNext ();
244 } else if (curarg < comm->maxargs - 1) { 259 } else if (curarg < comm->maxargs - 1) {
245 // Can continue, but can terminate as well. 260 // Can continue, but can terminate as well.
246 if (!token.compare (")")) { 261 if (!token.compare (")")) {
247 curarg++; 262 curarg++;
248 break; 263 break;
249 } else 264 } else {
250 MustThis (","); 265 MustThis (",");
266 MustNext ();
267 }
251 } 268 }
252 269
253 curarg++; 270 curarg++;
254 } 271 }
255 272
256 // If the script skipped any optional arguments, fill in defaults. 273 // If the script skipped any optional arguments, fill in defaults.
257 while (curarg < comm->maxargs) { 274 while (curarg < comm->maxargs) {
258 r->Write<byte> (DH_PUSHNUMBER); 275 r->Write<word> (DH_PUSHNUMBER);
259 r->Write<byte> (comm->defvals[curarg]); 276 r->Write<word> (comm->defvals[curarg]);
260 curarg++; 277 curarg++;
261 } 278 }
262 279
263 r->Write<byte> (DH_COMMAND); 280 r->Write<word> (DH_COMMAND);
264 r->Write<byte> (comm->number); 281 r->Write<word> (comm->number);
265 r->Write<byte> (comm->maxargs); 282 r->Write<word> (comm->maxargs);
266 283
267 printf ("command complete\n"); 284 printf ("command complete\n");
268 return r; 285 return r;
269 } 286 }
270 287
288 // ============================================================================
289 // Is the given operator an assignment operator?
271 static bool IsAssignmentOperator (int oper) { 290 static bool IsAssignmentOperator (int oper) {
272 switch (oper) { 291 switch (oper) {
273 case OPER_ASSIGNADD: 292 case OPER_ASSIGNADD:
274 case OPER_ASSIGNSUB: 293 case OPER_ASSIGNSUB:
275 case OPER_ASSIGNMUL: 294 case OPER_ASSIGNMUL:
280 } 299 }
281 return false; 300 return false;
282 } 301 }
283 302
284 // ============================================================================ 303 // ============================================================================
304 // Finds an operator's corresponding dataheader
285 static long DataHeaderByOperator (ScriptVar* var, int oper) { 305 static long DataHeaderByOperator (ScriptVar* var, int oper) {
286 if (IsAssignmentOperator (oper)) { 306 if (IsAssignmentOperator (oper)) {
287 if (!var) 307 if (!var)
288 error ("operator %d requires left operand to be a variable\n", oper); 308 error ("operator %d requires left operand to be a variable\n", oper);
289 309
310 error ("DataHeaderByOperator: couldn't find dataheader for operator %d!\n", oper); 330 error ("DataHeaderByOperator: couldn't find dataheader for operator %d!\n", oper);
311 return 0; 331 return 0;
312 } 332 }
313 333
314 // ============================================================================ 334 // ============================================================================
315 // Parses an expression 335 // Parses an expression, potentially recursively
316 DataBuffer* ScriptReader::ParseExpression (int reqtype) { 336 DataBuffer* ScriptReader::ParseExpression (int reqtype) {
317 printf ("begin parsing expression. this token is `%s`, next token is `%s`\n", 337 printf ("begin parsing expression. this token is `%s`, next token is `%s`\n",
318 token.chars(), PeekNext().chars()); 338 token.chars(), PeekNext().chars());
319 DataBuffer* retbuf = new DataBuffer (64); 339 DataBuffer* retbuf = new DataBuffer (64);
320 340
321 DataBuffer* lb = NULL; 341 DataBuffer* lb = NULL;
322 342
343 // If it's a variable, note it down - we need to do special checks with it later.
323 ScriptVar* var = FindGlobalVariable (token); 344 ScriptVar* var = FindGlobalVariable (token);
324 if (var) { 345
325 MustNext (); 346 lb = ParseExprValue (reqtype);
326 if (g_CurMode == MODE_TOPLEVEL) // TODO: lift this restriction
327 ParserError ("can't alter variables at top level");
328 reqtype = TYPE_INT;
329 } else
330 lb = ParseExprValue (reqtype);
331 printf ("done\n"); 347 printf ("done\n");
332 348
333 // Get an operator 349 // Get an operator
334 printf ("parse operator at token %s\n", token.chars()); 350 printf ("parse operator at token %s\n", token.chars());
335 int oper = ParseOperator (); 351 int oper = ParseOperator (true);
352 printf ("operator parsed: token is now %s\n", token.chars());
336 printf ("got %d\n", oper); 353 printf ("got %d\n", oper);
354
337 // No operator found - stop here. 355 // No operator found - stop here.
338 if (oper == -1) { 356 if (oper == -1) {
339 retbuf->Merge (lb); 357 retbuf->Merge (lb);
340 printf ("expression complete without operator, stopping at `%s`\n", token.chars()); 358 printf ("expression complete without operator, stopping at `%s`\n", token.chars());
341 return retbuf; 359 return retbuf;
342 } 360 }
343 361
362 // We peeked the operator, move forward now
363 MustNext();
364
365 // Can't be an assignement operator, those belong in assignments.
366 if (IsAssignmentOperator (oper))
367 ParserError ("assignment operator inside expressions");
368
344 // Parse the right operand, 369 // Parse the right operand,
345 printf ("parse right operand\n"); 370 printf ("parse right operand\n");
346 MustNext (); 371 MustNext ();
347 DataBuffer* rb = ParseExprValue (reqtype); 372 DataBuffer* rb = ParseExprValue (reqtype);
348 printf ("done\n"); 373 printf ("done\n");
349 374
375 retbuf->Merge (rb);
350 retbuf->Merge (lb); 376 retbuf->Merge (lb);
351 retbuf->Merge (rb);
352 377
353 long dh = DataHeaderByOperator (var, oper); 378 long dh = DataHeaderByOperator (var, oper);
354 retbuf->Write<byte> (dh); 379 retbuf->Write<word> (dh);
355
356 if (IsAssignmentOperator (oper))
357 retbuf->Write<byte> (var->index);
358 380
359 printf ("expression complete\n"); 381 printf ("expression complete\n");
360 return retbuf; 382 return retbuf;
361 } 383 }
362 384
363 // ============================================================================ 385 // ============================================================================
364 // Parsess an operator from tokens and returns an identifier. 386 // Parses an operator string. Returns the operator number code.
365 int ScriptReader::ParseOperator () { 387 int ScriptReader::ParseOperator (bool peek) {
366 str oper; 388 str oper;
367 oper += PeekNext (); 389 if (peek)
390 oper += PeekNext ();
391 else
392 oper += token;
368 393
369 // Check one-char operators 394 // Check one-char operators
370 int o = !oper.compare ("=") ? OPER_ASSIGN : 395 int o = !oper.compare ("=") ? OPER_ASSIGN :
371 !oper.compare ("+") ? OPER_ADD : 396 !oper.compare ("+") ? OPER_ADD :
372 !oper.compare ("-") ? OPER_SUBTRACT : 397 !oper.compare ("-") ? OPER_SUBTRACT :
374 !oper.compare ("/") ? OPER_DIVIDE : 399 !oper.compare ("/") ? OPER_DIVIDE :
375 !oper.compare ("%") ? OPER_MODULUS : 400 !oper.compare ("%") ? OPER_MODULUS :
376 -1; 401 -1;
377 402
378 if (o != -1) { 403 if (o != -1) {
379 MustNext ();
380 return o; 404 return o;
381 } 405 }
382 406
383 // Two-char operators 407 // Two-char operators
384 MustNext (); 408 oper += PeekNext (peek ? 1 : 0);
385 oper += PeekNext (1);
386 409
387 o = !oper.compare ("+=") ? OPER_ASSIGNADD : 410 o = !oper.compare ("+=") ? OPER_ASSIGNADD :
388 !oper.compare ("-=") ? OPER_ASSIGNSUB : 411 !oper.compare ("-=") ? OPER_ASSIGNSUB :
389 !oper.compare ("*=") ? OPER_ASSIGNMUL : 412 !oper.compare ("*=") ? OPER_ASSIGNMUL :
390 !oper.compare ("/=") ? OPER_ASSIGNDIV : 413 !oper.compare ("/=") ? OPER_ASSIGNDIV :
391 !oper.compare ("%=") ? OPER_ASSIGNMOD : 414 !oper.compare ("%=") ? OPER_ASSIGNMOD :
392 -1; 415 -1;
393 416
394 if (o != -1) { 417 if (o != -1)
395 MustNext (); 418 MustNext ();
396 MustNext ();
397 }
398 419
399 return o; 420 return o;
400 } 421 }
401 422
402 // ============================================================================ 423 // ============================================================================
421 delete b; 442 delete b;
422 443
423 // Command 444 // Command
424 if (reqtype && comm->returnvalue != reqtype) 445 if (reqtype && comm->returnvalue != reqtype)
425 ParserError ("%s returns an incompatible data type", comm->name.chars()); 446 ParserError ("%s returns an incompatible data type", comm->name.chars());
426 return ParseCommand (comm); 447 b = ParseCommand (comm);
427 } else if ((g = FindGlobalVariable (token)) && reqtype != TYPE_STRING) { 448 } else if ((g = FindGlobalVariable (token)) && reqtype != TYPE_STRING) {
428 printf ("value is a global var\n"); 449 printf ("value is a global var\n");
429 // Global variable 450 // Global variable
430 b->Write<byte> (DH_PUSHGLOBALVAR); 451 b->Write<word> (DH_PUSHGLOBALVAR);
431 b->Write<byte> (g->index); 452 b->Write<word> (g->index);
432 } else { 453 } else {
433 printf ("value is a literal\n"); 454 printf ("value is a literal\n");
434 // If nothing else, check for literal 455 // If nothing else, check for literal
435 switch (reqtype) { 456 switch (reqtype) {
436 case TYPE_VOID: 457 case TYPE_VOID:
437 ParserError ("bad syntax"); 458 ParserError ("bad syntax");
438 break; 459 break;
439 case TYPE_INT: { 460 case TYPE_INT: {
440 printf ("value is an integer literal\n");
441 /* if (!token.isnumber ())
442 ParserError ("expected an integer, got `%s`", token.chars());
443 */
444 MustNumber (true); 461 MustNumber (true);
445 printf ("literal is `%s` = %d\n", token.chars(), atoi (token.chars()));
446 462
447 // All values are written unsigned - thus we need to write the value's 463 // All values are written unsigned - thus we need to write the value's
448 // absolute value, followed by an unary minus if it was negative. 464 // absolute value, followed by an unary minus if it was negative.
449 b->Write<byte> (DH_PUSHNUMBER); 465 b->Write<word> (DH_PUSHNUMBER);
450 long v = atoi (token.chars ()); 466 long v = atoi (token.chars ());
451 b->Write<byte> (static_cast<byte> (abs (v))); 467 b->Write<word> (static_cast<word> (abs (v)));
452 if (v < 0) { 468 if (v < 0)
453 printf ("%ld is negative, write abs value %d and unary minus\n", v, abs(v)); 469 b->Write<word> (DH_UNARYMINUS);
454 b->Write<byte> (DH_UNARYMINUS);
455 }
456 break; 470 break;
457 } 471 }
458 case TYPE_STRING: 472 case TYPE_STRING:
459 // PushToStringTable either returns the string index of the 473 // PushToStringTable either returns the string index of the
460 // string if it finds it in the table, or writes it to the 474 // string if it finds it in the table, or writes it to the
461 // table and returns it index if it doesn't find it there. 475 // table and returns it index if it doesn't find it there.
462 printf ("value is a string literal\n"); 476 printf ("value is a string literal\n");
463 MustString (true); 477 MustString (true);
464 b->Write<byte> (DH_PUSHSTRINGINDEX); 478 b->Write<word> (DH_PUSHSTRINGINDEX);
465 b->Write<byte> (PushToStringTable (token.chars())); 479 b->Write<word> (PushToStringTable (token.chars()));
466 break; 480 break;
467 } 481 }
468 } 482 }
483 printf ("value parsed: current token is `%s`\n", token.chars());
469 484
470 return b; 485 return b;
471 } 486 }
487
488 // ============================================================================
489 // Parses an assignment. An assignment starts with a variable name, followed
490 // by an assignment operator, followed by an expression value. Expects current
491 // token to be the name of the variable, and expects the variable to be given.
492 DataBuffer* ScriptReader::ParseAssignment (ScriptVar* var) {
493 printf ("ASSIGNMENT: this token is `%s`, next token is `%s`\n",
494 token.chars(), PeekNext().chars());
495
496 // Get an operator
497 printf ("parse assignment operator at token %s\n", token.chars());
498
499 MustNext ();
500 int oper = ParseOperator ();
501 if (!IsAssignmentOperator (oper))
502 ParserError ("expected assignment operator");
503 printf ("got %d\n", oper);
504
505 if (g_CurMode == MODE_TOPLEVEL) // TODO: lift this restriction
506 ParserError ("can't alter variables at top level");
507
508 // Parse the right operand,
509 printf ("parse right operand\n");
510 MustNext ();
511 DataBuffer* retbuf = ParseExprValue (TYPE_INT);
512
513 long dh = DataHeaderByOperator (var, oper);
514 retbuf->Write<word> (dh);
515 retbuf->Write<word> (var->index);
516
517 printf ("assignment complete\n");
518 return retbuf;
519 }

mercurial