61 checkFileHeader (sc); |
61 checkFileHeader (sc); |
62 |
62 |
63 while (sc.getNextToken()) |
63 while (sc.getNextToken()) |
64 { |
64 { |
65 // Preprocessor commands: |
65 // Preprocessor commands: |
66 if (sc.getTokenType() ==TK_Hash) |
66 if (sc.getTokenType() ==Token::Hash) |
67 { |
67 { |
68 mustGetFromScanner (sc,TK_Symbol); |
68 mustGetFromScanner (sc,Token::Symbol); |
69 |
69 |
70 if (sc.getTokenText() == "include") |
70 if (sc.getTokenText() == "include") |
71 { |
71 { |
72 mustGetFromScanner (sc,TK_String); |
72 mustGetFromScanner (sc,Token::String); |
73 String fileName = sc.getTokenText(); |
73 String fileName = sc.getTokenText(); |
74 |
74 |
75 if (gFileNameStack.contains (fileName)) |
75 if (gFileNameStack.contains (fileName)) |
76 error ("attempted to #include %1 recursively", sc.getTokenText()); |
76 error ("attempted to #include %1 recursively", sc.getTokenText()); |
77 |
77 |
108 if (header.endsWith ("\n")) |
108 if (header.endsWith ("\n")) |
109 header.removeFromEnd (1); |
109 header.removeFromEnd (1); |
110 |
110 |
111 StringList tokens = header.split (" "); |
111 StringList tokens = header.split (" "); |
112 |
112 |
113 if (tokens.size() != 2 || tokens[0] != "#!botc" || tokens[1].isEmpty()) |
113 if (tokens.size() != 2 or tokens[0] != "#!botc" or tokens[1].isEmpty()) |
114 return false; |
114 return false; |
115 |
115 |
116 StringList nums = tokens[1].split ("."); |
116 StringList nums = tokens[1].split ("."); |
117 |
117 |
118 if (nums.size() == 2) |
118 if (nums.size() == 2) |
123 bool okA, okB, okC; |
123 bool okA, okB, okC; |
124 long major = nums[0].toLong (&okA); |
124 long major = nums[0].toLong (&okA); |
125 long minor = nums[1].toLong (&okB); |
125 long minor = nums[1].toLong (&okB); |
126 long patch = nums[2].toLong (&okC); |
126 long patch = nums[2].toLong (&okC); |
127 |
127 |
128 if (!okA || !okB || !okC) |
128 if (!okA or !okB or !okC) |
129 return false; |
129 return false; |
130 |
130 |
131 if (VERSION_NUMBER < MAKE_VERSION_NUMBER (major, minor, patch)) |
131 if (VERSION_NUMBER < MAKE_VERSION_NUMBER (major, minor, patch)) |
132 error ("The script file requires " APPNAME " v%1, this is v%2", |
132 error ("The script file requires " APPNAME " v%1, this is v%2", |
133 makeVersionString (major, minor, patch), versionString (false)); |
133 makeVersionString (major, minor, patch), versionString (false)); |
143 error ("Not a valid botscript file! File must start with '#!botc <version>'"); |
143 error ("Not a valid botscript file! File must start with '#!botc <version>'"); |
144 } |
144 } |
145 |
145 |
146 // ============================================================================= |
146 // ============================================================================= |
147 // |
147 // |
148 bool Lexer::next (ETokenType req) |
148 bool Lexer::next (Token req) |
149 { |
149 { |
150 Iterator pos = m_tokenPosition; |
150 Iterator pos = m_tokenPosition; |
151 |
151 |
152 if (m_tokens.isEmpty()) |
152 if (m_tokens.isEmpty()) |
153 return false; |
153 return false; |
154 |
154 |
155 m_tokenPosition++; |
155 m_tokenPosition++; |
156 |
156 |
157 if (isAtEnd() || (req !=TK_Any && tokenType() != req)) |
157 if (isAtEnd() or (req !=Token::Any and tokenType() != req)) |
158 { |
158 { |
159 m_tokenPosition = pos; |
159 m_tokenPosition = pos; |
160 return false; |
160 return false; |
161 } |
161 } |
162 |
162 |
163 return true; |
163 return true; |
164 } |
164 } |
165 |
165 |
166 // ============================================================================= |
166 // ============================================================================= |
167 // |
167 // |
168 void Lexer::mustGetNext (ETokenType tok) |
168 void Lexer::mustGetNext (Token tok) |
169 { |
169 { |
170 if (!next()) |
170 if (!next()) |
171 error ("unexpected EOF"); |
171 error ("unexpected EOF"); |
172 |
172 |
173 if (tok !=TK_Any) |
173 if (tok !=Token::Any) |
174 tokenMustBe (tok); |
174 tokenMustBe (tok); |
175 } |
175 } |
176 |
176 |
177 // ============================================================================= |
177 // ============================================================================= |
178 // eugh.. |
178 // eugh.. |
179 // |
179 // |
180 void Lexer::mustGetFromScanner (LexerScanner& sc, ETokenType tt) |
180 void Lexer::mustGetFromScanner (LexerScanner& sc, Token tt) |
181 { |
181 { |
182 if (sc.getNextToken() == false) |
182 if (sc.getNextToken() == false) |
183 error ("unexpected EOF"); |
183 error ("unexpected EOF"); |
184 |
184 |
185 if (tt != TK_Any && sc.getTokenType() != tt) |
185 if (tt != Token::Any and sc.getTokenType() != tt) |
186 { |
186 { |
187 // TODO |
187 // TODO |
188 TokenInfo tok; |
188 TokenInfo tok; |
189 tok.type = sc.getTokenType(); |
189 tok.type = sc.getTokenType(); |
190 tok.text = sc.getTokenText(); |
190 tok.text = sc.getTokenText(); |
197 } |
197 } |
198 } |
198 } |
199 |
199 |
200 // ============================================================================= |
200 // ============================================================================= |
201 // |
201 // |
202 void Lexer::mustGetAnyOf (const List<ETokenType>& toks) |
202 void Lexer::mustGetAnyOf (const List<Token>& toks) |
203 { |
203 { |
204 if (!next()) |
204 if (!next()) |
205 error ("unexpected EOF"); |
205 error ("unexpected EOF"); |
206 |
206 |
207 for (ETokenType tok : toks) |
207 for (Token tok : toks) |
208 if (tokenType() == tok) |
208 if (tokenType() == tok) |
209 return; |
209 return; |
210 |
210 |
211 String toknames; |
211 String toknames; |
212 |
212 |
213 for (const ETokenType& tokType : toks) |
213 for (const Token& tokType : toks) |
214 { |
214 { |
215 if (&tokType == &toks.last()) |
215 if (&tokType == &toks.last()) |
216 toknames += " or "; |
216 toknames += " or "; |
217 elif (toknames.isEmpty() == false) |
217 elif (toknames.isEmpty() == false) |
218 toknames += ", "; |
218 toknames += ", "; |
228 int Lexer::getOneSymbol (const StringList& syms) |
228 int Lexer::getOneSymbol (const StringList& syms) |
229 { |
229 { |
230 if (!next()) |
230 if (!next()) |
231 error ("unexpected EOF"); |
231 error ("unexpected EOF"); |
232 |
232 |
233 if (tokenType() ==TK_Symbol) |
233 if (tokenType() ==Token::Symbol) |
234 { |
234 { |
235 for (int i = 0; i < syms.size(); ++i) |
235 for (int i = 0; i < syms.size(); ++i) |
236 { |
236 { |
237 if (syms[i] == token()->text) |
237 if (syms[i] == token()->text) |
238 return i; |
238 return i; |
243 return -1; |
243 return -1; |
244 } |
244 } |
245 |
245 |
246 // ============================================================================= |
246 // ============================================================================= |
247 // |
247 // |
248 void Lexer::tokenMustBe (ETokenType tok) |
248 void Lexer::tokenMustBe (Token tok) |
249 { |
249 { |
250 if (tokenType() != tok) |
250 if (tokenType() != tok) |
251 error ("expected %1, got %2", describeTokenType (tok), |
251 error ("expected %1, got %2", describeTokenType (tok), |
252 describeToken (token())); |
252 describeToken (token())); |
253 } |
253 } |
254 |
254 |
255 // ============================================================================= |
255 // ============================================================================= |
256 // |
256 // |
257 String Lexer::describeTokenPrivate (ETokenType tokType, Lexer::TokenInfo* tok) |
257 String Lexer::describeTokenPrivate (Token tokType, Lexer::TokenInfo* tok) |
258 { |
258 { |
259 if (tokType <gLastNamedToken) |
259 if (tokType <gLastNamedToken) |
260 return "\"" + LexerScanner::getTokenString (tokType) + "\""; |
260 return "\"" + LexerScanner::GetTokenString (tokType) + "\""; |
261 |
261 |
262 switch (tokType) |
262 switch (tokType) |
263 { |
263 { |
264 case TK_Symbol: return tok ? tok->text : "a symbol"; |
264 case Token::Symbol: return tok ? tok->text : "a symbol"; |
265 case TK_Number: return tok ? tok->text : "a number"; |
265 case Token::Number: return tok ? tok->text : "a number"; |
266 case TK_String: return tok ? ("\"" + tok->text + "\"") : "a string"; |
266 case Token::String: return tok ? ("\"" + tok->text + "\"") : "a string"; |
267 case TK_Any: return tok ? tok->text : "any token"; |
267 case Token::Any: return tok ? tok->text : "any token"; |
268 default: break; |
268 default: break; |
269 } |
269 } |
270 |
270 |
271 return ""; |
271 return ""; |
272 } |
272 } |
276 bool Lexer::peekNext (Lexer::TokenInfo* tk) |
276 bool Lexer::peekNext (Lexer::TokenInfo* tk) |
277 { |
277 { |
278 Iterator pos = m_tokenPosition; |
278 Iterator pos = m_tokenPosition; |
279 bool r = next(); |
279 bool r = next(); |
280 |
280 |
281 if (r && tk != null) |
281 if (r and tk != null) |
282 *tk = *m_tokenPosition; |
282 *tk = *m_tokenPosition; |
283 |
283 |
284 m_tokenPosition = pos; |
284 m_tokenPosition = pos; |
285 return r; |
285 return r; |
286 } |
286 } |
287 |
287 |
288 // ============================================================================= |
288 // ============================================================================= |
289 // |
289 // |
290 bool Lexer::peekNextType (ETokenType req) |
290 bool Lexer::peekNextType (Token req) |
291 { |
291 { |
292 Iterator pos = m_tokenPosition; |
292 Iterator pos = m_tokenPosition; |
293 bool result = false; |
293 bool result = false; |
294 |
294 |
295 if (next() && tokenType() == req) |
295 if (next() and tokenType() == req) |
296 result = true; |
296 result = true; |
297 |
297 |
298 m_tokenPosition = pos; |
298 m_tokenPosition = pos; |
299 return result; |
299 return result; |
300 } |
300 } |
336 |
336 |
337 // ============================================================================= |
337 // ============================================================================= |
338 // |
338 // |
339 void Lexer::mustGetSymbol (const String& a) |
339 void Lexer::mustGetSymbol (const String& a) |
340 { |
340 { |
341 mustGetNext (TK_Any); |
341 mustGetNext (Token::Any); |
342 if (token()->text != a) |
342 if (token()->text != a) |
343 error ("expected \"%1\", got \"%2\"", a, token()->text); |
343 error ("expected \"%1\", got \"%2\"", a, token()->text); |
344 } |
344 } |