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 |
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 (); |
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 } |
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) { |