114 "Count of gTokenStrings is not the same as the amount of named token identifiers."); |
114 "Count of gTokenStrings is not the same as the amount of named token identifiers."); |
115 |
115 |
116 // ============================================================================= |
116 // ============================================================================= |
117 // |
117 // |
118 LexerScanner::LexerScanner (FILE* fp) : |
118 LexerScanner::LexerScanner (FILE* fp) : |
119 mLine (1) |
119 m_line (1) |
120 { |
120 { |
121 long fsize, bytes; |
121 long fsize, bytes; |
122 |
122 |
123 fseek (fp, 0l, SEEK_END); |
123 fseek (fp, 0l, SEEK_END); |
124 fsize = ftell (fp); |
124 fsize = ftell (fp); |
125 rewind (fp); |
125 rewind (fp); |
126 mData = new char[fsize]; |
126 m_data = new char[fsize]; |
127 mPosition = mLineBreakPosition = &mData[0]; |
127 m_position = m_lineBreakPosition = &m_data[0]; |
128 bytes = fread (mData, 1, fsize, fp); |
128 bytes = fread (m_data, 1, fsize, fp); |
129 assert (bytes >= fsize); |
129 assert (bytes >= fsize); |
130 } |
130 } |
131 |
131 |
132 // ============================================================================= |
132 // ============================================================================= |
133 // |
133 // |
134 LexerScanner::~LexerScanner() |
134 LexerScanner::~LexerScanner() |
135 { |
135 { |
136 delete mData; |
136 delete m_data; |
137 } |
137 } |
138 |
138 |
139 // ============================================================================= |
139 // ============================================================================= |
140 // |
140 // |
141 bool LexerScanner::CheckString (const char* c, int flags) |
141 bool LexerScanner::checkString (const char* c, int flags) |
142 { |
142 { |
143 bool r = strncmp (mPosition, c, strlen (c)) == 0; |
143 bool r = strncmp (m_position, c, strlen (c)) == 0; |
144 |
144 |
145 // There is to be a non-symbol character after words |
145 // There is to be a non-symbol character after words |
146 if (r && (flags & FCheckWord) && IsSymbolChar (mPosition[strlen (c)], true)) |
146 if (r && (flags & FCheckWord) && isSymbolChar (m_position[strlen (c)], true)) |
147 r = false; |
147 r = false; |
148 |
148 |
149 // Advance the cursor unless we want to just peek |
149 // Advance the cursor unless we want to just peek |
150 if (r && !(flags & FCheckPeek)) |
150 if (r && !(flags & FCheckPeek)) |
151 mPosition += strlen (c); |
151 m_position += strlen (c); |
152 |
152 |
153 return r; |
153 return r; |
154 } |
154 } |
155 |
155 |
156 // ============================================================================= |
156 // ============================================================================= |
157 // |
157 // |
158 bool LexerScanner::GetNextToken() |
158 bool LexerScanner::getNextToken() |
159 { |
159 { |
160 mTokenText = ""; |
160 m_tokenText = ""; |
161 |
161 |
162 while (isspace (*mPosition)) |
162 while (isspace (*m_position)) |
163 Skip(); |
163 skip(); |
164 |
164 |
165 // Check for comments |
165 // Check for comments |
166 if (strncmp (mPosition, "//", 2) == 0) |
166 if (strncmp (m_position, "//", 2) == 0) |
167 { |
167 { |
168 mPosition += 2; |
168 m_position += 2; |
169 |
169 |
170 while (*mPosition != '\n') |
170 while (*m_position != '\n') |
171 Skip(); |
171 skip(); |
172 |
172 |
173 return GetNextToken(); |
173 return getNextToken(); |
174 } |
174 } |
175 elif (strncmp (mPosition, "/*", 2) == 0) |
175 elif (strncmp (m_position, "/*", 2) == 0) |
176 { |
176 { |
177 Skip (2); // skip the start symbols |
177 skip (2); // skip the start symbols |
178 |
178 |
179 while (strncmp (mPosition, "*/", 2) != 0) |
179 while (strncmp (m_position, "*/", 2) != 0) |
180 Skip(); |
180 skip(); |
181 |
181 |
182 Skip (2); // skip the end symbols |
182 skip (2); // skip the end symbols |
183 return GetNextToken(); |
183 return getNextToken(); |
184 } |
184 } |
185 |
185 |
186 if (*mPosition == '\0') |
186 if (*m_position == '\0') |
187 return false; |
187 return false; |
188 |
188 |
189 // Check tokens |
189 // Check tokens |
190 for (int i = 0; i < countof (gTokenStrings); ++i) |
190 for (int i = 0; i < countof (gTokenStrings); ++i) |
191 { |
191 { |
192 int flags = 0; |
192 int flags = 0; |
193 |
193 |
194 if (i >= gFirstNamedToken) |
194 if (i >= gFirstNamedToken) |
195 flags |= FCheckWord; |
195 flags |= FCheckWord; |
196 |
196 |
197 if (CheckString (gTokenStrings[i], flags)) |
197 if (checkString (gTokenStrings[i], flags)) |
198 { |
198 { |
199 mTokenText = gTokenStrings[i]; |
199 m_tokenText = gTokenStrings[i]; |
200 mTokenType = (ETokenType) i; |
200 m_tokenType = (ETokenType) i; |
201 return true; |
201 return true; |
202 } |
202 } |
203 } |
203 } |
204 |
204 |
205 // Check and parse string |
205 // Check and parse string |
206 if (*mPosition == '\"') |
206 if (*m_position == '\"') |
207 { |
207 { |
208 mPosition++; |
208 m_position++; |
209 |
209 |
210 while (*mPosition != '\"') |
210 while (*m_position != '\"') |
211 { |
211 { |
212 if (!*mPosition) |
212 if (!*m_position) |
213 Error ("unterminated string"); |
213 error ("unterminated string"); |
214 |
214 |
215 if (CheckString ("\\n")) |
215 if (checkString ("\\n")) |
216 { |
216 { |
217 mTokenText += '\n'; |
217 m_tokenText += '\n'; |
218 continue; |
218 continue; |
219 } |
219 } |
220 elif (CheckString ("\\t")) |
220 elif (checkString ("\\t")) |
221 { |
221 { |
222 mTokenText += '\t'; |
222 m_tokenText += '\t'; |
223 continue; |
223 continue; |
224 } |
224 } |
225 elif (CheckString ("\\\"")) |
225 elif (checkString ("\\\"")) |
226 { |
226 { |
227 mTokenText += '"'; |
227 m_tokenText += '"'; |
228 continue; |
228 continue; |
229 } |
229 } |
230 |
230 |
231 mTokenText += *mPosition++; |
231 m_tokenText += *m_position++; |
232 } |
232 } |
233 |
233 |
234 mTokenType =TK_String; |
234 m_tokenType =TK_String; |
235 Skip(); // skip the final quote |
235 skip(); // skip the final quote |
236 return true; |
236 return true; |
237 } |
237 } |
238 |
238 |
239 if (isdigit (*mPosition)) |
239 if (isdigit (*m_position)) |
240 { |
240 { |
241 while (isdigit (*mPosition)) |
241 while (isdigit (*m_position)) |
242 mTokenText += *mPosition++; |
242 m_tokenText += *m_position++; |
243 |
243 |
244 mTokenType =TK_Number; |
244 m_tokenType =TK_Number; |
245 return true; |
245 return true; |
246 } |
246 } |
247 |
247 |
248 if (IsSymbolChar (*mPosition, false)) |
248 if (isSymbolChar (*m_position, false)) |
249 { |
249 { |
250 mTokenType =TK_Symbol; |
250 m_tokenType =TK_Symbol; |
251 |
251 |
252 do |
252 do |
253 { |
253 { |
254 if (!IsSymbolChar (*mPosition, true)) |
254 if (!isSymbolChar (*m_position, true)) |
255 break; |
255 break; |
256 |
256 |
257 mTokenText += *mPosition++; |
257 m_tokenText += *m_position++; |
258 } while (*mPosition != '\0'); |
258 } while (*m_position != '\0'); |
259 |
259 |
260 return true; |
260 return true; |
261 } |
261 } |
262 |
262 |
263 Error ("unknown character \"%1\"", *mPosition); |
263 error ("unknown character \"%1\"", *m_position); |
264 return false; |
264 return false; |
265 } |
265 } |
266 |
266 |
267 // ============================================================================= |
267 // ============================================================================= |
268 // |
268 // |
269 void LexerScanner::Skip() |
269 void LexerScanner::skip() |
270 { |
270 { |
271 if (*mPosition == '\n') |
271 if (*m_position == '\n') |
272 { |
272 { |
273 mLine++; |
273 m_line++; |
274 mLineBreakPosition = mPosition; |
274 m_lineBreakPosition = m_position; |
275 } |
275 } |
276 |
276 |
277 mPosition++; |
277 m_position++; |
278 } |
278 } |
279 |
279 |
280 // ============================================================================= |
280 // ============================================================================= |
281 // |
281 // |
282 void LexerScanner::Skip (int chars) |
282 void LexerScanner::skip (int chars) |
283 { |
283 { |
284 for (int i = 0; i < chars; ++i) |
284 for (int i = 0; i < chars; ++i) |
285 Skip(); |
285 skip(); |
286 } |
286 } |
287 |
287 |
288 // ============================================================================= |
288 // ============================================================================= |
289 // |
289 // |
290 String LexerScanner::GetTokenString (ETokenType a) |
290 String LexerScanner::getTokenString (ETokenType a) |
291 { |
291 { |
292 assert ((int) a <= gLastNamedToken); |
292 assert ((int) a <= gLastNamedToken); |
293 return gTokenStrings[a]; |
293 return gTokenStrings[a]; |
294 } |
294 } |
295 |
295 |
296 // ============================================================================= |
296 // ============================================================================= |
297 // |
297 // |
298 String LexerScanner::ReadLine() |
298 String LexerScanner::readLine() |
299 { |
299 { |
300 String line; |
300 String line; |
301 |
301 |
302 while (*mPosition != '\n') |
302 while (*m_position != '\n') |
303 line += *(mPosition++); |
303 line += *(m_position++); |
304 |
304 |
305 return line; |
305 return line; |
306 } |
306 } |