parser.cxx

changeset 69
29a3e669d648
parent 68
588cc27e84bb
equal deleted inserted replaced
68:588cc27e84bb 69:29a3e669d648
103 ParserError ("state name must be a single word, got `%s`", token.chars()); 103 ParserError ("state name must be a single word, got `%s`", token.chars());
104 str statename = token; 104 str statename = token;
105 105
106 // stateSpawn is special - it *must* be defined. If we 106 // stateSpawn is special - it *must* be defined. If we
107 // encountered it, then mark down that we have it. 107 // encountered it, then mark down that we have it.
108 if (!token.icompare ("statespawn")) 108 if (-token == "statespawn")
109 g_stateSpawnDefined = true; 109 g_stateSpawnDefined = true;
110 110
111 // Must end in a colon 111 // Must end in a colon
112 MustNext (":"); 112 MustNext (":");
113 113
141 MustNext ("{"); 141 MustNext ("{");
142 142
143 g_CurMode = MODE_EVENT; 143 g_CurMode = MODE_EVENT;
144 144
145 w->Write (DH_EVENT); 145 w->Write (DH_EVENT);
146 w->Write<word> (e->number); 146 w->Write (e->number);
147 g_NumEvents++; 147 g_NumEvents++;
148 continue; 148 continue;
149 } 149 }
150 150
151 // ============================================================ 151 // ============================================================
171 w->Write (onenter ? DH_ONENTER : DH_ONEXIT); 171 w->Write (onenter ? DH_ONENTER : DH_ONEXIT);
172 continue; 172 continue;
173 } 173 }
174 174
175 // ============================================================ 175 // ============================================================
176 if (token == "int" || token == "str" || token == "float" || token == "bool") { 176 if (token == "int" || token == "str" || token == "bool") {
177 // For now, only globals are supported 177 // For now, only globals are supported
178 if (g_CurMode != MODE_TOPLEVEL || g_CurState.len()) 178 if (g_CurMode != MODE_TOPLEVEL || g_CurState.len())
179 ParserError ("variables must only be global for now"); 179 ParserError ("variables must only be global for now");
180 180
181 type_e type = (token == "int") ? TYPE_INT : 181 type_e type = (token == "int") ? TYPE_INT :
182 (token == "str") ? TYPE_STRING : 182 (token == "str") ? TYPE_STRING :
183 (token == "float") ? TYPE_FLOAT :
184 TYPE_BOOL; 183 TYPE_BOOL;
185 184
186 MustNext (); 185 MustNext ();
187 186
188 // Var name must not be a number 187 // Var name must not be a number
216 m = w->AddMark (token); 215 m = w->AddMark (token);
217 g_UndefinedLabels[m] = new str (token); 216 g_UndefinedLabels[m] = new str (token);
218 } 217 }
219 218
220 // Add a reference to the mark. 219 // Add a reference to the mark.
221 w->Write<word> (DH_GOTO); 220 w->Write (DH_GOTO);
222 w->AddReference (m); 221 w->AddReference (m);
223 MustNext (";"); 222 MustNext (";");
224 continue; 223 continue;
225 } 224 }
226 225
245 // Upon a closing brace, the mark will be adjusted. 244 // Upon a closing brace, the mark will be adjusted.
246 unsigned int marknum = w->AddMark (""); 245 unsigned int marknum = w->AddMark ("");
247 246
248 // Use DH_IFNOTGOTO - if the expression is not true, we goto the mark 247 // Use DH_IFNOTGOTO - if the expression is not true, we goto the mark
249 // we just defined - and this mark will be at the end of the scope block. 248 // we just defined - and this mark will be at the end of the scope block.
250 w->Write<word> (DH_IFNOTGOTO); 249 w->Write (DH_IFNOTGOTO);
251 w->AddReference (marknum); 250 w->AddReference (marknum);
252 251
253 // Store it 252 // Store it
254 SCOPE(0).mark1 = marknum; 253 SCOPE(0).mark1 = marknum;
255 SCOPE(0).type = SCOPETYPE_IF; 254 SCOPE(0).type = SCOPETYPE_IF;
304 303
305 // Write condition 304 // Write condition
306 w->WriteBuffer (expr); 305 w->WriteBuffer (expr);
307 306
308 // Instruction to go to the end if it fails 307 // Instruction to go to the end if it fails
309 w->Write<word> (DH_IFNOTGOTO); 308 w->Write (DH_IFNOTGOTO);
310 w->AddReference (mark2); 309 w->AddReference (mark2);
311 310
312 // Store the needed stuff 311 // Store the needed stuff
313 SCOPE(0).mark1 = mark1; 312 SCOPE(0).mark1 = mark1;
314 SCOPE(0).mark2 = mark2; 313 SCOPE(0).mark2 = mark2;
355 int mark1 = w->AddMark (""); 354 int mark1 = w->AddMark ("");
356 int mark2 = w->AddMark (""); 355 int mark2 = w->AddMark ("");
357 356
358 // Add the condition 357 // Add the condition
359 w->WriteBuffer (cond); 358 w->WriteBuffer (cond);
360 w->Write<word> (DH_IFNOTGOTO); 359 w->Write (DH_IFNOTGOTO);
361 w->AddReference (mark2); 360 w->AddReference (mark2);
362 361
363 // Store the marks and incrementor 362 // Store the marks and incrementor
364 SCOPE(0).mark1 = mark1; 363 SCOPE(0).mark1 = mark1;
365 SCOPE(0).mark2 = mark2; 364 SCOPE(0).mark2 = mark2;
430 // for the case block that this heralds, and takes care 429 // for the case block that this heralds, and takes care
431 // of buffering setup and stuff like that. 430 // of buffering setup and stuff like that.
432 // NULL the switch buffer for the case-go-to statement, 431 // NULL the switch buffer for the case-go-to statement,
433 // we want it all under the switch, not into the case-buffers. 432 // we want it all under the switch, not into the case-buffers.
434 w->SwitchBuffer = NULL; 433 w->SwitchBuffer = NULL;
435 w->Write<word> (DH_CASEGOTO); 434 w->Write (DH_CASEGOTO);
436 w->Write<word> (num); 435 w->Write (num);
437 AddSwitchCase (w, NULL); 436 AddSwitchCase (w, NULL);
438 SCOPE(0).casenumbers[SCOPE(0).casecursor] = num; 437 SCOPE(0).casenumbers[SCOPE(0).casecursor] = num;
439 continue; 438 continue;
440 } 439 }
441 440
455 // and is only popped when case succeeds, we have 454 // and is only popped when case succeeds, we have
456 // to pop it with DH_DROP manually if we end up in 455 // to pop it with DH_DROP manually if we end up in
457 // a default. 456 // a default.
458 DataBuffer* b = new DataBuffer; 457 DataBuffer* b = new DataBuffer;
459 SCOPE(0).buffer1 = b; 458 SCOPE(0).buffer1 = b;
460 b->Write<word> (DH_DROP); 459 b->Write (DH_DROP);
461 b->Write<word> (DH_GOTO); 460 b->Write (DH_GOTO);
462 AddSwitchCase (w, b); 461 AddSwitchCase (w, b);
463 continue; 462 continue;
464 } 463 }
465 464
466 // ============================================================ 465 // ============================================================
467 // Break statement. 466 // Break statement.
468 if (token == "break") { 467 if (token == "break") {
469 if (!g_ScopeCursor) 468 if (!g_ScopeCursor)
470 ParserError ("unexpected `break`"); 469 ParserError ("unexpected `break`");
471 470
472 w->Write<word> (DH_GOTO); 471 w->Write (DH_GOTO);
473 472
474 // switch and if use mark1 for the closing point, 473 // switch and if use mark1 for the closing point,
475 // for and while use mark2. 474 // for and while use mark2.
476 switch (SCOPE(0).type) { 475 switch (SCOPE(0).type) {
477 case SCOPETYPE_IF: 476 case SCOPETYPE_IF:
503 for (curs = g_ScopeCursor; curs > 0 && !found; curs--) { 502 for (curs = g_ScopeCursor; curs > 0 && !found; curs--) {
504 switch (scopestack[curs].type) { 503 switch (scopestack[curs].type) {
505 case SCOPETYPE_FOR: 504 case SCOPETYPE_FOR:
506 case SCOPETYPE_WHILE: 505 case SCOPETYPE_WHILE:
507 case SCOPETYPE_DO: 506 case SCOPETYPE_DO:
508 w->Write<word> (DH_GOTO); 507 w->Write (DH_GOTO);
509 w->AddReference (scopestack[curs].mark1); 508 w->AddReference (scopestack[curs].mark1);
510 found = true; 509 found = true;
511 break; 510 break;
512 default: 511 default:
513 break; 512 break;
578 info.val = token; 577 info.val = token;
579 break; 578 break;
580 case TYPE_STRING: 579 case TYPE_STRING:
581 MustString (); 580 MustString ();
582 info.val = token; 581 info.val = token;
583 break;
584 case TYPE_FLOAT:
585 MustNext ();
586 info.val = ParseFloat ();
587 break; 582 break;
588 case TYPE_UNKNOWN: 583 case TYPE_UNKNOWN:
589 case TYPE_VOID: 584 case TYPE_VOID:
590 break; 585 break;
591 } 586 }
635 MustNext (")"); 630 MustNext (")");
636 MustNext (";"); 631 MustNext (";");
637 632
638 // If the condition runs true, go back to the start. 633 // If the condition runs true, go back to the start.
639 w->WriteBuffer (expr); 634 w->WriteBuffer (expr);
640 w->Write<long> (DH_IFGOTO); 635 w->Write (DH_IFGOTO);
641 w->AddReference (SCOPE(0).mark1); 636 w->AddReference (SCOPE(0).mark1);
642 break; 637 break;
643 } 638 }
644 case SCOPETYPE_SWITCH: { 639 case SCOPETYPE_SWITCH: {
645 // Switch closes. Move down to the record buffer of 640 // Switch closes. Move down to the record buffer of
653 // If not, write instruction to jump to the end of switch after 648 // If not, write instruction to jump to the end of switch after
654 // the headers (thus won't fall-through if no case matched) 649 // the headers (thus won't fall-through if no case matched)
655 if (SCOPE(0).buffer1) 650 if (SCOPE(0).buffer1)
656 w->WriteBuffer (SCOPE(0).buffer1); 651 w->WriteBuffer (SCOPE(0).buffer1);
657 else { 652 else {
658 w->Write<word> (DH_DROP); 653 w->Write (DH_DROP);
659 w->Write<word> (DH_GOTO); 654 w->Write (DH_GOTO);
660 w->AddReference (SCOPE(0).mark1); 655 w->AddReference (SCOPE(0).mark1);
661 } 656 }
662 657
663 // Go through all of the buffers we 658 // Go through all of the buffers we
664 // recorded down and write them. 659 // recorded down and write them.
784 curarg++; 779 curarg++;
785 } 780 }
786 781
787 // If the script skipped any optional arguments, fill in defaults. 782 // If the script skipped any optional arguments, fill in defaults.
788 while (curarg < comm->maxargs) { 783 while (curarg < comm->maxargs) {
789 r->Write<word> (DH_PUSHNUMBER); 784 r->Write (DH_PUSHNUMBER);
790 r->Write<word> (comm->defvals[curarg]); 785 r->Write (comm->defvals[curarg]);
791 curarg++; 786 curarg++;
792 } 787 }
793 788
794 r->Write<word> (DH_COMMAND); 789 r->Write (DH_COMMAND);
795 r->Write<word> (comm->number); 790 r->Write (comm->number);
796 r->Write<word> (comm->maxargs); 791 r->Write (comm->maxargs);
797 792
798 return r; 793 return r;
799 } 794 }
800 795
801 // ============================================================================ 796 // ============================================================================
893 // It also is handled differently: there isn't a dataheader for ternary 888 // It also is handled differently: there isn't a dataheader for ternary
894 // operator. Instead, we abuse PUSHNUMBER and IFNOTGOTO for this. 889 // operator. Instead, we abuse PUSHNUMBER and IFNOTGOTO for this.
895 // Behold, big block of writing madness! :P 890 // Behold, big block of writing madness! :P
896 int mark1 = retbuf->AddMark (""); // start of "else" case 891 int mark1 = retbuf->AddMark (""); // start of "else" case
897 int mark2 = retbuf->AddMark (""); // end of expression 892 int mark2 = retbuf->AddMark (""); // end of expression
898 retbuf->Write<word> (DH_IFNOTGOTO); // if the first operand (condition) 893 retbuf->Write (DH_IFNOTGOTO); // if the first operand (condition)
899 retbuf->AddMarkReference (mark1); // didn't eval true, jump into mark1 894 retbuf->AddMarkReference (mark1); // didn't eval true, jump into mark1
900 retbuf->Merge (rb); // otherwise, perform second operand (true case) 895 retbuf->Merge (rb); // otherwise, perform second operand (true case)
901 retbuf->Write<word> (DH_GOTO); // afterwards, jump to the end, which is 896 retbuf->Write (DH_GOTO); // afterwards, jump to the end, which is
902 retbuf->AddMarkReference (mark2); // marked by mark2. 897 retbuf->AddMarkReference (mark2); // marked by mark2.
903 retbuf->MoveMark (mark1); // move mark1 at the end of the true case 898 retbuf->MoveMark (mark1); // move mark1 at the end of the true case
904 retbuf->Merge (tb); // perform third operand (false case) 899 retbuf->Merge (tb); // perform third operand (false case)
905 retbuf->MoveMark (mark2); // move the ending mark2 here 900 retbuf->MoveMark (mark2); // move the ending mark2 here
906 } else { 901 } else {
907 // Write to buffer 902 // Write to buffer
908 retbuf->Merge (rb); 903 retbuf->Merge (rb);
909 retbuf->Write<word> (DataHeaderByOperator (NULL, oper)); 904 retbuf->Write (DataHeaderByOperator (NULL, oper));
910 } 905 }
911 } 906 }
912 907
913 return retbuf; 908 return retbuf;
914 } 909 }
1026 ParserError ("strlen only works with const str"); 1021 ParserError ("strlen only works with const str");
1027 1022
1028 if (reqtype != TYPE_INT) 1023 if (reqtype != TYPE_INT)
1029 ParserError ("strlen returns int but %s is expected\n", (char*)GetTypeName (reqtype)); 1024 ParserError ("strlen returns int but %s is expected\n", (char*)GetTypeName (reqtype));
1030 1025
1031 b->Write<word> (DH_PUSHNUMBER); 1026 b->Write (DH_PUSHNUMBER);
1032 b->Write<word> (constant->val.len ()); 1027 b->Write (constant->val.len ());
1033 1028
1034 MustNext (")"); 1029 MustNext (")");
1035 } else if (token == "(") { 1030 } else if (token == "(") {
1036 // Expression 1031 // Expression
1037 MustNext (); 1032 MustNext ();
1053 (char*)GetTypeName (reqtype)); 1048 (char*)GetTypeName (reqtype));
1054 1049
1055 switch (constant->type) { 1050 switch (constant->type) {
1056 case TYPE_BOOL: 1051 case TYPE_BOOL:
1057 case TYPE_INT: 1052 case TYPE_INT:
1058 b->Write<word> (DH_PUSHNUMBER); 1053 b->Write (DH_PUSHNUMBER);
1059 b->Write<word> (atoi (constant->val)); 1054 b->Write (atoi (constant->val));
1060 break;
1061 case TYPE_FLOAT:
1062 b->WriteFloat (constant->val);
1063 break; 1055 break;
1064 case TYPE_STRING: 1056 case TYPE_STRING:
1065 b->WriteString (constant->val); 1057 b->WriteString (constant->val);
1066 break; 1058 break;
1067 case TYPE_VOID: 1059 case TYPE_VOID:
1068 case TYPE_UNKNOWN: 1060 case TYPE_UNKNOWN:
1069 break; 1061 break;
1070 } 1062 }
1071 } else if ((g = FindGlobalVariable (token))) { 1063 } else if ((g = FindGlobalVariable (token))) {
1072 // Global variable 1064 // Global variable
1073 b->Write<word> (DH_PUSHGLOBALVAR); 1065 b->Write (DH_PUSHGLOBALVAR);
1074 b->Write<word> (g->index); 1066 b->Write (g->index);
1075 } else { 1067 } else {
1076 // If nothing else, check for literal 1068 // If nothing else, check for literal
1077 switch (reqtype) { 1069 switch (reqtype) {
1078 case TYPE_VOID: 1070 case TYPE_VOID:
1079 case TYPE_UNKNOWN: 1071 case TYPE_UNKNOWN:
1083 case TYPE_INT: { 1075 case TYPE_INT: {
1084 MustNumber (true); 1076 MustNumber (true);
1085 1077
1086 // All values are written unsigned - thus we need to write the value's 1078 // All values are written unsigned - thus we need to write the value's
1087 // absolute value, followed by an unary minus for negatives. 1079 // absolute value, followed by an unary minus for negatives.
1088 b->Write<word> (DH_PUSHNUMBER); 1080 b->Write (DH_PUSHNUMBER);
1089 1081
1090 long v = atol (token); 1082 long v = atol (token);
1091 b->Write<word> (static_cast<word> (abs (v))); 1083 b->Write (static_cast<word> (abs (v)));
1092 if (v < 0) 1084 if (v < 0)
1093 b->Write<word> (DH_UNARYMINUS); 1085 b->Write (DH_UNARYMINUS);
1094 break; 1086 break;
1095 } 1087 }
1096 case TYPE_STRING: 1088 case TYPE_STRING:
1097 // PushToStringTable either returns the string index of the 1089 // PushToStringTable either returns the string index of the
1098 // string if it finds it in the table, or writes it to the 1090 // string if it finds it in the table, or writes it to the
1099 // table and returns it index if it doesn't find it there. 1091 // table and returns it index if it doesn't find it there.
1100 MustString (true); 1092 MustString (true);
1101 b->WriteString (token); 1093 b->WriteString (token);
1102 break; 1094 break;
1103 case TYPE_FLOAT: {
1104 str floatstring = ParseFloat ();
1105
1106 // TODO: Keep this check after decimal loss is fixed, but make
1107 // it a real precision loss check. 55.5123 -> 55.512299, this
1108 // should probably be warned of.
1109 float check = static_cast<float> (static_cast<word> (atof (floatstring)));
1110 if (atof (floatstring) != check)
1111 ParserWarning ("floating point number %f loses precision (-> %f)",
1112 atof (floatstring), check);
1113
1114 b->WriteFloat (floatstring);
1115 break;
1116 }
1117 } 1095 }
1118 } 1096 }
1119 1097
1120 // Negate it now if desired 1098 // Negate it now if desired
1121 if (negate) 1099 if (negate)
1122 b->Write<word> (DH_NEGATELOGICAL); 1100 b->Write (DH_NEGATELOGICAL);
1123 1101
1124 return b; 1102 return b;
1125 } 1103 }
1126 1104
1127 // ============================================================================ 1105 // ============================================================================
1147 1125
1148 // <<= and >>= do not have data headers. Solution: expand them. 1126 // <<= and >>= do not have data headers. Solution: expand them.
1149 // a <<= b -> a = a << b 1127 // a <<= b -> a = a << b
1150 // a >>= b -> a = a >> b 1128 // a >>= b -> a = a >> b
1151 if (oper == OPER_ASSIGNLEFTSHIFT || oper == OPER_ASSIGNRIGHTSHIFT) { 1129 if (oper == OPER_ASSIGNLEFTSHIFT || oper == OPER_ASSIGNRIGHTSHIFT) {
1152 retbuf->Write<word> (global ? DH_PUSHGLOBALVAR : DH_PUSHLOCALVAR); 1130 retbuf->Write (global ? DH_PUSHGLOBALVAR : DH_PUSHLOCALVAR);
1153 retbuf->Write<word> (var->index); 1131 retbuf->Write (var->index);
1154 retbuf->Merge (expr); 1132 retbuf->Merge (expr);
1155 retbuf->Write<word> ((oper == OPER_ASSIGNLEFTSHIFT) ? DH_LSHIFT : DH_RSHIFT); 1133 retbuf->Write ((oper == OPER_ASSIGNLEFTSHIFT) ? DH_LSHIFT : DH_RSHIFT);
1156 retbuf->Write<word> (global ? DH_ASSIGNGLOBALVAR : DH_ASSIGNLOCALVAR); 1134 retbuf->Write (global ? DH_ASSIGNGLOBALVAR : DH_ASSIGNLOCALVAR);
1157 retbuf->Write<word> (var->index); 1135 retbuf->Write (var->index);
1158 } else { 1136 } else {
1159 retbuf->Merge (expr); 1137 retbuf->Merge (expr);
1160 long dh = DataHeaderByOperator (var, oper); 1138 long dh = DataHeaderByOperator (var, oper);
1161 retbuf->Write<word> (dh); 1139 retbuf->Write (dh);
1162 retbuf->Write<word> (var->index); 1140 retbuf->Write (var->index);
1163 } 1141 }
1164 1142
1165 return retbuf; 1143 return retbuf;
1166 } 1144 }
1167 1145

mercurial