1 #ifndef GMQCC_LEXER_HDR
2 #define GMQCC_LEXER_HDR
7 /* Other tokens which we can return: */ \
12 X(BACKSLASH, = '\\') \
32 X(QUOT_SINGLE, = '\'') \
33 X(QUOT_DOUBLE, = '"') \
35 X(BRACE_OPEN, = '{') \
36 X(BRACE_CLOSE, = '}') \
37 X(BRACKET_OPEN, = '[') \
38 X(BRACKET_CLOSE, = ']') \
39 X(PAREN_OPEN, = '(') \
40 X(PAREN_CLOSE, = ')') \
58 X(ATTRIBUTE_CLOSE, ) \
59 /* for the ftepp only */ \
61 /* for the ftepp only */ \
63 /* to get the count of vaargs */ \
65 /* not the typename but an actual "string" */ \
73 /* if we add additional tokens before this, the exposed API \
74 * should not be broken anyway, but EOF/ERROR/... should \
75 * still be at the bottom \
78 /* We use '< ERROR', so FATAL must come after it and any \
79 * other error related tokens as well \
82 /* internal error, eg out of memory */ \
86 enum Token : int { // todo: enum class
87 #define X(id, val) id val,
92 inline const char *TokenName(Token t) {
96 #define X(id, val) case Token::id: return #id;
105 explicit cvec() = default;
111 const char *c_str() {
112 return value.c_str();
115 void shrinkto(size_t i) {
119 void shrinkby(size_t i) {
120 value.resize(value.size() - i);
135 qc_type t; /* type */
147 const char *open_string;
148 size_t open_string_length;
149 size_t open_string_pos;
153 size_t sline; /* line at the start of a token */
156 std::array<Token, 256> peek;
161 token tok; /* not a pointer anymore */
165 bool nodigraphs:1; /* used when lexing string constants */
166 bool preprocessing:1; /* whitespace and EOLs become actual tokens */
167 bool mergelines:1; /* backslash at the end of a line escapes the newline */
168 } flags; /* sizeof == 1 */
172 std::string modelname;
177 lex_file *lex_open(const char *file);
179 lex_file *lex_open_string(const char *str, size_t len, const char *name);
181 void lex_close(lex_file *lex);
183 Token lex_do(lex_file *lex);
201 unsigned int operands;
210 * Explicit uint8_t casts since the left operand of shift operator cannot
211 * be negative, even though it won't happen, this supresses the future
214 #define opid1(a) ((uint8_t)a)
215 #define opid2(a, b) (((uint8_t)a<<8) |(uint8_t)b)
216 #define opid3(a, b, c) (((uint8_t)a<<16)|((uint8_t)b<<8)|(uint8_t)c)
218 static const oper_info c_operators[] = {
219 {"(", 0, opid1('('), ASSOC_LEFT, 99, OP_PREFIX, false}, /* paren expression - non function call */
220 {"_length", 1, opid3('l', 'e', 'n'), ASSOC_RIGHT, 98, OP_PREFIX, true},
222 {"++", 1, opid3('S', '+', '+'), ASSOC_LEFT, 17, OP_SUFFIX, false},
223 {"--", 1, opid3('S', '-', '-'), ASSOC_LEFT, 17, OP_SUFFIX, false},
224 {".", 2, opid1('.'), ASSOC_LEFT, 17, 0, false},
225 {"(", 0, opid1('('), ASSOC_LEFT, 17, 0, false}, /* function call */
226 {"[", 2, opid1('['), ASSOC_LEFT, 17, 0, false}, /* array subscript */
228 {"++", 1, opid3('+', '+', 'P'), ASSOC_RIGHT, 16, OP_PREFIX, false},
229 {"--", 1, opid3('-', '-', 'P'), ASSOC_RIGHT, 16, OP_PREFIX, false},
231 {"**", 2, opid2('*', '*'), ASSOC_RIGHT, 14, 0, true},
232 {"!", 1, opid2('!', 'P'), ASSOC_RIGHT, 14, OP_PREFIX, true},
233 {"~", 1, opid2('~', 'P'), ASSOC_RIGHT, 14, OP_PREFIX, true},
234 {"+", 1, opid2('+', 'P'), ASSOC_RIGHT, 14, OP_PREFIX, false},
235 {"-", 1, opid2('-', 'P'), ASSOC_RIGHT, 14, OP_PREFIX, true},
236 /* { "&", 1, opid2('&','P'), ASSOC_RIGHT, 14, OP_PREFIX, false}, */
238 {"*", 2, opid1('*'), ASSOC_LEFT, 13, 0, true},
239 {"/", 2, opid1('/'), ASSOC_LEFT, 13, 0, true},
240 {"%", 2, opid1('%'), ASSOC_LEFT, 13, 0, true},
241 {"><", 2, opid2('>', '<'), ASSOC_LEFT, 13, 0, true},
243 {"+", 2, opid1('+'), ASSOC_LEFT, 12, 0, true},
244 {"-", 2, opid1('-'), ASSOC_LEFT, 12, 0, true},
246 {"<<", 2, opid2('<', '<'), ASSOC_LEFT, 11, 0, true},
247 {">>", 2, opid2('>', '>'), ASSOC_LEFT, 11, 0, true},
249 {"<", 2, opid1('<'), ASSOC_LEFT, 10, 0, false},
250 {">", 2, opid1('>'), ASSOC_LEFT, 10, 0, false},
251 {"<=>", 2, opid3('<', '=', '>'), ASSOC_LEFT, 10, 0, true},
252 {"<=", 2, opid2('<', '='), ASSOC_LEFT, 10, 0, false},
253 {">=", 2, opid2('>', '='), ASSOC_LEFT, 10, 0, false},
255 {"==", 2, opid2('=', '='), ASSOC_LEFT, 9, 0, true},
256 {"!=", 2, opid2('!', '='), ASSOC_LEFT, 9, 0, true},
258 {"&", 2, opid1('&'), ASSOC_LEFT, 8, 0, true},
260 {"^", 2, opid1('^'), ASSOC_LEFT, 7, 0, true},
262 {"|", 2, opid1('|'), ASSOC_LEFT, 6, 0, true},
264 {"&&", 2, opid2('&', '&'), ASSOC_LEFT, 5, 0, true},
266 {"||", 2, opid2('|', '|'), ASSOC_LEFT, 4, 0, true},
268 {"?", 3, opid2('?', ':'), ASSOC_RIGHT, 3, 0, true},
270 {"=", 2, opid1('='), ASSOC_RIGHT, 2, 0, false},
271 {"+=", 2, opid2('+', '='), ASSOC_RIGHT, 2, 0, false},
272 {"-=", 2, opid2('-', '='), ASSOC_RIGHT, 2, 0, false},
273 {"*=", 2, opid2('*', '='), ASSOC_RIGHT, 2, 0, false},
274 {"/=", 2, opid2('/', '='), ASSOC_RIGHT, 2, 0, false},
275 {"%=", 2, opid2('%', '='), ASSOC_RIGHT, 2, 0, false},
276 {">>=", 2, opid3('>', '>', '='), ASSOC_RIGHT, 2, 0, false},
277 {"<<=", 2, opid3('<', '<', '='), ASSOC_RIGHT, 2, 0, false},
278 {"&=", 2, opid2('&', '='), ASSOC_RIGHT, 2, 0, false},
279 {"^=", 2, opid2('^', '='), ASSOC_RIGHT, 2, 0, false},
280 {"|=", 2, opid2('|', '='), ASSOC_RIGHT, 2, 0, false},
282 {":", 0, opid2(':', '?'), ASSOC_RIGHT, 1, 0, false},
284 {",", 2, opid1(','), ASSOC_LEFT, 0, 0, false}
287 static const oper_info fte_operators[] = {
288 {"(", 0, opid1('('), ASSOC_LEFT, 99, OP_PREFIX, false}, /* paren expression - non function call */
290 {"++", 1, opid3('S', '+', '+'), ASSOC_LEFT, 15, OP_SUFFIX, false},
291 {"--", 1, opid3('S', '-', '-'), ASSOC_LEFT, 15, OP_SUFFIX, false},
292 {".", 2, opid1('.'), ASSOC_LEFT, 15, 0, false},
293 {"(", 0, opid1('('), ASSOC_LEFT, 15, 0, false}, /* function call */
294 {"[", 2, opid1('['), ASSOC_LEFT, 15, 0, false}, /* array subscript */
296 {"!", 1, opid2('!', 'P'), ASSOC_RIGHT, 14, OP_PREFIX, true},
297 {"+", 1, opid2('+', 'P'), ASSOC_RIGHT, 14, OP_PREFIX, false},
298 {"-", 1, opid2('-', 'P'), ASSOC_RIGHT, 14, OP_PREFIX, true},
299 {"++", 1, opid3('+', '+', 'P'), ASSOC_RIGHT, 14, OP_PREFIX, false},
300 {"--", 1, opid3('-', '-', 'P'), ASSOC_RIGHT, 14, OP_PREFIX, false},
302 {"*", 2, opid1('*'), ASSOC_LEFT, 13, 0, true},
303 {"/", 2, opid1('/'), ASSOC_LEFT, 13, 0, true},
304 {"&", 2, opid1('&'), ASSOC_LEFT, 13, 0, true},
305 {"|", 2, opid1('|'), ASSOC_LEFT, 13, 0, true},
307 {"+", 2, opid1('+'), ASSOC_LEFT, 12, 0, true},
308 {"-", 2, opid1('-'), ASSOC_LEFT, 12, 0, true},
310 {"<<", 2, opid2('<', '<'), ASSOC_LEFT, 11, 0, true},
311 {">>", 2, opid2('>', '>'), ASSOC_LEFT, 11, 0, true},
313 {"<", 2, opid1('<'), ASSOC_LEFT, 10, 0, false},
314 {">", 2, opid1('>'), ASSOC_LEFT, 10, 0, false},
315 {"<=", 2, opid2('<', '='), ASSOC_LEFT, 10, 0, false},
316 {">=", 2, opid2('>', '='), ASSOC_LEFT, 10, 0, false},
317 {"==", 2, opid2('=', '='), ASSOC_LEFT, 10, 0, true},
318 {"!=", 2, opid2('!', '='), ASSOC_LEFT, 10, 0, true},
320 {"?", 3, opid2('?', ':'), ASSOC_RIGHT, 9, 0, true},
322 {"=", 2, opid1('='), ASSOC_RIGHT, 8, 0, false},
323 {"+=", 2, opid2('+', '='), ASSOC_RIGHT, 8, 0, false},
324 {"-=", 2, opid2('-', '='), ASSOC_RIGHT, 8, 0, false},
325 {"*=", 2, opid2('*', '='), ASSOC_RIGHT, 8, 0, false},
326 {"/=", 2, opid2('/', '='), ASSOC_RIGHT, 8, 0, false},
327 {"%=", 2, opid2('%', '='), ASSOC_RIGHT, 8, 0, false},
328 {"&=", 2, opid2('&', '='), ASSOC_RIGHT, 8, 0, false},
329 {"|=", 2, opid2('|', '='), ASSOC_RIGHT, 8, 0, false},
330 {"&~=", 2, opid3('&', '~', '='), ASSOC_RIGHT, 8, 0, false},
332 {"&&", 2, opid2('&', '&'), ASSOC_LEFT, 5, 0, true},
333 {"||", 2, opid2('|', '|'), ASSOC_LEFT, 5, 0, true},
335 /* Leave precedence 3 for : with -fcorrect-ternary */
336 {",", 2, opid1(','), ASSOC_LEFT, 2, 0, false},
337 {":", 0, opid2(':', '?'), ASSOC_RIGHT, 1, 0, false}
340 static const oper_info qcc_operators[] = {
341 {"(", 0, opid1('('), ASSOC_LEFT, 99, OP_PREFIX, false}, /* paren expression - non function call */
343 {".", 2, opid1('.'), ASSOC_LEFT, 15, 0, false},
344 {"(", 0, opid1('('), ASSOC_LEFT, 15, 0, false}, /* function call */
345 {"[", 2, opid1('['), ASSOC_LEFT, 15, 0, false}, /* array subscript */
347 {"!", 1, opid2('!', 'P'), ASSOC_RIGHT, 14, OP_PREFIX, true},
348 {"+", 1, opid2('+', 'P'), ASSOC_RIGHT, 14, OP_PREFIX, false},
349 {"-", 1, opid2('-', 'P'), ASSOC_RIGHT, 14, OP_PREFIX, true},
351 {"*", 2, opid1('*'), ASSOC_LEFT, 13, 0, true},
352 {"/", 2, opid1('/'), ASSOC_LEFT, 13, 0, true},
353 {"&", 2, opid1('&'), ASSOC_LEFT, 13, 0, true},
354 {"|", 2, opid1('|'), ASSOC_LEFT, 13, 0, true},
356 {"+", 2, opid1('+'), ASSOC_LEFT, 12, 0, true},
357 {"-", 2, opid1('-'), ASSOC_LEFT, 12, 0, true},
359 {"<", 2, opid1('<'), ASSOC_LEFT, 10, 0, false},
360 {">", 2, opid1('>'), ASSOC_LEFT, 10, 0, false},
361 {"<=", 2, opid2('<', '='), ASSOC_LEFT, 10, 0, false},
362 {">=", 2, opid2('>', '='), ASSOC_LEFT, 10, 0, false},
363 {"==", 2, opid2('=', '='), ASSOC_LEFT, 10, 0, true},
364 {"!=", 2, opid2('!', '='), ASSOC_LEFT, 10, 0, true},
366 {"=", 2, opid1('='), ASSOC_RIGHT, 8, 0, false},
367 {"+=", 2, opid2('+', '='), ASSOC_RIGHT, 8, 0, false},
368 {"-=", 2, opid2('-', '='), ASSOC_RIGHT, 8, 0, false},
369 {"*=", 2, opid2('*', '='), ASSOC_RIGHT, 8, 0, false},
370 {"/=", 2, opid2('/', '='), ASSOC_RIGHT, 8, 0, false},
371 {"%=", 2, opid2('%', '='), ASSOC_RIGHT, 8, 0, false},
372 {"&=", 2, opid2('&', '='), ASSOC_RIGHT, 8, 0, false},
373 {"|=", 2, opid2('|', '='), ASSOC_RIGHT, 8, 0, false},
375 {"&&", 2, opid2('&', '&'), ASSOC_LEFT, 5, 0, true},
376 {"||", 2, opid2('|', '|'), ASSOC_LEFT, 5, 0, true},
378 {",", 2, opid1(','), ASSOC_LEFT, 2, 0, false},
380 extern const oper_info *operators;
381 extern size_t operator_count;