parser.cxx

changeset 24
7dcc8419dbdb
parent 22
b48e10ca8832
child 25
2a600af97c6b
equal deleted inserted replaced
23:ba351235688e 24:7dcc8419dbdb
72 if (!newfile) 72 if (!newfile)
73 ParserError ("couldn't open included file `%s`!", token.chars()); 73 ParserError ("couldn't open included file `%s`!", token.chars());
74 fclose (newfile); 74 fclose (newfile);
75 ScriptReader* newreader = new ScriptReader (token.chars()); 75 ScriptReader* newreader = new ScriptReader (token.chars());
76 newreader->BeginParse (w); 76 newreader->BeginParse (w);
77 } else if (!token.icompare ("state")) { 77 continue;
78 }
79
80 if (!token.icompare ("state")) {
78 MUST_TOPLEVEL 81 MUST_TOPLEVEL
79 82
80 MustString (); 83 MustString ();
81 84
82 // State name must be a word. 85 // State name must be a word.
105 w->Write (g_NumStates); 108 w->Write (g_NumStates);
106 109
107 g_NumStates++; 110 g_NumStates++;
108 g_CurState = token; 111 g_CurState = token;
109 gotMainLoop = false; 112 gotMainLoop = false;
110 } else if (!token.icompare ("event")) { 113 continue;
114 }
115
116 if (!token.icompare ("event")) {
111 MUST_TOPLEVEL 117 MUST_TOPLEVEL
112 118
113 // Event definition 119 // Event definition
114 MustString (); 120 MustString ();
115 121
122 g_CurMode = MODE_EVENT; 128 g_CurMode = MODE_EVENT;
123 129
124 w->Write (DH_EVENT); 130 w->Write (DH_EVENT);
125 w->Write<long> (e->number); 131 w->Write<long> (e->number);
126 g_NumEvents++; 132 g_NumEvents++;
127 } else if (!token.icompare ("mainloop")) { 133 continue;
134 }
135
136 if (!token.icompare ("mainloop")) {
128 MUST_TOPLEVEL 137 MUST_TOPLEVEL
129 MustNext ("{"); 138 MustNext ("{");
130 g_CurMode = MODE_MAINLOOP; 139 g_CurMode = MODE_MAINLOOP;
131 w->Write (DH_MAINLOOP); 140 w->Write (DH_MAINLOOP);
132 gotMainLoop = true; 141 gotMainLoop = true;
133 } else if (!token.icompare ("onenter") || !token.icompare ("onexit")) { 142 continue;
143 }
144
145 if (!token.icompare ("onenter") || !token.icompare ("onexit")) {
134 MUST_TOPLEVEL 146 MUST_TOPLEVEL
135 bool onenter = !token.compare ("onenter"); 147 bool onenter = !token.compare ("onenter");
136 148
137 MustNext ("{"); 149 MustNext ("{");
138 g_CurMode = onenter ? MODE_ONENTER : MODE_ONEXIT; 150 g_CurMode = onenter ? MODE_ONENTER : MODE_ONEXIT;
139 w->Write (onenter ? DH_ONENTER : DH_ONEXIT); 151 w->Write (onenter ? DH_ONENTER : DH_ONEXIT);
140 } else if (!token.compare ("int") || !token.compare ("bool")) { 152 continue;
153 }
154
155 if (!token.compare ("var")) {
141 // For now, only globals are supported 156 // For now, only globals are supported
142 if (g_CurMode != MODE_TOPLEVEL || g_CurState.len()) 157 if (g_CurMode != MODE_TOPLEVEL || g_CurState.len())
143 ParserError ("variables must only be global for now"); 158 ParserError ("variables must only be global for now");
144 159
145 // Variable definition
146 int type = !token.compare ("int") ? RETURNVAL_INT: RETURNVAL_BOOLEAN;
147
148 MustNext (); 160 MustNext ();
161
162 // Var name must not be a number
163 if (token.isnumber())
164 ParserError ("variable name must not be a number");
165
149 str varname = token; 166 str varname = token;
150 ScriptVar* var = DeclareGlobalVariable (this, varname, type); 167 ScriptVar* var = DeclareGlobalVariable (this, varname);
151 168
152 if (!var) 169 if (!var)
153 ParserError ("declaring %s variable %s failed", 170 ParserError ("declaring %s variable %s failed",
154 g_CurState.len() ? "state" : "global", varname.chars()); 171 g_CurState.len() ? "state" : "global", varname.chars());
155 172
156 // Assign it, if desired
157 if (!PeekNext().compare ("=")) {
158 MustNext ("=");
159 MustValue (type);
160
161 var->value = token;
162 }
163
164 MustNext (";"); 173 MustNext (";");
165 } else if (!token.compare ("}")) { 174 continue;
175 }
176
177 if (!token.compare ("}")) {
166 // Closing brace 178 // Closing brace
167 int dataheader = (g_CurMode == MODE_EVENT) ? DH_ENDEVENT : 179 int dataheader = (g_CurMode == MODE_EVENT) ? DH_ENDEVENT :
168 (g_CurMode == MODE_MAINLOOP) ? DH_ENDMAINLOOP : 180 (g_CurMode == MODE_MAINLOOP) ? DH_ENDMAINLOOP :
169 (g_CurMode == MODE_ONENTER) ? DH_ENDONENTER : 181 (g_CurMode == MODE_ONENTER) ? DH_ENDONENTER :
170 (g_CurMode == MODE_ONEXIT) ? DH_ENDONEXIT : -1; 182 (g_CurMode == MODE_ONEXIT) ? DH_ENDONEXIT : -1;
175 // Closing brace.. 187 // Closing brace..
176 w->Write (dataheader); 188 w->Write (dataheader);
177 g_CurMode = MODE_TOPLEVEL; 189 g_CurMode = MODE_TOPLEVEL;
178 190
179 MustNext (";"); 191 MustNext (";");
180 } else { 192 continue;
181 // Check if it's a command. 193 }
182 CommandDef* comm = GetCommandByName (token); 194 // Check global variables
183 if (comm) 195 ScriptVar* g = FindGlobalVariable (token);
184 ParseCommand (comm, w); 196 if (g) {
185 else 197 // Not in top level, unfortunately..
186 ParserError ("unknown keyword `%s`", token.chars()); 198 if (g_CurMode == MODE_TOPLEVEL)
187 } 199 ParserError ("can't alter variables at top level");
200
201 // Only addition for now..
202 MustNext ();
203
204 // Build operator string. Only '=' is one
205 // character, others are two.
206 str oper = token;
207 if (token.compare ("=") != 0) {
208 MustNext ();
209 oper += token;
210 }
211
212 // Unary operators
213 if (!oper.compare ("++")) {
214 w->Write<long> (DH_INCGLOBALVAR);
215 w->Write<long> (g->index);
216 } else if (!oper.compare ("--")) {
217 w->Write<long> (DH_DECGLOBALVAR);
218 w->Write<long> (g->index);
219 }
220
221 // And only with numbers for now too.
222 // TODO: make a proper expression parser!
223 MustNumber();
224
225 int val = atoi (token.chars());
226 w->Write<long> (DH_PUSHNUMBER);
227 w->Write<long> (val);
228
229 int dataheader = !oper.compare("=") ? DH_ASSIGNGLOBALVAR :
230 !oper.compare("+=") ? DH_ADDGLOBALVAR :
231 !oper.compare("-=") ? DH_SUBGLOBALVAR :
232 !oper.compare("*=") ? DH_MULGLOBALVAR :
233 !oper.compare("/=") ? DH_DIVGLOBALVAR :
234 !oper.compare("%=") ? DH_MODGLOBALVAR : -1;
235
236 if (dataheader == -1)
237 ParserError ("bad operator `%s`!", oper.chars());
238
239 w->Write<long> (dataheader);
240 w->Write<long> (g->index);
241
242 MustNext (";");
243 continue;
244 }
245
246 // Check if it's a command.
247 CommandDef* comm = GetCommandByName (token);
248 if (comm) {
249 ParseCommand (comm, w);
250 continue;
251 }
252
253 ParserError ("unknown keyword `%s`", token.chars());
188 } 254 }
189 255
190 if (g_CurMode != MODE_TOPLEVEL) 256 if (g_CurMode != MODE_TOPLEVEL)
191 ParserError ("script did not end at top level; did you forget a `}`?"); 257 ParserError ("script did not end at top level; did you forget a `}`?");
192 258
227 MustNext (")"); 293 MustNext (")");
228 curarg++; 294 curarg++;
229 break; 295 break;
230 } 296 }
231 297
232 /* 298 if (!PeekNext().len())
233 if (!Next ())
234 ParserError ("unexpected end-of-file, unterminated command"); 299 ParserError ("unexpected end-of-file, unterminated command");
235 300
236 // If we get a ")" now, the user probably gave too few parameters 301 // If we get a ")" now, the user probably gave too few parameters
237 if (!token.compare (")")) 302 if (!PeekNext().compare (")"))
238 ParserError ("unexpected `)`, did you pass too few parameters? (need %d)", comm->numargs); 303 ParserError ("unexpected `)`, did you pass too few parameters? (need %d)", comm->numargs);
239 */ 304
240 305 // Argument may be using a variable
241 switch (comm->argtypes[curarg]) { 306 ScriptVar* g = FindGlobalVariable (PeekNext ());
242 case RETURNVAL_INT: 307 if (g && comm->argtypes[curarg] != RETURNVAL_STRING) {
243 MustNumber(); 308 // Advance cursor past the var name
244 w->Write<long> (DH_PUSHNUMBER); 309 Next();
245 w->Write<long> (atoi (token.chars ())); 310
246 break; 311 w->Write<long> (DH_PUSHGLOBALVAR);
247 case RETURNVAL_BOOLEAN: 312 w->Write<long> (g->index);
248 MustBool(); 313 } else {
249 w->Write<long> (DH_PUSHNUMBER); 314 // Check for raw value
250 w->Write<long> (BoolValue ()); 315 switch (comm->argtypes[curarg]) {
251 break; 316 case RETURNVAL_INT:
252 case RETURNVAL_STRING: 317 MustNumber();
253 MustString(); 318 w->Write<long> (DH_PUSHNUMBER);
254 w->Write<long> (DH_PUSHSTRINGINDEX); 319 w->Write<long> (atoi (token.chars ()));
255 w->Write<long> (PushToStringTable (token.chars())); 320 break;
256 break; 321 case RETURNVAL_BOOLEAN:
322 MustBool();
323 w->Write<long> (DH_PUSHNUMBER);
324 w->Write<long> (BoolValue ());
325 break;
326 case RETURNVAL_STRING:
327 MustString();
328 w->Write<long> (DH_PUSHSTRINGINDEX);
329 w->Write<long> (PushToStringTable (token.chars()));
330 break;
331 }
257 } 332 }
258 333
259 if (curarg < comm->numargs - 1) { 334 if (curarg < comm->numargs - 1) {
260 MustNext (","); 335 MustNext (",");
261 } else if (curarg < comm->maxargs - 1) { 336 } else if (curarg < comm->maxargs - 1) {

mercurial