68 } |
70 } |
69 |
71 |
70 // Opens a file and pushes its pointer to stack |
72 // Opens a file and pushes its pointer to stack |
71 void ScriptReader::OpenFile (str path) { |
73 void ScriptReader::OpenFile (str path) { |
72 if (fc+1 >= MAX_FILESTACK) |
74 if (fc+1 >= MAX_FILESTACK) |
73 ParserError ("supposed to open file `%s` but file stack is full! \ |
75 ParserError ("supposed to open file `%s` but file stack is full! do you have recursive `#include` directives?", |
74 do you have recursive `#include` directives?", |
|
75 path.chars()); |
76 path.chars()); |
76 |
77 |
77 // Save the position first. |
78 // Save the position first. |
78 if (fc != -1) { |
79 if (fc != -1) { |
79 savedpos[fc] = ftell (fp[fc]); |
80 savedpos[fc] = ftell (fp[fc]); |
155 fseek (fp[fc], curpos, SEEK_SET); |
156 fseek (fp[fc], curpos, SEEK_SET); |
156 |
157 |
157 return c[0]; |
158 return c[0]; |
158 } |
159 } |
159 |
160 |
160 // true if was found, false if not. |
161 // Read a token from the file buffer. Returns true if token was found, false if not. |
161 bool ScriptReader::Next (bool peek) { |
162 bool ScriptReader::Next (bool peek) { |
|
163 prevpos = ftell (fp[fc]); |
162 str tmp = ""; |
164 str tmp = ""; |
163 // printf ("begin token\n"); |
|
164 |
165 |
165 while (1) { |
166 while (1) { |
166 // Check end-of-file |
167 // Check end-of-file |
167 if (feof (fp[fc])) { |
168 if (feof (fp[fc])) { |
168 // If we're just peeking, we shouldn't |
169 // If we're just peeking, we shouldn't |
188 // comment characters, since they will get |
189 // comment characters, since they will get |
189 // ignored due to comment mode anyway. |
190 // ignored due to comment mode anyway. |
190 } |
191 } |
191 |
192 |
192 c = ReadChar (); |
193 c = ReadChar (); |
193 // printf ("add char [%d] `%c`\n", c, c); |
|
194 |
194 |
195 // If this is a comment we're reading, check if this character |
195 // If this is a comment we're reading, check if this character |
196 // gets the comment terminated, otherwise ignore it. |
196 // gets the comment terminated, otherwise ignore it. |
197 if (commentmode > 0) { |
197 if (commentmode > 0) { |
198 if (commentmode == 1 && c == '\n') { |
198 if (commentmode == 1 && c == '\n') { |
234 tmp += c; |
234 tmp += c; |
235 } |
235 } |
236 } |
236 } |
237 |
237 |
238 // If we got nothing here, read failed. This should |
238 // If we got nothing here, read failed. This should |
239 // only hapen in the case of EOF. |
239 // only happen in the case of EOF. |
240 if (!tmp.len()) { |
240 if (!tmp.len()) { |
241 token = ""; |
241 token = ""; |
242 return false; |
242 return false; |
243 } |
243 } |
244 |
244 |
245 pos[fc]++; |
245 pos[fc]++; |
|
246 prevtoken = token; |
246 token = tmp; |
247 token = tmp; |
247 return true; |
248 return true; |
248 } |
249 } |
249 |
250 |
|
251 void ScriptReader::Prev () { |
|
252 if (!prevpos) |
|
253 error ("ScriptReader::Prev: cannot go back twice!\n"); |
|
254 |
|
255 fseek (fp[fc], prevpos, SEEK_SET); |
|
256 prevpos = 0; |
|
257 token = prevtoken; |
|
258 } |
|
259 |
250 // Returns the next token without advancing the cursor. |
260 // Returns the next token without advancing the cursor. |
251 str ScriptReader::PeekNext () { |
261 str ScriptReader::PeekNext (int offset) { |
252 // Store current position |
262 // Store current information |
|
263 str storedtoken = token; |
253 int cpos = ftell (fp[fc]); |
264 int cpos = ftell (fp[fc]); |
254 |
265 |
255 // Advance on the token. |
266 // Advance on the token. |
256 if (!Next (true)) |
267 while (offset >= 0) { |
257 return ""; |
268 if (!Next (true)) |
|
269 return ""; |
|
270 offset--; |
|
271 } |
258 |
272 |
259 str tmp = token; |
273 str tmp = token; |
260 |
274 |
261 // Restore position |
275 // Restore position |
262 fseek (fp[fc], cpos, SEEK_SET); |
276 fseek (fp[fc], cpos, SEEK_SET); |
263 pos[fc]--; |
277 pos[fc]--; |
264 |
278 token = storedtoken; |
265 return tmp; |
279 return tmp; |
266 } |
280 } |
267 |
281 |
268 void ScriptReader::Seek (unsigned int n, int origin) { |
282 void ScriptReader::Seek (unsigned int n, int origin) { |
269 switch (origin) { |
283 switch (origin) { |
288 ParserError ("expected `%s`, reached end of file instead\n", c); |
302 ParserError ("expected `%s`, reached end of file instead\n", c); |
289 else |
303 else |
290 ParserError ("expected a token, reached end of file instead\n"); |
304 ParserError ("expected a token, reached end of file instead\n"); |
291 } |
305 } |
292 |
306 |
293 if (strlen (c) && token.compare (c) != 0) { |
307 if (strlen (c)) |
|
308 MustThis (c); |
|
309 } |
|
310 |
|
311 void ScriptReader::MustThis (const char* c) { |
|
312 if (token.compare (c) != 0) |
294 ParserError ("expected `%s`, got `%s` instead", c, token.chars()); |
313 ParserError ("expected `%s`, got `%s` instead", c, token.chars()); |
295 } |
|
296 } |
314 } |
297 |
315 |
298 void ScriptReader::ParserError (const char* message, ...) { |
316 void ScriptReader::ParserError (const char* message, ...) { |
299 PERFORM_FORMAT (message, outmessage); |
317 PERFORM_FORMAT (message, outmessage); |
300 ParserMessage ("\nError: ", outmessage); |
318 ParserMessage ("\nError: ", outmessage); |
312 header, filepath[fc], curline[fc], curchar[fc], message); |
330 header, filepath[fc], curline[fc], curchar[fc], message); |
313 else |
331 else |
314 fprintf (stderr, "%s%s\n", header, message); |
332 fprintf (stderr, "%s%s\n", header, message); |
315 } |
333 } |
316 |
334 |
317 void ScriptReader::MustString () { |
335 // if gotquote == 1, the current token already holds the quotation mark. |
318 MustNext ("\""); |
336 void ScriptReader::MustString (bool gotquote) { |
|
337 if (gotquote) |
|
338 MustThis ("\""); |
|
339 else |
|
340 MustNext ("\""); |
319 |
341 |
320 str string; |
342 str string; |
321 // Keep reading characters until we find a terminating quote. |
343 // Keep reading characters until we find a terminating quote. |
322 while (1) { |
344 while (1) { |
323 // can't end here! |
345 // can't end here! |