Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2016 Andrew Kelley
3 : : *
4 : : * This file is part of zig, which is MIT licensed.
5 : : * See http://opensource.org/licenses/MIT
6 : : */
7 : :
8 : : #include "c_tokenizer.hpp"
9 : : #include <inttypes.h>
10 : :
11 : : #define WHITESPACE_EXCEPT_N \
12 : : ' ': \
13 : : case '\t': \
14 : : case '\v': \
15 : : case '\f'
16 : :
17 : : #define DIGIT_NON_ZERO \
18 : : '1': \
19 : : case '2': \
20 : : case '3': \
21 : : case '4': \
22 : : case '5': \
23 : : case '6': \
24 : : case '7': \
25 : : case '8': \
26 : : case '9'
27 : :
28 : : #define DIGIT \
29 : : '0': \
30 : : case DIGIT_NON_ZERO
31 : :
32 : : #define ALPHA \
33 : : 'a': \
34 : : case 'b': \
35 : : case 'c': \
36 : : case 'd': \
37 : : case 'e': \
38 : : case 'f': \
39 : : case 'g': \
40 : : case 'h': \
41 : : case 'i': \
42 : : case 'j': \
43 : : case 'k': \
44 : : case 'l': \
45 : : case 'm': \
46 : : case 'n': \
47 : : case 'o': \
48 : : case 'p': \
49 : : case 'q': \
50 : : case 'r': \
51 : : case 's': \
52 : : case 't': \
53 : : case 'u': \
54 : : case 'v': \
55 : : case 'w': \
56 : : case 'x': \
57 : : case 'y': \
58 : : case 'z': \
59 : : case 'A': \
60 : : case 'B': \
61 : : case 'C': \
62 : : case 'D': \
63 : : case 'E': \
64 : : case 'F': \
65 : : case 'G': \
66 : : case 'H': \
67 : : case 'I': \
68 : : case 'J': \
69 : : case 'K': \
70 : : case 'L': \
71 : : case 'M': \
72 : : case 'N': \
73 : : case 'O': \
74 : : case 'P': \
75 : : case 'Q': \
76 : : case 'R': \
77 : : case 'S': \
78 : : case 'T': \
79 : : case 'U': \
80 : : case 'V': \
81 : : case 'W': \
82 : : case 'X': \
83 : : case 'Y': \
84 : : case 'Z'
85 : :
86 : : #define IDENT_START \
87 : : ALPHA: \
88 : : case '_'
89 : :
90 : : #define IDENT \
91 : : IDENT_START: \
92 : : case DIGIT
93 : :
94 : : #define LINE_ENDING \
95 : : '\r': \
96 : : case '\n'
97 : :
98 : 0 : static void begin_token(CTokenize *ctok, CTokId id) {
99 : 0 : assert(ctok->cur_tok == nullptr);
100 : 0 : ctok->tokens.add_one();
101 : 0 : ctok->cur_tok = &ctok->tokens.last();
102 : 0 : ctok->cur_tok->id = id;
103 : :
104 [ # # # # : 0 : switch (id) {
# ]
105 : 0 : case CTokIdStrLit:
106 : 0 : memset(&ctok->cur_tok->data.str_lit, 0, sizeof(Buf));
107 : 0 : buf_resize(&ctok->cur_tok->data.str_lit, 0);
108 : 0 : break;
109 : 0 : case CTokIdSymbol:
110 : 0 : memset(&ctok->cur_tok->data.symbol, 0, sizeof(Buf));
111 : 0 : buf_resize(&ctok->cur_tok->data.symbol, 0);
112 : 0 : break;
113 : 0 : case CTokIdNumLitInt:
114 : 0 : ctok->cur_tok->data.num_lit_int.x = 0;
115 : 0 : ctok->cur_tok->data.num_lit_int.suffix = CNumLitSuffixNone;
116 : 0 : break;
117 : 0 : case CTokIdCharLit:
118 : : case CTokIdNumLitFloat:
119 : : case CTokIdMinus:
120 : : case CTokIdLParen:
121 : : case CTokIdRParen:
122 : : case CTokIdEOF:
123 : : case CTokIdDot:
124 : : case CTokIdAsterisk:
125 : : case CTokIdBang:
126 : : case CTokIdTilde:
127 : : case CTokIdShl:
128 : : case CTokIdLt:
129 : 0 : break;
130 : : }
131 : 0 : }
132 : :
133 : 0 : static void end_token(CTokenize *ctok) {
134 : 0 : ctok->cur_tok = nullptr;
135 : 0 : }
136 : :
137 : 0 : static void mark_error(CTokenize *ctok) {
138 : 0 : ctok->error = true;
139 : 0 : }
140 : :
141 : 0 : static void add_char(CTokenize *ctok, uint8_t c) {
142 : 0 : assert(ctok->cur_tok);
143 [ # # ]: 0 : if (ctok->cur_tok->id == CTokIdCharLit) {
144 : 0 : ctok->cur_tok->data.char_lit = c;
145 : 0 : ctok->state = CTokStateExpectEndQuot;
146 [ # # ]: 0 : } else if (ctok->cur_tok->id == CTokIdStrLit) {
147 : 0 : buf_append_char(&ctok->cur_tok->data.str_lit, c);
148 : 0 : ctok->state = CTokStateString;
149 : : } else {
150 : 0 : zig_unreachable();
151 : : }
152 : 0 : }
153 : :
154 : 0 : static void hex_digit(CTokenize *ctok, uint8_t value) {
155 : : // TODO @mul_with_overflow
156 : 0 : ctok->cur_tok->data.num_lit_int.x *= 16;
157 : : // TODO @add_with_overflow
158 : 0 : ctok->cur_tok->data.num_lit_int.x += value;
159 : :
160 : : static const uint8_t hex_digit[] = "0123456789abcdef";
161 : 0 : buf_append_char(&ctok->buf, hex_digit[value]);
162 : 0 : }
163 : :
164 : 0 : static void end_float(CTokenize *ctok) {
165 : : // TODO detect errors, overflow, and underflow
166 : 0 : double value = strtod(buf_ptr(&ctok->buf), nullptr);
167 : :
168 : 0 : ctok->cur_tok->data.num_lit_float = value;
169 : :
170 : 0 : end_token(ctok);
171 : 0 : ctok->state = CTokStateStart;
172 : :
173 : 0 : }
174 : :
175 : 0 : void tokenize_c_macro(CTokenize *ctok, const uint8_t *c) {
176 : 0 : ctok->tokens.resize(0);
177 : 0 : ctok->state = CTokStateStart;
178 : 0 : ctok->error = false;
179 : 0 : ctok->cur_tok = nullptr;
180 : :
181 : 0 : buf_resize(&ctok->buf, 0);
182 : :
183 [ # # ]: 0 : for (; *c; c += 1) {
184 [ # # # # : 0 : switch (ctok->state) {
# # # # #
# # # # #
# # # # #
# # # # #
# # # ]
185 : 0 : case CTokStateStart:
186 [ # # # # : 0 : switch (*c) {
# # # # #
# # # # #
# # # # ]
187 : 0 : case WHITESPACE_EXCEPT_N:
188 : 0 : break;
189 : 0 : case '\'':
190 : 0 : ctok->state = CTokStateExpectChar;
191 : 0 : begin_token(ctok, CTokIdCharLit);
192 : 0 : break;
193 : 0 : case '\"':
194 : 0 : ctok->state = CTokStateString;
195 : 0 : begin_token(ctok, CTokIdStrLit);
196 : 0 : break;
197 : 0 : case '/':
198 : 0 : ctok->state = CTokStateOpenComment;
199 : 0 : break;
200 : 0 : case '\\':
201 : 0 : ctok->state = CTokStateBackslash;
202 : 0 : break;
203 : 0 : case LINE_ENDING:
204 : 0 : goto found_end_of_macro;
205 : 0 : case IDENT_START:
206 : 0 : ctok->state = CTokStateIdentifier;
207 : 0 : begin_token(ctok, CTokIdSymbol);
208 : 0 : buf_append_char(&ctok->cur_tok->data.symbol, *c);
209 : 0 : break;
210 : 0 : case DIGIT_NON_ZERO:
211 : 0 : ctok->state = CTokStateDecimal;
212 : 0 : begin_token(ctok, CTokIdNumLitInt);
213 : 0 : ctok->cur_tok->data.num_lit_int.x = *c - '0';
214 : 0 : buf_resize(&ctok->buf, 0);
215 : 0 : buf_append_char(&ctok->buf, *c);
216 : 0 : break;
217 : 0 : case '0':
218 : 0 : ctok->state = CTokStateGotZero;
219 : 0 : begin_token(ctok, CTokIdNumLitInt);
220 : 0 : ctok->cur_tok->data.num_lit_int.x = 0;
221 : 0 : buf_resize(&ctok->buf, 0);
222 : 0 : buf_append_char(&ctok->buf, '0');
223 : 0 : break;
224 : 0 : case '.':
225 : 0 : begin_token(ctok, CTokIdDot);
226 : 0 : end_token(ctok);
227 : 0 : break;
228 : 0 : case '<':
229 : 0 : begin_token(ctok, CTokIdLt);
230 : 0 : ctok->state = CTokStateGotLt;
231 : 0 : break;
232 : 0 : case '(':
233 : 0 : begin_token(ctok, CTokIdLParen);
234 : 0 : end_token(ctok);
235 : 0 : break;
236 : 0 : case ')':
237 : 0 : begin_token(ctok, CTokIdRParen);
238 : 0 : end_token(ctok);
239 : 0 : break;
240 : 0 : case '*':
241 : 0 : begin_token(ctok, CTokIdAsterisk);
242 : 0 : end_token(ctok);
243 : 0 : break;
244 : 0 : case '-':
245 : 0 : begin_token(ctok, CTokIdMinus);
246 : 0 : end_token(ctok);
247 : 0 : break;
248 : 0 : case '!':
249 : 0 : begin_token(ctok, CTokIdBang);
250 : 0 : end_token(ctok);
251 : 0 : break;
252 : 0 : case '~':
253 : 0 : begin_token(ctok, CTokIdTilde);
254 : 0 : end_token(ctok);
255 : 0 : break;
256 : 0 : default:
257 : 0 : return mark_error(ctok);
258 : : }
259 : 0 : break;
260 : 0 : case CTokStateGotLt:
261 [ # # ]: 0 : switch (*c) {
262 : 0 : case '<':
263 : 0 : ctok->cur_tok->id = CTokIdShl;
264 : 0 : end_token(ctok);
265 : 0 : ctok->state = CTokStateStart;
266 : 0 : break;
267 : 0 : default:
268 : 0 : end_token(ctok);
269 : 0 : ctok->state = CTokStateStart;
270 : 0 : continue;
271 : : }
272 : 0 : break;
273 : 0 : case CTokStateFloat:
274 [ # # # # : 0 : switch (*c) {
# ]
275 : 0 : case '.':
276 : 0 : break;
277 : 0 : case 'e':
278 : : case 'E':
279 : 0 : buf_append_char(&ctok->buf, 'e');
280 : 0 : ctok->state = CTokStateExpSign;
281 : 0 : break;
282 : 0 : case 'f':
283 : : case 'F':
284 : : case 'l':
285 : : case 'L':
286 : 0 : end_float(ctok);
287 : 0 : break;
288 : 0 : case DIGIT:
289 : 0 : buf_append_char(&ctok->buf, *c);
290 : 0 : break;
291 : 0 : default:
292 : 0 : c -= 1;
293 : 0 : end_float(ctok);
294 : 0 : continue;
295 : : }
296 : 0 : break;
297 : 0 : case CTokStateExpSign:
298 [ # # # ]: 0 : switch (*c) {
299 : 0 : case '+':
300 : : case '-':
301 : 0 : ctok->state = CTokStateFloatExpFirst;
302 : 0 : buf_append_char(&ctok->buf, *c);
303 : 0 : break;
304 : 0 : case DIGIT:
305 : 0 : ctok->state = CTokStateFloatExp;
306 : 0 : buf_append_char(&ctok->buf, *c);
307 : 0 : break;
308 : 0 : default:
309 : 0 : return mark_error(ctok);
310 : : }
311 : 0 : break;
312 : 0 : case CTokStateFloatExpFirst:
313 [ # # ]: 0 : switch (*c) {
314 : 0 : case DIGIT:
315 : 0 : buf_append_char(&ctok->buf, *c);
316 : 0 : ctok->state = CTokStateFloatExp;
317 : 0 : break;
318 : 0 : default:
319 : 0 : return mark_error(ctok);
320 : : }
321 : 0 : break;
322 : 0 : case CTokStateFloatExp:
323 [ # # # ]: 0 : switch (*c) {
324 : 0 : case DIGIT:
325 : 0 : buf_append_char(&ctok->buf, *c);
326 : 0 : break;
327 : 0 : case 'f':
328 : : case 'F':
329 : : case 'l':
330 : : case 'L':
331 : 0 : end_float(ctok);
332 : 0 : break;
333 : 0 : default:
334 : 0 : c -= 1;
335 : 0 : end_float(ctok);
336 : 0 : continue;
337 : : }
338 : 0 : break;
339 : 0 : case CTokStateDecimal:
340 [ # # # # : 0 : switch (*c) {
# # ]
341 : 0 : case DIGIT:
342 : 0 : buf_append_char(&ctok->buf, *c);
343 : :
344 : : // TODO @mul_with_overflow
345 : 0 : ctok->cur_tok->data.num_lit_int.x *= 10;
346 : : // TODO @add_with_overflow
347 : 0 : ctok->cur_tok->data.num_lit_int.x += *c - '0';
348 : 0 : break;
349 : 0 : case '\'':
350 : 0 : break;
351 : 0 : case 'u':
352 : : case 'U':
353 : 0 : ctok->state = CTokStateNumLitIntSuffixU;
354 : 0 : ctok->cur_tok->data.num_lit_int.suffix = CNumLitSuffixU;
355 : 0 : break;
356 : 0 : case 'l':
357 : : case 'L':
358 : 0 : ctok->state = CTokStateNumLitIntSuffixL;
359 : 0 : ctok->cur_tok->data.num_lit_int.suffix = CNumLitSuffixL;
360 : 0 : break;
361 : 0 : case '.':
362 : 0 : buf_append_char(&ctok->buf, '.');
363 : 0 : ctok->cur_tok->id = CTokIdNumLitFloat;
364 : 0 : ctok->state = CTokStateFloat;
365 : 0 : break;
366 : 0 : default:
367 : 0 : c -= 1;
368 : 0 : end_token(ctok);
369 : 0 : ctok->state = CTokStateStart;
370 : 0 : continue;
371 : : }
372 : 0 : break;
373 : 0 : case CTokStateGotZero:
374 [ # # # # ]: 0 : switch (*c) {
375 : 0 : case 'x':
376 : : case 'X':
377 : 0 : ctok->state = CTokStateHex;
378 : 0 : break;
379 : 0 : case '.':
380 : 0 : ctok->state = CTokStateFloat;
381 : 0 : ctok->cur_tok->id = CTokIdNumLitFloat;
382 : 0 : buf_append_char(&ctok->buf, '.');
383 : 0 : break;
384 : 0 : case 'l':
385 : : case 'L':
386 : : case 'u':
387 : : case 'U':
388 : 0 : c -= 1;
389 : 0 : ctok->state = CTokStateDecimal;
390 : 0 : continue;
391 : 0 : default:
392 : 0 : c -= 1;
393 : 0 : ctok->state = CTokStateOctal;
394 : 0 : continue;
395 : : }
396 : 0 : break;
397 : 0 : case CTokStateOctal:
398 [ # # # # ]: 0 : switch (*c) {
399 : 0 : case '0':
400 : : case '1':
401 : : case '2':
402 : : case '3':
403 : : case '4':
404 : : case '5':
405 : : case '6':
406 : : case '7':
407 : : // TODO @mul_with_overflow
408 : 0 : ctok->cur_tok->data.num_lit_int.x *= 8;
409 : : // TODO @add_with_overflow
410 : 0 : ctok->cur_tok->data.num_lit_int.x += *c - '0';
411 : 0 : break;
412 : 0 : case '8':
413 : : case '9':
414 : 0 : return mark_error(ctok);
415 : 0 : case '\'':
416 : 0 : break;
417 : 0 : default:
418 : 0 : c -= 1;
419 : 0 : end_token(ctok);
420 : 0 : ctok->state = CTokStateStart;
421 : 0 : continue;
422 : : }
423 : 0 : break;
424 : 0 : case CTokStateHex:
425 [ # # # # : 0 : switch (*c) {
# # # # #
# # # # #
# # # # #
# ]
426 : 0 : case '0':
427 : 0 : hex_digit(ctok, 0);
428 : 0 : break;
429 : 0 : case '1':
430 : 0 : hex_digit(ctok, 1);
431 : 0 : break;
432 : 0 : case '2':
433 : 0 : hex_digit(ctok, 2);
434 : 0 : break;
435 : 0 : case '3':
436 : 0 : hex_digit(ctok, 3);
437 : 0 : break;
438 : 0 : case '4':
439 : 0 : hex_digit(ctok, 4);
440 : 0 : break;
441 : 0 : case '5':
442 : 0 : hex_digit(ctok, 5);
443 : 0 : break;
444 : 0 : case '6':
445 : 0 : hex_digit(ctok, 6);
446 : 0 : break;
447 : 0 : case '7':
448 : 0 : hex_digit(ctok, 7);
449 : 0 : break;
450 : 0 : case '8':
451 : 0 : hex_digit(ctok, 8);
452 : 0 : break;
453 : 0 : case '9':
454 : 0 : hex_digit(ctok, 9);
455 : 0 : break;
456 : 0 : case 'a':
457 : : case 'A':
458 : 0 : hex_digit(ctok, 10);
459 : 0 : break;
460 : 0 : case 'b':
461 : : case 'B':
462 : 0 : hex_digit(ctok, 11);
463 : 0 : break;
464 : 0 : case 'c':
465 : : case 'C':
466 : 0 : hex_digit(ctok, 12);
467 : 0 : break;
468 : 0 : case 'd':
469 : : case 'D':
470 : 0 : hex_digit(ctok, 13);
471 : 0 : break;
472 : 0 : case 'e':
473 : : case 'E':
474 : 0 : hex_digit(ctok, 14);
475 : 0 : break;
476 : 0 : case 'f':
477 : : case 'F':
478 : 0 : hex_digit(ctok, 15);
479 : 0 : break;
480 : 0 : case 'p':
481 : : case 'P':
482 : 0 : ctok->cur_tok->id = CTokIdNumLitFloat;
483 : 0 : ctok->state = CTokStateExpSign;
484 : 0 : break;
485 : 0 : case 'u':
486 : : case 'U':
487 : : // marks the number literal as unsigned
488 : 0 : ctok->state = CTokStateNumLitIntSuffixU;
489 : 0 : ctok->cur_tok->data.num_lit_int.suffix = CNumLitSuffixU;
490 : 0 : break;
491 : 0 : case 'l':
492 : : case 'L':
493 : : // marks the number literal as long
494 : 0 : ctok->state = CTokStateNumLitIntSuffixL;
495 : 0 : ctok->cur_tok->data.num_lit_int.suffix = CNumLitSuffixL;
496 : 0 : break;
497 : 0 : default:
498 : 0 : c -= 1;
499 : 0 : end_token(ctok);
500 : 0 : ctok->state = CTokStateStart;
501 : 0 : continue;
502 : : }
503 : 0 : break;
504 : 0 : case CTokStateNumLitIntSuffixU:
505 [ # # ]: 0 : switch (*c) {
506 : 0 : case 'l':
507 : : case 'L':
508 : 0 : ctok->cur_tok->data.num_lit_int.suffix = CNumLitSuffixLU;
509 : 0 : ctok->state = CTokStateNumLitIntSuffixUL;
510 : 0 : break;
511 : 0 : default:
512 : 0 : c -= 1;
513 : 0 : end_token(ctok);
514 : 0 : ctok->state = CTokStateStart;
515 : 0 : continue;
516 : : }
517 : 0 : break;
518 : 0 : case CTokStateNumLitIntSuffixL:
519 [ # # # ]: 0 : switch (*c) {
520 : 0 : case 'l':
521 : : case 'L':
522 : 0 : ctok->cur_tok->data.num_lit_int.suffix = CNumLitSuffixLL;
523 : 0 : ctok->state = CTokStateNumLitIntSuffixLL;
524 : 0 : break;
525 : 0 : case 'u':
526 : : case 'U':
527 : 0 : ctok->cur_tok->data.num_lit_int.suffix = CNumLitSuffixLU;
528 : 0 : end_token(ctok);
529 : 0 : ctok->state = CTokStateStart;
530 : 0 : break;
531 : 0 : default:
532 : 0 : c -= 1;
533 : 0 : end_token(ctok);
534 : 0 : ctok->state = CTokStateStart;
535 : 0 : continue;
536 : : }
537 : 0 : break;
538 : 0 : case CTokStateNumLitIntSuffixLL:
539 [ # # ]: 0 : switch (*c) {
540 : 0 : case 'u':
541 : : case 'U':
542 : 0 : ctok->cur_tok->data.num_lit_int.suffix = CNumLitSuffixLLU;
543 : 0 : end_token(ctok);
544 : 0 : ctok->state = CTokStateStart;
545 : 0 : break;
546 : 0 : default:
547 : 0 : c -= 1;
548 : 0 : end_token(ctok);
549 : 0 : ctok->state = CTokStateStart;
550 : 0 : continue;
551 : : }
552 : 0 : break;
553 : 0 : case CTokStateNumLitIntSuffixUL:
554 [ # # ]: 0 : switch (*c) {
555 : 0 : case 'l':
556 : : case 'L':
557 : 0 : ctok->cur_tok->data.num_lit_int.suffix = CNumLitSuffixLLU;
558 : 0 : end_token(ctok);
559 : 0 : ctok->state = CTokStateStart;
560 : 0 : break;
561 : 0 : default:
562 : 0 : c -= 1;
563 : 0 : end_token(ctok);
564 : 0 : ctok->state = CTokStateStart;
565 : 0 : continue;
566 : : }
567 : 0 : break;
568 : 0 : case CTokStateIdentifier:
569 [ # # ]: 0 : switch (*c) {
570 : 0 : case IDENT:
571 : 0 : buf_append_char(&ctok->cur_tok->data.symbol, *c);
572 : 0 : break;
573 : 0 : default:
574 : 0 : c -= 1;
575 : 0 : end_token(ctok);
576 : 0 : ctok->state = CTokStateStart;
577 : 0 : continue;
578 : : }
579 : 0 : break;
580 : 0 : case CTokStateString:
581 [ # # # ]: 0 : switch (*c) {
582 : 0 : case '\\':
583 : 0 : ctok->state = CTokStateCharEscape;
584 : 0 : break;
585 : 0 : case '\"':
586 : 0 : end_token(ctok);
587 : 0 : ctok->state = CTokStateStart;
588 : 0 : break;
589 : 0 : default:
590 : 0 : buf_append_char(&ctok->cur_tok->data.str_lit, *c);
591 : : }
592 : 0 : break;
593 : 0 : case CTokStateExpectChar:
594 [ # # # ]: 0 : switch (*c) {
595 : 0 : case '\\':
596 : 0 : ctok->state = CTokStateCharEscape;
597 : 0 : break;
598 : 0 : case '\'':
599 : 0 : return mark_error(ctok);
600 : 0 : default:
601 : 0 : ctok->cur_tok->data.char_lit = *c;
602 : 0 : ctok->state = CTokStateExpectEndQuot;
603 : : }
604 : 0 : break;
605 : 0 : case CTokStateCharEscape:
606 [ # # # # : 0 : switch (*c) {
# # # # #
# # # # ]
607 : 0 : case '\'':
608 : : case '"':
609 : : case '?':
610 : : case '\\':
611 : 0 : add_char(ctok, *c);
612 : 0 : break;
613 : 0 : case 'a':
614 : 0 : add_char(ctok, '\a');
615 : 0 : break;
616 : 0 : case 'b':
617 : 0 : add_char(ctok, '\b');
618 : 0 : break;
619 : 0 : case 'f':
620 : 0 : add_char(ctok, '\f');
621 : 0 : break;
622 : 0 : case 'n':
623 : 0 : add_char(ctok, '\n');
624 : 0 : break;
625 : 0 : case 'r':
626 : 0 : add_char(ctok, '\r');
627 : 0 : break;
628 : 0 : case 't':
629 : 0 : add_char(ctok, '\t');
630 : 0 : break;
631 : 0 : case 'v':
632 : 0 : add_char(ctok, '\v');
633 : 0 : break;
634 : 0 : case '0':
635 : : case '1':
636 : : case '2':
637 : : case '3':
638 : : case '4':
639 : : case '5':
640 : : case '6':
641 : : case '7':
642 : 0 : ctok->state = CTokStateStrOctal;
643 : 0 : ctok->cur_char = (uint8_t)(*c - '0');
644 : 0 : ctok->octal_index = 1;
645 : 0 : break;
646 : 0 : case 'x':
647 : 0 : ctok->state = CTokStateStrHex;
648 : 0 : ctok->cur_char = 0;
649 : 0 : break;
650 : 0 : case 'u':
651 : 0 : zig_panic("TODO unicode");
652 : : break;
653 : 0 : case 'U':
654 : 0 : zig_panic("TODO Unicode");
655 : : break;
656 : 0 : default:
657 : 0 : return mark_error(ctok);
658 : : }
659 : 0 : break;
660 : 0 : case CTokStateStrHex: {
661 : 0 : uint8_t value = 0;
662 [ # # # # ]: 0 : switch (*c) {
663 : 0 : case '0':
664 : : case '1':
665 : : case '2':
666 : : case '3':
667 : : case '4':
668 : : case '5':
669 : : case '6':
670 : : case '7':
671 : : case '8':
672 : : case '9':
673 : 0 : value = *c - '0';
674 : 0 : break;
675 : 0 : case 'a':
676 : : case 'b':
677 : : case 'c':
678 : : case 'd':
679 : : case 'e':
680 : : case 'f':
681 : 0 : value = (*c - 'a') + 10;
682 : 0 : break;
683 : 0 : case 'A':
684 : : case 'B':
685 : : case 'C':
686 : : case 'D':
687 : : case 'E':
688 : : case 'F':
689 : 0 : value = (*c - 'A') + 10;
690 : 0 : break;
691 : 0 : default:
692 : 0 : c -= 1;
693 : 0 : add_char(ctok, ctok->cur_char);
694 : 0 : continue;
695 : : }
696 : : // TODO @mul_with_overflow
697 [ # # ]: 0 : if (((long)ctok->cur_char) * 16 >= 256) {
698 : 0 : zig_panic("TODO str hex mul overflow");
699 : : }
700 : 0 : ctok->cur_char = (uint8_t)(ctok->cur_char * (uint8_t)16);
701 : : // TODO @add_with_overflow
702 [ # # ]: 0 : if (((long)ctok->cur_char) + (long)(value) >= 256) {
703 : 0 : zig_panic("TODO str hex add overflow");
704 : : }
705 : 0 : ctok->cur_char = (uint8_t)(ctok->cur_char + value);
706 : 0 : break;
707 : : }
708 : 0 : case CTokStateStrOctal:
709 [ # # ]: 0 : switch (*c) {
710 : 0 : case '0':
711 : : case '1':
712 : : case '2':
713 : : case '3':
714 : : case '4':
715 : : case '5':
716 : : case '6':
717 : : case '7':
718 : : // TODO @mul_with_overflow
719 [ # # ]: 0 : if (((long)ctok->cur_char) * 8 >= 256) {
720 : 0 : zig_panic("TODO");
721 : : }
722 : 0 : ctok->cur_char = (uint8_t)(ctok->cur_char * (uint8_t)8);
723 : : // TODO @add_with_overflow
724 [ # # ]: 0 : if (((long)ctok->cur_char) + (long)(*c - '0') >= 256) {
725 : 0 : zig_panic("TODO");
726 : : }
727 : 0 : ctok->cur_char = (uint8_t)(ctok->cur_char + (uint8_t)(*c - '0'));
728 : 0 : ctok->octal_index += 1;
729 [ # # ]: 0 : if (ctok->octal_index == 3) {
730 : 0 : add_char(ctok, ctok->cur_char);
731 : : }
732 : 0 : break;
733 : 0 : default:
734 : 0 : c -= 1;
735 : 0 : add_char(ctok, ctok->cur_char);
736 : 0 : continue;
737 : : }
738 : 0 : break;
739 : 0 : case CTokStateExpectEndQuot:
740 [ # # ]: 0 : switch (*c) {
741 : 0 : case '\'':
742 : 0 : end_token(ctok);
743 : 0 : ctok->state = CTokStateStart;
744 : 0 : break;
745 : 0 : default:
746 : 0 : return mark_error(ctok);
747 : : }
748 : 0 : break;
749 : 0 : case CTokStateOpenComment:
750 [ # # # ]: 0 : switch (*c) {
751 : 0 : case '/':
752 : 0 : ctok->state = CTokStateLineComment;
753 : 0 : break;
754 : 0 : case '*':
755 : 0 : ctok->state = CTokStateComment;
756 : 0 : break;
757 : 0 : default:
758 : 0 : return mark_error(ctok);
759 : : }
760 : 0 : break;
761 : 0 : case CTokStateLineComment:
762 [ # # ]: 0 : if (*c == '\n') {
763 : 0 : ctok->state = CTokStateStart;
764 : 0 : goto found_end_of_macro;
765 : : }
766 : 0 : break;
767 : 0 : case CTokStateComment:
768 [ # # ]: 0 : switch (*c) {
769 : 0 : case '*':
770 : 0 : ctok->state = CTokStateCommentStar;
771 : 0 : break;
772 : 0 : default:
773 : 0 : break;
774 : : }
775 : 0 : break;
776 : 0 : case CTokStateCommentStar:
777 [ # # # ]: 0 : switch (*c) {
778 : 0 : case '/':
779 : 0 : ctok->state = CTokStateStart;
780 : 0 : break;
781 : 0 : case '*':
782 : 0 : break;
783 : 0 : default:
784 : 0 : ctok->state = CTokStateComment;
785 : 0 : break;
786 : : }
787 : 0 : break;
788 : 0 : case CTokStateBackslash:
789 [ # # ]: 0 : switch (*c) {
790 : 0 : case '\n':
791 : 0 : ctok->state = CTokStateStart;
792 : 0 : break;
793 : 0 : default:
794 : 0 : return mark_error(ctok);
795 : : }
796 : 0 : break;
797 : : }
798 : : }
799 : 0 : found_end_of_macro:
800 : :
801 [ # # # # : 0 : switch (ctok->state) {
# ]
802 : 0 : case CTokStateStart:
803 : 0 : break;
804 : 0 : case CTokStateIdentifier:
805 : : case CTokStateDecimal:
806 : : case CTokStateHex:
807 : : case CTokStateOctal:
808 : : case CTokStateGotZero:
809 : : case CTokStateNumLitIntSuffixU:
810 : : case CTokStateNumLitIntSuffixL:
811 : : case CTokStateNumLitIntSuffixUL:
812 : : case CTokStateNumLitIntSuffixLL:
813 : : case CTokStateGotLt:
814 : 0 : end_token(ctok);
815 : 0 : break;
816 : 0 : case CTokStateFloat:
817 : : case CTokStateFloatExp:
818 : 0 : end_float(ctok);
819 : 0 : break;
820 : 0 : case CTokStateExpectChar:
821 : : case CTokStateExpectEndQuot:
822 : : case CTokStateOpenComment:
823 : : case CTokStateLineComment:
824 : : case CTokStateComment:
825 : : case CTokStateCommentStar:
826 : : case CTokStateCharEscape:
827 : : case CTokStateBackslash:
828 : : case CTokStateString:
829 : : case CTokStateExpSign:
830 : : case CTokStateFloatExpFirst:
831 : : case CTokStateStrHex:
832 : : case CTokStateStrOctal:
833 : 0 : return mark_error(ctok);
834 : : }
835 : :
836 : 0 : assert(ctok->cur_tok == nullptr);
837 : :
838 : 0 : begin_token(ctok, CTokIdEOF);
839 : 0 : end_token(ctok);
840 : : }
|