scriptreader.cxx

changeset 33
fd35f6cb5f28
parent 30
6c4efed2dbdd
child 34
0a9a5902beaa
equal deleted inserted replaced
32:d11a034aabfd 33:fd35f6cb5f28
43 #include "string.h" 43 #include "string.h"
44 #include "str.h" 44 #include "str.h"
45 #include "common.h" 45 #include "common.h"
46 #include "scriptreader.h" 46 #include "scriptreader.h"
47 47
48 static bool IsWhitespace (char c) {
49 // These characters are invisible, thus considered whitespace
50 if (c <= 32 || c == 127 || c == 255)
51 return true;
52
53 return false;
54 }
55
56 ScriptReader::ScriptReader (str path) { 48 ScriptReader::ScriptReader (str path) {
57 if (!(fp = fopen (path, "r"))) {
58 error ("couldn't open %s for reading!\n", path.chars ());
59 exit (1);
60 }
61
62 filepath = path;
63 curline = 1;
64 curchar = 1;
65 pos = 0;
66 token = ""; 49 token = "";
67 atnewline = false; 50 fc = -1;
51
52 for (unsigned int u = 0; u < MAX_FILESTACK; u++)
53 fp[u] = NULL;
54
55 OpenFile (path);
68 commentmode = 0; 56 commentmode = 0;
69 } 57 }
70 58
71 ScriptReader::~ScriptReader () { 59 ScriptReader::~ScriptReader () {
72 FinalChecks (); 60 FinalChecks ();
73 fclose (fp); 61
62 for (unsigned int u = 0; u < MAX_FILESTACK; u++) {
63 if (fp[u]) {
64 ParserWarning ("file idx %u remained open after parsing", u);
65 CloseFile (u);
66 }
67 }
68 }
69
70 // Opens a file and pushes its pointer to stack
71 void ScriptReader::OpenFile (str path) {
72 if (fc+1 >= MAX_FILESTACK)
73 ParserError ("supposed to open file `%s` but file stack is full! \
74 do you have recursive `#include` directives?",
75 path.chars());
76
77 // Save the position first.
78 if (fc != -1) {
79 savedpos[fc] = ftell (fp[fc]);
80 }
81
82 fc++;
83
84 fp[fc] = fopen (path, "r");
85 if (!fp[fc]) {
86 ParserError ("couldn't open %s for reading!\n", path.chars ());
87 exit (1);
88 }
89
90 fseek (fp[fc], 0, SEEK_SET);
91 filepath[fc] = path.chars();
92 curline[fc] = 1;
93 curchar[fc] = 1;
94 pos[fc] = 0;
95 atnewline = 0;
96 }
97
98 void ScriptReader::CloseFile (unsigned int u) {
99 if (u >= MAX_FILESTACK)
100 u = fc;
101
102 if (!fp[u])
103 return;
104
105 fclose (fp[u]);
106 fp[u] = NULL;
107 fc--;
108
109 if (fc != -1)
110 fseek (fp[fc], savedpos[fc], SEEK_SET);
74 } 111 }
75 112
76 char ScriptReader::ReadChar () { 113 char ScriptReader::ReadChar () {
114 if (feof (fp[fc]))
115 return 0;
116
77 char* c = (char*)malloc (sizeof (char)); 117 char* c = (char*)malloc (sizeof (char));
78 if (!fread (c, sizeof (char), 1, fp)) 118 if (!fread (c, sizeof (char), 1, fp[fc]))
79 return 0; 119 return 0;
80 120
81 // We're at a newline, thus next char read will begin the next line 121 // We're at a newline, thus next char read will begin the next line
82 if (atnewline) { 122 if (atnewline) {
83 atnewline = false; 123 atnewline = false;
84 curline++; 124 curline[fc]++;
85 curchar = 0; // gets incremented to 1 125 curchar[fc] = 0; // gets incremented to 1
86 } 126 }
87 127
88 if (c[0] == '\n') 128 if (c[0] == '\n') {
89 atnewline = true; 129 atnewline = true;
90 130
91 curchar++; 131 // Check for pre-processor directives
132 PreprocessDirectives ();
133 }
134
135 curchar[fc]++;
92 return c[0]; 136 return c[0];
93 } 137 }
94 138
95 char ScriptReader::PeekChar (int offset) { 139 char ScriptReader::PeekChar (int offset) {
96 // Store current position 140 // Store current position
97 long curpos = ftell (fp); 141 long curpos = ftell (fp[fc]);
98 142
99 // Forward by offset 143 // Forward by offset
100 fseek (fp, offset, SEEK_CUR); 144 fseek (fp[fc], offset, SEEK_CUR);
101 145
102 // Read the character 146 // Read the character
103 char* c = (char*)malloc (sizeof (char)); 147 char* c = (char*)malloc (sizeof (char));
104 if (!fread (c, sizeof (char), 1, fp)) 148
149 if (!fread (c, sizeof (char), 1, fp[fc])) {
150 fseek (fp[fc], curpos, SEEK_SET);
105 return 0; 151 return 0;
152 }
106 153
107 // Rewind back 154 // Rewind back
108 fseek (fp, curpos, SEEK_SET); 155 fseek (fp[fc], curpos, SEEK_SET);
109 156
110 return c[0]; 157 return c[0];
111 } 158 }
112 159
113 // true if was found, false if not. 160 // true if was found, false if not.
114 bool ScriptReader::Next () { 161 bool ScriptReader::Next (bool peek) {
115 str tmp = ""; 162 str tmp = "";
116 163 // printf ("begin token\n");
117 while (!feof (fp)) { 164
165 while (1) {
166 // Check end-of-file
167 if (feof (fp[fc])) {
168 // If we're just peeking, we shouldn't
169 // actually close anything..
170 if (peek)
171 break;
172
173 CloseFile ();
174 if (fc == -1)
175 break;
176 }
177
118 // Check if the next token possibly starts a comment. 178 // Check if the next token possibly starts a comment.
119 if (PeekChar () == '/' && !tmp.len()) { 179 if (PeekChar () == '/' && !tmp.len()) {
120 char c2 = PeekChar (1); 180 char c2 = PeekChar (1);
121 // C++-style comment 181 // C++-style comment
122 if (c2 == '/') 182 if (c2 == '/')
128 // comment characters, since they will get 188 // comment characters, since they will get
129 // ignored due to comment mode anyway. 189 // ignored due to comment mode anyway.
130 } 190 }
131 191
132 c = ReadChar (); 192 c = ReadChar ();
193 // printf ("add char [%d] `%c`\n", c, c);
133 194
134 // 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
135 // gets the comment terminated, otherwise ignore it. 196 // gets the comment terminated, otherwise ignore it.
136 if (commentmode > 0) { 197 if (commentmode > 0) {
137 if (commentmode == 1 && c == '\n') { 198 if (commentmode == 1 && c == '\n') {
140 continue; 201 continue;
141 } else if (commentmode == 2 && c == '*') { 202 } else if (commentmode == 2 && c == '*') {
142 // C-style comments are terminated by a `*/` 203 // C-style comments are terminated by a `*/`
143 if (PeekChar() == '/') { 204 if (PeekChar() == '/') {
144 commentmode = 0; 205 commentmode = 0;
145 // Now the char has to be read in since we
146 // no longer are reading a comment
147 ReadChar (); 206 ReadChar ();
148 } 207 }
149 } 208 }
150 209
151 // Otherwise, ignore it. 210 // Otherwise, ignore it.
159 if ((c >= 33 && c <= 47) || 218 if ((c >= 33 && c <= 47) ||
160 (c >= 58 && c <= 64) || 219 (c >= 58 && c <= 64) ||
161 (c >= 91 && c <= 96 && c != '_') || 220 (c >= 91 && c <= 96 && c != '_') ||
162 (c >= 123 && c <= 126)) { 221 (c >= 123 && c <= 126)) {
163 if (tmp.len()) 222 if (tmp.len())
164 fseek (fp, ftell (fp) - 1, SEEK_SET); 223 fseek (fp[fc], ftell (fp[fc]) - 1, SEEK_SET);
165 else 224 else
166 tmp += c; 225 tmp += c;
167 break; 226 break;
168 } 227 }
169 228
170 if (IsWhitespace (c)) { 229 if (IsCharWhitespace (c)) {
171 // Don't break if we haven't gathered anything yet. 230 // Don't break if we haven't gathered anything yet.
172 if (tmp.len()) 231 if (tmp.len())
173 break; 232 break;
174 } else { 233 } else {
175 tmp += c; 234 tmp += c;
181 if (!tmp.len()) { 240 if (!tmp.len()) {
182 token = ""; 241 token = "";
183 return false; 242 return false;
184 } 243 }
185 244
186 pos++; 245 pos[fc]++;
187 token = tmp; 246 token = tmp;
188 return true; 247 return true;
189 } 248 }
190 249
191 // Returns the next token without advancing the cursor. 250 // Returns the next token without advancing the cursor.
192 str ScriptReader::PeekNext () { 251 str ScriptReader::PeekNext () {
193 // Store current position 252 // Store current position
194 int cpos = ftell (fp); 253 int cpos = ftell (fp[fc]);
195 254
196 // Advance on the token. 255 // Advance on the token.
197 if (!Next ()) 256 if (!Next (true))
198 return ""; 257 return "";
199 258
200 str tmp = token; 259 str tmp = token;
201 260
202 // Restore position 261 // Restore position
203 fseek (fp, cpos, SEEK_SET); 262 fseek (fp[fc], cpos, SEEK_SET);
204 pos--; 263 pos[fc]--;
205 264
206 return tmp; 265 return tmp;
207 } 266 }
208 267
209 void ScriptReader::Seek (unsigned int n, int origin) { 268 void ScriptReader::Seek (unsigned int n, int origin) {
210 switch (origin) { 269 switch (origin) {
211 case SEEK_SET: 270 case SEEK_SET:
212 fseek (fp, 0, SEEK_SET); 271 fseek (fp[fc], 0, SEEK_SET);
213 pos = 0; 272 pos[fc] = 0;
214 break; 273 break;
215 case SEEK_CUR: 274 case SEEK_CUR:
216 break; 275 break;
217 case SEEK_END: 276 case SEEK_END:
218 printf ("ScriptReader::Seek: SEEK_END not yet supported.\n"); 277 printf ("ScriptReader::Seek: SEEK_END not yet supported.\n");
236 } 295 }
237 } 296 }
238 297
239 void ScriptReader::ParserError (const char* message, ...) { 298 void ScriptReader::ParserError (const char* message, ...) {
240 PERFORM_FORMAT (message, outmessage); 299 PERFORM_FORMAT (message, outmessage);
241 ParserMessage ("\nParse error\n", outmessage); 300 ParserMessage ("\nError: ", outmessage);
242 exit (1); 301 exit (1);
243 } 302 }
244 303
245 void ScriptReader::ParserWarning (const char* message, ...) { 304 void ScriptReader::ParserWarning (const char* message, ...) {
246 PERFORM_FORMAT (message, outmessage); 305 PERFORM_FORMAT (message, outmessage);
247 ParserMessage ("Warning: ", outmessage); 306 ParserMessage ("Warning: ", outmessage);
248 } 307 }
249 308
250 void ScriptReader::ParserMessage (const char* header, char* message) { 309 void ScriptReader::ParserMessage (const char* header, char* message) {
251 fprintf (stderr, "%sIn file %s, at line %u, col %u: %s\n", 310 if (fc >= 0 && fc < MAX_FILESTACK)
252 header, filepath.chars(), curline, curchar, message); 311 fprintf (stderr, "%sIn file %s, at line %u, col %u: %s\n",
312 header, filepath[fc], curline[fc], curchar[fc], message);
313 else
314 fprintf (stderr, "%s%s\n", header, message);
253 } 315 }
254 316
255 void ScriptReader::MustString () { 317 void ScriptReader::MustString () {
256 MustNext ("\""); 318 MustNext ("\"");
257 319
258 str string; 320 str string;
259 // Keep reading characters until we find a terminating quote. 321 // Keep reading characters until we find a terminating quote.
260 while (1) { 322 while (1) {
261 // can't end here! 323 // can't end here!
262 if (feof (fp)) 324 if (feof (fp[fc]))
263 ParserError ("unterminated string"); 325 ParserError ("unterminated string");
264 326
265 char c = ReadChar (); 327 char c = ReadChar ();
266 if (c == '"') 328 if (c == '"')
267 break; 329 break;

mercurial