parser.cxx

changeset 67
0a202714eea4
parent 66
4fc1ec88aa41
child 68
588cc27e84bb
equal deleted inserted replaced
66:4fc1ec88aa41 67:0a202714eea4
59 59
60 #define SCOPE(n) scopestack[g_ScopeCursor - n] 60 #define SCOPE(n) scopestack[g_ScopeCursor - n]
61 61
62 int g_NumStates = 0; 62 int g_NumStates = 0;
63 int g_NumEvents = 0; 63 int g_NumEvents = 0;
64 int g_CurMode = MODE_TOPLEVEL; 64 parsermode_e g_CurMode = MODE_TOPLEVEL;
65 str g_CurState = ""; 65 str g_CurState = "";
66 bool g_stateSpawnDefined = false; 66 bool g_stateSpawnDefined = false;
67 bool g_GotMainLoop = false; 67 bool g_GotMainLoop = false;
68 unsigned int g_ScopeCursor = 0; 68 unsigned int g_ScopeCursor = 0;
69 DataBuffer* g_IfExpression = NULL; 69 DataBuffer* g_IfExpression = NULL;
169 w->Write (onenter ? DH_ONENTER : DH_ONEXIT); 169 w->Write (onenter ? DH_ONENTER : DH_ONEXIT);
170 continue; 170 continue;
171 } 171 }
172 172
173 // ============================================================ 173 // ============================================================
174 if (token == "var") { 174 if (token == "int" || token == "str" || token == "float" || token == "bool") {
175 // For now, only globals are supported 175 // For now, only globals are supported
176 if (g_CurMode != MODE_TOPLEVEL || g_CurState.len()) 176 if (g_CurMode != MODE_TOPLEVEL || g_CurState.len())
177 ParserError ("variables must only be global for now"); 177 ParserError ("variables must only be global for now");
178 178
179 type_e type = (token == "int") ? TYPE_INT :
180 (token == "str") ? TYPE_STRING :
181 (token == "float") ? TYPE_FLOAT :
182 TYPE_BOOL;
183
179 MustNext (); 184 MustNext ();
180 185
181 // Var name must not be a number 186 // Var name must not be a number
182 if (token.isnumber()) 187 if (token.isnumber())
183 ParserError ("variable name must not be a number"); 188 ParserError ("variable name must not be a number");
184 189
185 str varname = token; 190 str varname = token;
186 ScriptVar* var = DeclareGlobalVariable (this, varname); 191 ScriptVar* var = DeclareGlobalVariable (this, type, varname);
187 192
188 if (!var) 193 if (!var)
189 ParserError ("declaring %s variable %s failed", 194 ParserError ("declaring %s variable %s failed",
190 g_CurState.len() ? "state" : "global", varname.chars()); 195 g_CurState.len() ? "state" : "global", varname.chars());
191 196
317 322
318 // Initializer 323 // Initializer
319 MustNext ("("); 324 MustNext ("(");
320 MustNext (); 325 MustNext ();
321 DataBuffer* init = ParseStatement (w); 326 DataBuffer* init = ParseStatement (w);
327 if (!init)
328 ParserError ("bad statement for initializer of for");
329
322 MustNext (";"); 330 MustNext (";");
323 331
324 // Condition 332 // Condition
325 MustNext (); 333 MustNext ();
326 DataBuffer* cond = ParseExpression (TYPE_INT); 334 DataBuffer* cond = ParseExpression (TYPE_INT);
335 if (!cond)
336 ParserError ("bad statement for condition of for");
337
327 MustNext (";"); 338 MustNext (";");
328 339
329 // Incrementor 340 // Incrementor
330 MustNext (); 341 MustNext ();
331 DataBuffer* incr = ParseStatement (w); 342 DataBuffer* incr = ParseStatement (w);
343 if (!incr)
344 ParserError ("bad statement for incrementor of for");
345
332 MustNext (")"); 346 MustNext (")");
333 MustNext ("{"); 347 MustNext ("{");
334 348
335 // First, write out the initializer 349 // First, write out the initializer
336 w->WriteBuffer (init); 350 w->WriteBuffer (init);
505 continue; 519 continue;
506 } 520 }
507 521
508 // ============================================================ 522 // ============================================================
509 // Label 523 // Label
510 if (!PeekNext().compare (":")) { 524 if (PeekNext() == ":") {
511 MUST_NOT_TOPLEVEL 525 MUST_NOT_TOPLEVEL
512 526
513 // want no conflicts.. 527 // want no conflicts..
514 if (IsKeyword (token)) 528 if (IsKeyword (token))
515 ParserError ("label name `%s` conflicts with keyword\n", token.chars()); 529 ParserError ("label name `%s` conflicts with keyword\n", token.chars());
519 ParserError ("label name `%s` conflicts with variable\n", token.chars()); 533 ParserError ("label name `%s` conflicts with variable\n", token.chars());
520 534
521 // See if a mark already exists for this label 535 // See if a mark already exists for this label
522 int mark = -1; 536 int mark = -1;
523 for (int i = 0; i < MAX_MARKS; i++) { 537 for (int i = 0; i < MAX_MARKS; i++) {
524 if (g_UndefinedLabels[i] && !g_UndefinedLabels[i]->compare (token)) { 538 if (g_UndefinedLabels[i] && *g_UndefinedLabels[i] == token) {
525 mark = i; 539 mark = i;
526 w->MoveMark (i); 540 w->MoveMark (i);
527 541
528 // No longer undefinde 542 // No longer undefinde
529 delete g_UndefinedLabels[i]; 543 delete g_UndefinedLabels[i];
538 MustNext (":"); 552 MustNext (":");
539 continue; 553 continue;
540 } 554 }
541 555
542 // ============================================================ 556 // ============================================================
543 if (!token.compare ("}")) { 557 if (token == "}") {
544 // Closing brace 558 // Closing brace
545 559
546 // If we're in the block stack, we're descending down from it now 560 // If we're in the block stack, we're descending down from it now
547 if (g_ScopeCursor > 0) { 561 if (g_ScopeCursor > 0) {
548 switch (SCOPE(0).type) { 562 switch (SCOPE(0).type) {
638 // onenter and mainloop go into special buffers, and we want 652 // onenter and mainloop go into special buffers, and we want
639 // the closing data headers into said buffers too. 653 // the closing data headers into said buffers too.
640 w->Write (dataheader); 654 w->Write (dataheader);
641 g_CurMode = MODE_TOPLEVEL; 655 g_CurMode = MODE_TOPLEVEL;
642 656
643 if (!PeekNext().compare (";")) 657 if (PeekNext() == ";")
644 MustNext (";"); 658 MustNext (";");
645 continue; 659 continue;
646 } 660 }
647 661
648 // Check if it's a command 662 // Check if it's a command
654 } 668 }
655 669
656 // ============================================================ 670 // ============================================================
657 // If nothing else, parse it as a statement 671 // If nothing else, parse it as a statement
658 DataBuffer* b = ParseStatement (w); 672 DataBuffer* b = ParseStatement (w);
673 if (!b)
674 ParserError ("unknown token `%s`", token.chars());
675
659 w->WriteBuffer (b); 676 w->WriteBuffer (b);
660 MustNext (";"); 677 MustNext (";");
661 } 678 }
662 679
663 // =============================================================================== 680 // ===============================================================================
690 MustNext ("("); 707 MustNext ("(");
691 MustNext (); 708 MustNext ();
692 709
693 int curarg = 0; 710 int curarg = 0;
694 while (1) { 711 while (1) {
695 if (!token.compare (")")) { 712 if (token == ")") {
696 if (curarg < comm->numargs) 713 if (curarg < comm->numargs)
697 ParserError ("too few arguments passed to %s\n\tprototype: %s", 714 ParserError ("too few arguments passed to %s\n\tprototype: %s",
698 comm->name.chars(), GetCommandPrototype (comm).chars()); 715 comm->name.chars(), GetCommandPrototype (comm).chars());
699 break; 716 break;
700 curarg++; 717 curarg++;
710 if (curarg < comm->numargs - 1) { 727 if (curarg < comm->numargs - 1) {
711 MustThis (","); 728 MustThis (",");
712 MustNext (); 729 MustNext ();
713 } else if (curarg < comm->maxargs - 1) { 730 } else if (curarg < comm->maxargs - 1) {
714 // Can continue, but can terminate as well. 731 // Can continue, but can terminate as well.
715 if (!token.compare (")")) { 732 if (token == ")") {
716 curarg++; 733 curarg++;
717 break; 734 break;
718 } else { 735 } else {
719 MustThis (","); 736 MustThis (",");
720 MustNext (); 737 MustNext ();
853 return retbuf; 870 return retbuf;
854 } 871 }
855 872
856 // ============================================================================ 873 // ============================================================================
857 // Parses an operator string. Returns the operator number code. 874 // Parses an operator string. Returns the operator number code.
858 #define ISNEXT(char) !PeekNext (peek ? 1 : 0).compare (char) 875 #define ISNEXT(char) (!PeekNext (peek ? 1 : 0) == char)
859 int ScriptReader::ParseOperator (bool peek) { 876 int ScriptReader::ParseOperator (bool peek) {
860 str oper; 877 str oper;
861 if (peek) 878 if (peek)
862 oper += PeekNext (); 879 oper += PeekNext ();
863 else 880 else
864 oper += token; 881 oper += token;
865 882
866 // Check one-char operators 883 // Check one-char operators
867 bool equalsnext = ISNEXT ("="); 884 bool equalsnext = ISNEXT ("=");
868 885
869 int o = (!oper.compare ("=") && !equalsnext) ? OPER_ASSIGN : 886 int o = (oper == "=" && !equalsnext) ? OPER_ASSIGN :
870 (!oper.compare (">") && !equalsnext && !ISNEXT (">")) ? OPER_GREATERTHAN : 887 (oper == ">" && !equalsnext && !ISNEXT (">")) ? OPER_GREATERTHAN :
871 (!oper.compare ("<") && !equalsnext && !ISNEXT ("<")) ? OPER_LESSTHAN : 888 (oper == "<" && !equalsnext && !ISNEXT ("<")) ? OPER_LESSTHAN :
872 (!oper.compare ("&") && !ISNEXT ("&")) ? OPER_BITWISEAND : 889 (oper == "&" && !ISNEXT ("&")) ? OPER_BITWISEAND :
873 (!oper.compare ("|") && !ISNEXT ("|")) ? OPER_BITWISEOR : 890 (oper == "|" && !ISNEXT ("|")) ? OPER_BITWISEOR :
874 !oper.compare ("^") ? OPER_BITWISEEOR : 891 (oper == "+" && !equalsnext) ? OPER_ADD :
875 !oper.compare ("+") ? OPER_ADD : 892 (oper == "-" && !equalsnext) ? OPER_SUBTRACT :
876 !oper.compare ("-") ? OPER_SUBTRACT : 893 (oper == "*" && !equalsnext) ? OPER_MULTIPLY :
877 !oper.compare ("*") ? OPER_MULTIPLY : 894 (oper == "/" && !equalsnext) ? OPER_DIVIDE :
878 !oper.compare ("/") ? OPER_DIVIDE : 895 (oper == "%" && !equalsnext) ? OPER_MODULUS :
879 !oper.compare ("%") ? OPER_MODULUS : 896 (oper == "^") ? OPER_BITWISEEOR :
880 !oper.compare ("?") ? OPER_TERNARY : 897 (oper == "?") ? OPER_TERNARY :
881 -1; 898 -1;
882 899
883 if (o != -1) { 900 if (o != -1) {
884 return o; 901 return o;
885 } 902 }
886 903
887 // Two-char operators 904 // Two-char operators
888 oper += PeekNext (peek ? 1 : 0); 905 oper += PeekNext (peek ? 1 : 0);
889 equalsnext = !PeekNext (peek ? 2 : 1).compare ("="); 906 equalsnext = PeekNext (peek ? 2 : 1) == ("=");
890 907
891 o = !oper.compare ("+=") ? OPER_ASSIGNADD : 908 o = (oper == "+=") ? OPER_ASSIGNADD :
892 !oper.compare ("-=") ? OPER_ASSIGNSUB : 909 (oper == "-=") ? OPER_ASSIGNSUB :
893 !oper.compare ("*=") ? OPER_ASSIGNMUL : 910 (oper == "*=") ? OPER_ASSIGNMUL :
894 !oper.compare ("/=") ? OPER_ASSIGNDIV : 911 (oper == "/=") ? OPER_ASSIGNDIV :
895 !oper.compare ("%=") ? OPER_ASSIGNMOD : 912 (oper == "%=") ? OPER_ASSIGNMOD :
896 !oper.compare ("==") ? OPER_EQUALS : 913 (oper == "==") ? OPER_EQUALS :
897 !oper.compare ("!=") ? OPER_NOTEQUALS : 914 (oper == "!=") ? OPER_NOTEQUALS :
898 !oper.compare (">=") ? OPER_GREATERTHANEQUALS : 915 (oper == ">=") ? OPER_GREATERTHANEQUALS :
899 !oper.compare ("<=") ? OPER_LESSTHANEQUALS : 916 (oper == "<=") ? OPER_LESSTHANEQUALS :
900 !oper.compare ("&&") ? OPER_AND : 917 (oper == "&&") ? OPER_AND :
901 !oper.compare ("||") ? OPER_OR : 918 (oper == "||") ? OPER_OR :
902 (!oper.compare ("<<") && !equalsnext) ? OPER_LEFTSHIFT : 919 (oper == "<<" && !equalsnext) ? OPER_LEFTSHIFT :
903 (!oper.compare (">>") && !equalsnext) ? OPER_RIGHTSHIFT : 920 (oper == ">>" && !equalsnext) ? OPER_RIGHTSHIFT :
904 -1; 921 -1;
905 922
906 if (o != -1) { 923 if (o != -1) {
907 MustNext (); 924 MustNext ();
908 return o; 925 return o;
909 } 926 }
910 927
911 // Three-char opers 928 // Three-char opers
912 oper += PeekNext (peek ? 2 : 1); 929 oper += PeekNext (peek ? 2 : 1);
913 o = !oper.compare ("<<=") ? OPER_ASSIGNLEFTSHIFT : 930 o = oper == "<<=" ? OPER_ASSIGNLEFTSHIFT :
914 !oper.compare (">>=") ? OPER_ASSIGNRIGHTSHIFT : 931 oper == ">>=" ? OPER_ASSIGNRIGHTSHIFT :
915 -1; 932 -1;
916 933
917 if (o != -1) { 934 if (o != -1) {
918 MustNext (); 935 MustNext ();
919 MustNext (); 936 MustNext ();
930 DataBuffer* b = new DataBuffer(16); 947 DataBuffer* b = new DataBuffer(16);
931 948
932 ScriptVar* g; 949 ScriptVar* g;
933 950
934 // Prefixing "!" means negation. 951 // Prefixing "!" means negation.
935 bool negate = !token.compare ("!"); 952 bool negate = (token == "!");
936 if (negate) // Jump past the "!" 953 if (negate) // Jump past the "!"
937 MustNext (); 954 Next ();
938 955
939 if (!token.compare ("(")) { 956 if (token == "(") {
940 // Expression 957 // Expression
941 MustNext (); 958 MustNext ();
942 DataBuffer* c = ParseExpression (reqtype); 959 DataBuffer* c = ParseExpression (reqtype);
943 b->Merge (c); 960 b->Merge (c);
944 MustNext (")"); 961 MustNext (")");
947 964
948 // Command 965 // Command
949 if (reqtype && comm->returnvalue != reqtype) 966 if (reqtype && comm->returnvalue != reqtype)
950 ParserError ("%s returns an incompatible data type", comm->name.chars()); 967 ParserError ("%s returns an incompatible data type", comm->name.chars());
951 b = ParseCommand (comm); 968 b = ParseCommand (comm);
952 } else if ((g = FindGlobalVariable (token)) && reqtype != TYPE_STRING) { 969 } else if ((g = FindGlobalVariable (token))) {
953 // Global variable 970 // Global variable
954 b->Write<word> (DH_PUSHGLOBALVAR); 971 b->Write<word> (DH_PUSHGLOBALVAR);
955 b->Write<word> (g->index); 972 b->Write<word> (g->index);
956 } else { 973 } else {
957 // If nothing else, check for literal 974 // If nothing else, check for literal
975 printf ("reqtype: %d\n", reqtype);
958 switch (reqtype) { 976 switch (reqtype) {
959 case TYPE_VOID: 977 case TYPE_VOID:
960 ParserError ("unknown identifier `%s` (expected keyword, function or variable)", token.chars()); 978 ParserError ("unknown identifier `%s` (expected keyword, function or variable)", token.chars());
961 break; 979 break;
962 case TYPE_BOOL: 980 case TYPE_BOOL:
963 case TYPE_INT: { 981 case TYPE_INT: {
964 MustNumber (true); 982 MustNumber (true);
965 983
966 // All values are written unsigned - thus we need to write the value's 984 // All values are written unsigned - thus we need to write the value's
967 // absolute value, followed by an unary minus if it was negative. 985 // absolute value, followed by an unary minus for negatives.
968 b->Write<word> (DH_PUSHNUMBER); 986 b->Write<word> (DH_PUSHNUMBER);
969 987
970 long v = atoi (token.chars ()); 988 long v = atol (token);
971 b->Write<word> (static_cast<word> (abs (v))); 989 b->Write<word> (static_cast<word> (abs (v)));
972 if (v < 0) 990 if (v < 0)
973 b->Write<word> (DH_UNARYMINUS); 991 b->Write<word> (DH_UNARYMINUS);
974 break; 992 break;
975 } 993 }
986 1004
987 MustNumber (true); 1005 MustNumber (true);
988 floatstring += token; 1006 floatstring += token;
989 1007
990 // Go after the decimal point 1008 // Go after the decimal point
991 if (!PeekNext ().compare(".")) { 1009 if (PeekNext () == ".") {
992 MustNext ("."); 1010 MustNext (".");
993 MustNumber (false); 1011 MustNumber (false);
994 floatstring += "."; 1012 floatstring += ".";
995 floatstring += token; 1013 floatstring += token;
996 } 1014 }
1028 bool global = !var->statename.len (); 1046 bool global = !var->statename.len ();
1029 1047
1030 // Get an operator 1048 // Get an operator
1031 MustNext (); 1049 MustNext ();
1032 int oper = ParseOperator (); 1050 int oper = ParseOperator ();
1051 printf ("got operator %d\n", oper);
1033 if (!IsAssignmentOperator (oper)) 1052 if (!IsAssignmentOperator (oper))
1034 ParserError ("expected assignment operator"); 1053 ParserError ("expected assignment operator");
1035 1054
1036 if (g_CurMode == MODE_TOPLEVEL) // TODO: lift this restriction 1055 if (g_CurMode == MODE_TOPLEVEL) // TODO: lift this restriction
1037 ParserError ("can't alter variables at top level"); 1056 ParserError ("can't alter variables at top level");
1038 1057
1039 // Parse the right operand 1058 // Parse the right operand
1040 MustNext (); 1059 MustNext ();
1041 DataBuffer* retbuf = new DataBuffer; 1060 DataBuffer* retbuf = new DataBuffer;
1042 DataBuffer* expr = ParseExpression (TYPE_INT); 1061 DataBuffer* expr = ParseExpression (var->type);
1043 1062
1044 // <<= and >>= do not have data headers. Solution: expand them. 1063 // <<= and >>= do not have data headers. Solution: expand them.
1045 // a <<= b -> a = a << b 1064 // a <<= b -> a = a << b
1046 // a >>= b -> a = a >> b 1065 // a >>= b -> a = a >> b
1047 if (oper == OPER_ASSIGNLEFTSHIFT || oper == OPER_ASSIGNRIGHTSHIFT) { 1066 if (oper == OPER_ASSIGNLEFTSHIFT || oper == OPER_ASSIGNRIGHTSHIFT) {
1084 if (ScriptVar* var = FindGlobalVariable (token)) { 1103 if (ScriptVar* var = FindGlobalVariable (token)) {
1085 DataBuffer* b = ParseAssignment (var); 1104 DataBuffer* b = ParseAssignment (var);
1086 return b; 1105 return b;
1087 } 1106 }
1088 1107
1089 ParserError ("bad statement");
1090 return NULL; 1108 return NULL;
1091 } 1109 }
1092 1110
1093 void ScriptReader::AddSwitchCase (ObjWriter* w, DataBuffer* b) { 1111 void ScriptReader::AddSwitchCase (ObjWriter* w, DataBuffer* b) {
1094 ScopeInfo* info = &SCOPE(0); 1112 ScopeInfo* info = &SCOPE(0);

mercurial