160 fseek (fp[fc], curpos, SEEK_SET); |
168 fseek (fp[fc], curpos, SEEK_SET); |
161 |
169 |
162 return c[0]; |
170 return c[0]; |
163 } |
171 } |
164 |
172 |
|
173 // ============================================================================ |
165 // Read a token from the file buffer. Returns true if token was found, false if not. |
174 // Read a token from the file buffer. Returns true if token was found, false if not. |
166 bool ScriptReader::Next (bool peek) { |
175 bool ScriptReader::Next (bool peek) { |
167 prevpos = ftell (fp[fc]); |
176 prevpos = ftell (fp[fc]); |
168 str tmp = ""; |
177 str tmp = ""; |
169 |
178 |
250 prevtoken = token; |
259 prevtoken = token; |
251 token = tmp; |
260 token = tmp; |
252 return true; |
261 return true; |
253 } |
262 } |
254 |
263 |
255 void ScriptReader::Prev () { |
264 // ============================================================================ |
256 if (!prevpos) |
|
257 error ("ScriptReader::Prev: cannot go back twice!\n"); |
|
258 |
|
259 fseek (fp[fc], prevpos, SEEK_SET); |
|
260 prevpos = 0; |
|
261 token = prevtoken; |
|
262 } |
|
263 |
|
264 // Returns the next token without advancing the cursor. |
265 // Returns the next token without advancing the cursor. |
265 str ScriptReader::PeekNext (int offset) { |
266 str ScriptReader::PeekNext (int offset) { |
266 // Store current information |
267 // Store current information |
267 str storedtoken = token; |
268 str storedtoken = token; |
268 int cpos = ftell (fp[fc]); |
269 int cpos = ftell (fp[fc]); |
310 |
313 |
311 if (strlen (c)) |
314 if (strlen (c)) |
312 MustThis (c); |
315 MustThis (c); |
313 } |
316 } |
314 |
317 |
|
318 // ============================================================================ |
315 void ScriptReader::MustThis (const char* c) { |
319 void ScriptReader::MustThis (const char* c) { |
316 if (token.compare (c) != 0) |
320 if (token.compare (c) != 0) |
317 ParserError ("expected `%s`, got `%s` instead", c, token.chars()); |
321 ParserError ("expected `%s`, got `%s` instead", c, token.chars()); |
318 } |
322 } |
319 |
323 |
|
324 // ============================================================================ |
320 void ScriptReader::ParserError (const char* message, ...) { |
325 void ScriptReader::ParserError (const char* message, ...) { |
321 PERFORM_FORMAT (message, outmessage); |
326 PERFORM_FORMAT (message, outmessage); |
322 ParserMessage ("\nError: ", outmessage); |
327 ParserMessage ("\nError: ", outmessage); |
323 exit (1); |
328 exit (1); |
324 } |
329 } |
325 |
330 |
|
331 // ============================================================================ |
326 void ScriptReader::ParserWarning (const char* message, ...) { |
332 void ScriptReader::ParserWarning (const char* message, ...) { |
327 PERFORM_FORMAT (message, outmessage); |
333 PERFORM_FORMAT (message, outmessage); |
328 ParserMessage ("Warning: ", outmessage); |
334 ParserMessage ("Warning: ", outmessage); |
329 } |
335 } |
330 |
336 |
|
337 // ============================================================================ |
331 void ScriptReader::ParserMessage (const char* header, char* message) { |
338 void ScriptReader::ParserMessage (const char* header, char* message) { |
332 if (fc >= 0 && fc < MAX_FILESTACK) |
339 if (fc >= 0 && fc < MAX_FILESTACK) |
333 fprintf (stderr, "%sIn file %s, at line %u, col %u: %s\n", |
340 fprintf (stderr, "%sIn file %s, at line %u, col %u: %s\n", |
334 header, filepath[fc], curline[fc], curchar[fc], message); |
341 header, filepath[fc], curline[fc], curchar[fc], message); |
335 else |
342 else |
336 fprintf (stderr, "%s%s\n", header, message); |
343 fprintf (stderr, "%s%s\n", header, message); |
337 } |
344 } |
338 |
345 |
|
346 // ============================================================================ |
339 // if gotquote == 1, the current token already holds the quotation mark. |
347 // if gotquote == 1, the current token already holds the quotation mark. |
340 void ScriptReader::MustString (bool gotquote) { |
348 void ScriptReader::MustString (bool gotquote) { |
341 if (gotquote) |
349 if (gotquote) |
342 MustThis ("\""); |
350 MustThis ("\""); |
343 else |
351 else |
372 if (!token.compare ("-")) { |
381 if (!token.compare ("-")) { |
373 MustNext (); |
382 MustNext (); |
374 num += token; |
383 num += token; |
375 } |
384 } |
376 |
385 |
377 // Result must be a number. |
386 // "true" and "false" are valid numbers |
378 if (!num.isnumber()) |
387 if (!token.icompare ("true")) |
379 ParserError ("expected a number, got `%s`", num.chars()); |
388 token = "1"; |
380 |
389 else if (!token.icompare ("false")) |
381 // Save the number into the token. |
390 token = "0"; |
382 token = num; |
391 else { |
383 } |
392 if (!num.isnumber()) |
384 |
393 ParserError ("expected a number, got `%s`", num.chars()); |
385 void ScriptReader::MustBool () { |
394 token = num; |
386 MustNext(); |
395 } |
387 if (!token.compare ("0") || !token.compare ("1") || |
396 } |
388 !token.compare ("true") || !token.compare ("false") || |
|
389 !token.compare ("yes") || !token.compare ("no")) { |
|
390 return; |
|
391 } |
|
392 |
|
393 ParserError ("expected a boolean value, got `%s`", token.chars()); |
|
394 } |
|
395 |
|
396 bool ScriptReader::BoolValue () { |
|
397 return (!token.compare ("1") || !token.compare ("true") || !token.compare ("yes")); |
|
398 } |
|
399 |
|
400 void ScriptReader::MustValue (int type) { |
|
401 switch (type) { |
|
402 case RETURNVAL_INT: MustNumber (); break; |
|
403 case RETURNVAL_STRING: MustString (); break; |
|
404 case RETURNVAL_BOOLEAN: MustBool (); break; |
|
405 } |
|
406 } |
|