cosmetics
[m6w6/ext-psi] / src / parser.re
1 /*******************************************************************************
2 Copyright (c) 2016, Michael Wallner <mike@php.net>.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7
8 * Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
18 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *******************************************************************************/
25
26 #include "php_psi_stdinc.h"
27 #include <sys/mman.h>
28 #include <assert.h>
29 #include <stdarg.h>
30
31 #include "parser.h"
32
33 /*!max:re2c*/
34 #ifndef YYMAXFILL
35 # define YYMAXFILL 256
36 #endif
37
38 struct psi_parser *psi_parser_init(struct psi_parser *P, psi_error_cb error, unsigned flags)
39 {
40 if (!P) {
41 P = malloc(sizeof(*P));
42 }
43 memset(P, 0, sizeof(*P));
44
45 psi_data_ctor_with_dtors(PSI_DATA(P), error, flags);
46
47 P->preproc = psi_cpp_init(P);
48
49 psi_cpp_load_defaults(P->preproc);
50
51 return P;
52 }
53
54 struct psi_parser_input *psi_parser_open_file(struct psi_parser *P, const char *filename, bool report_errors)
55 {
56 struct stat sb;
57 FILE *fp;
58 struct psi_parser_input *fb;
59
60 if (stat(filename, &sb)) {
61 if (report_errors) {
62 P->error(PSI_DATA(P), NULL, PSI_WARNING,
63 "Could not stat '%s': %s",
64 filename, strerror(errno));
65 }
66 return NULL;
67 }
68
69 if (!(fb = malloc(sizeof(*fb) + strlen(filename) + 1 + sb.st_size + YYMAXFILL))) {
70 if (report_errors) {
71 P->error(PSI_DATA(P), NULL, PSI_WARNING,
72 "Could not allocate %zu bytes for reading '%s': %s",
73 sb.st_size + YYMAXFILL, filename, strerror(errno));
74 }
75 return NULL;
76 }
77
78 if (!(fp = fopen(filename, "r"))) {
79 free(fb);
80 if (report_errors) {
81 P->error(PSI_DATA(P), NULL, PSI_WARNING,
82 "Could not open '%s' for reading: %s",
83 filename, strerror(errno));
84 }
85 return NULL;
86 }
87
88 if (sb.st_size != fread(fb->buffer, 1, sb.st_size, fp)) {
89 free(fb);
90 fclose(fp);
91 if (report_errors) {
92 P->error(PSI_DATA(P), NULL, PSI_WARNING,
93 "Could not read %zu bytes from '%s': %s",
94 sb.st_size + YYMAXFILL, filename, strerror(errno));
95 }
96 return NULL;
97 }
98
99 memset(fb->buffer + sb.st_size, 0, YYMAXFILL);
100 fb->length = sb.st_size;
101 fb->file = &fb->buffer[sb.st_size + YYMAXFILL];
102 memcpy(fb->file, filename, strlen(filename) + 1);
103
104 return fb;
105 }
106
107 struct psi_parser_input *psi_parser_open_string(struct psi_parser *P, const char *string, size_t length)
108 {
109 struct psi_parser_input *sb;
110
111 if (!(sb = malloc(sizeof(*sb) + sizeof("<stdin>") + length + YYMAXFILL))) {
112 P->error(PSI_DATA(P), NULL, PSI_WARNING,
113 "Could not allocate %zu bytes: %s",
114 length + YYMAXFILL, strerror(errno));
115 return NULL;
116 }
117
118 memcpy(sb->buffer, string, length);
119 memset(sb->buffer + length, 0, YYMAXFILL);
120
121 sb->length = length;
122 sb->file = &sb->buffer[length + YYMAXFILL];
123 memcpy(sb->file, "<stdin>", sizeof("<stdin>"));
124
125 return sb;
126 }
127
128 #if 0
129 static void psi_parser_register_constants(struct psi_parser *P)
130 {
131 zend_string *key;
132 zval *val;
133
134 ZEND_HASH_FOREACH_STR_KEY_VAL(&P->cpp.defs, key, val)
135 {
136 struct psi_impl_def_val *iv;
137 struct psi_const_type *ct;
138 struct psi_const *c;
139 const char *ctn;
140 token_t ctt;
141 impl_val tmp;
142 zend_string *str;
143
144 ZVAL_DEREF(val);
145 switch (Z_TYPE_P(val)) {
146 case IS_TRUE:
147 case IS_FALSE:
148 ctt = PSI_T_BOOL;
149 ctn = "bool";
150 tmp.zend.bval = Z_TYPE_P(val) == IS_TRUE;
151 break;
152 case IS_LONG:
153 ctt = PSI_T_INT;
154 ctn = "int";
155 tmp.zend.lval = Z_LVAL_P(val);
156 break;
157 case IS_DOUBLE:
158 ctt = PSI_T_FLOAT;
159 ctn = "float";
160 tmp.dval = Z_DVAL_P(val);
161 break;
162 default:
163 ctt = PSI_T_STRING;
164 ctn = "string";
165 str = zval_get_string(val);
166 tmp.zend.str = zend_string_dup(str, 1);
167 zend_string_release(str);
168 break;
169 }
170
171 iv = psi_impl_def_val_init(ctt, NULL);
172 iv->ival = tmp;
173 ct = psi_const_type_init(ctt, ctn);
174 c = psi_const_init(ct, key->val, iv);
175 if (!P->consts) {
176 P->consts = psi_plist_init((psi_plist_dtor) psi_const_free);
177 }
178 P->consts = psi_plist_add(P->consts, &c);
179 }
180 ZEND_HASH_FOREACH_END();
181 }
182 #endif
183
184 struct psi_plist *psi_parser_preprocess(struct psi_parser *P, struct psi_plist **tokens)
185 {
186 if (psi_cpp_process(P->preproc, tokens)) {
187 return *tokens;
188 }
189 return NULL;
190 }
191
192 bool psi_parser_process(struct psi_parser *P, struct psi_plist *tokens, size_t *processed)
193 {
194 if (psi_plist_count(tokens)) {
195 return 0 == psi_parser_proc_parse(P, tokens, processed);
196 }
197 return true;
198 }
199
200 bool psi_parser_parse(struct psi_parser *P, struct psi_parser_input *I)
201 {
202 struct psi_plist *scanned, *preproc;
203 size_t processed = 0;
204
205 if (!(scanned = psi_parser_scan(P, I))) {
206 return false;
207 }
208
209 if (!(preproc = psi_parser_preprocess(P, &scanned))) {
210 psi_plist_free(scanned);
211 return false;
212 }
213
214 if (!psi_parser_process(P, preproc, &processed)) {
215 psi_plist_free(preproc);
216 return false;
217 }
218
219 psi_plist_free(preproc);
220 return true;
221 }
222
223 void psi_parser_dtor(struct psi_parser *P)
224 {
225 psi_cpp_free(&P->preproc);
226 psi_data_dtor(PSI_DATA(P));
227
228 memset(P, 0, sizeof(*P));
229 }
230
231 void psi_parser_free(struct psi_parser **P)
232 {
233 if (*P) {
234 psi_parser_dtor(*P);
235 free(*P);
236 *P = NULL;
237 }
238 }
239
240 #define NEWLINE() \
241 eol = cur; \
242 ++I->lines
243
244 #define NEWTOKEN(t) \
245 token = psi_token_init(t, tok, cur - tok, tok - eol + 1, I->lines, I->file); \
246 tokens = psi_plist_add(tokens, &token); \
247 if (P->flags & PSI_DEBUG) { \
248 fprintf(stderr, "PSI< "); \
249 psi_token_dump(2, token); \
250 }
251
252 union int_suffix {
253 char s[SIZEOF_UINT32_T];
254 uint32_t i;
255 };
256
257 struct psi_plist *psi_parser_scan(struct psi_parser *P, struct psi_parser_input *I)
258 {
259 struct psi_plist *tokens;
260 struct psi_token *token;
261 const char *tok, *cur, *lim, *mrk, *eol, *ctxmrk;
262 unsigned parens;
263 bool escaped;
264 token_t char_width;
265
266 PSI_DEBUG_PRINT(P, "PSI: scanning %s\n", I->file);
267
268 tok = mrk = eol = cur = I->buffer;
269 lim = I->buffer + I->length;
270 I->lines = 1;
271 tokens = psi_plist_init((psi_plist_dtor) psi_token_free);
272
273 start: ;
274 char_width = 1;
275 ctxmrk = NULL;
276 tok = cur;
277
278 /*!re2c
279
280 re2c:indent:top = 2;
281 re2c:define:YYCTYPE = "unsigned char";
282 re2c:define:YYCURSOR = cur;
283 re2c:define:YYLIMIT = lim;
284 re2c:define:YYMARKER = mrk;
285 re2c:define:YYCTXMARKER = ctxmrk;
286 re2c:define:YYFILL = "if (cur >= lim) goto done;";
287 re2c:yyfill:parameter = 0;
288
289 W = [a-zA-Z0-9_\x80-\xff];
290 SP = [ \t\f];
291 EOL = [\r\n];
292 NAME = [a-zA-Z_\x80-\xff] W*;
293 NSNAME = (NAME)? ("\\" NAME)+;
294 DOLLAR_NAME = '$' W+;
295 CPP_HEADER = "<" [-._/a-zA-Z0-9]+ ">";
296 CPP_ATTRIBUTE = "__attribute__" SP* "((";
297
298 DEC_CONST = [1-9] [0-9]*;
299 OCT_CONST = "0" [0-7]*;
300 HEX_CONST = '0x' [0-9a-fA-F]+;
301 INT_CONST = (DEC_CONST | OCT_CONST | HEX_CONST);
302
303 FLT_HEX_CONST = HEX_CONST ("." [0-9a-fA-F]*)? 'p' [+-]? [0-9]+;
304 FLT_DEC_NUM = "0" | DEC_CONST;
305 FLT_DEC_CONST = (FLT_DEC_NUM ("." [0-9]*)? 'e' [+-]? [0-9]+) | (FLT_DEC_NUM "." [0-9]*) | ("." [0-9]+);
306 FLT_CONST = (FLT_DEC_CONST | FLT_HEX_CONST);
307
308 [+-]? INT_CONST { NEWTOKEN(PSI_T_NUMBER); token->flags = PSI_NUMBER_INT; goto start; }
309 [+-]? INT_CONST / 'u' { NEWTOKEN(PSI_T_NUMBER); token->flags = PSI_NUMBER_INT | PSI_NUMBER_U; cur += 1; goto start; }
310 [+-]? INT_CONST / 'l' { NEWTOKEN(PSI_T_NUMBER); token->flags = PSI_NUMBER_INT | PSI_NUMBER_L; cur += 1; goto start; }
311 [+-]? INT_CONST / ('lu' | 'ul') { NEWTOKEN(PSI_T_NUMBER); token->flags = PSI_NUMBER_INT | PSI_NUMBER_UL; cur += 2; goto start; }
312 [+-]? INT_CONST / ('llu' | 'ull') { NEWTOKEN(PSI_T_NUMBER); token->flags = PSI_NUMBER_INT | PSI_NUMBER_ULL; cur += 3; goto start; }
313
314 [+-]? FLT_CONST { NEWTOKEN(PSI_T_NUMBER); token->flags = PSI_NUMBER_FLT; goto start; }
315 [+-]? FLT_CONST / 'f' { NEWTOKEN(PSI_T_NUMBER); token->flags = PSI_NUMBER_FLT | PSI_NUMBER_F; cur += 1; goto start; }
316 [+-]? FLT_CONST / 'l' { NEWTOKEN(PSI_T_NUMBER); token->flags = PSI_NUMBER_FLT | PSI_NUMBER_L; cur += 1; goto start; }
317 [+-]? FLT_CONST / 'df' { NEWTOKEN(PSI_T_NUMBER); token->flags = PSI_NUMBER_FLT | PSI_NUMBER_DF; cur += 2; goto start; }
318 [+-]? FLT_CONST / 'dd' { NEWTOKEN(PSI_T_NUMBER); token->flags = PSI_NUMBER_FLT | PSI_NUMBER_DD; cur += 2; goto start; }
319 [+-]? FLT_CONST / 'dl' { NEWTOKEN(PSI_T_NUMBER); token->flags = PSI_NUMBER_FLT | PSI_NUMBER_DL; cur += 2; goto start; }
320
321 "'" { escaped = false; tok += 1; goto character; }
322 "\"" { escaped = false; tok += 1; goto string; }
323 "u8" / "\"" { char_width = 1; }
324 "u" / ['"] { char_width = 2; }
325 "U" / ['"] { char_width = 4; }
326 "L" / ['"] { char_width = SIZEOF_WCHAR_T/8; }
327
328 "/*" { goto comment; }
329 "//" { goto comment_sl; }
330
331 "##" { NEWTOKEN(PSI_T_CPP_PASTE); goto start; }
332 "#" { NEWTOKEN(PSI_T_HASH); goto start; }
333 "(" { NEWTOKEN(PSI_T_LPAREN); goto start; }
334 ")" { NEWTOKEN(PSI_T_RPAREN); goto start; }
335 ";" { NEWTOKEN(PSI_T_EOS); goto start; }
336 "," { NEWTOKEN(PSI_T_COMMA); goto start; }
337 ":" { NEWTOKEN(PSI_T_COLON); goto start; }
338 "{" { NEWTOKEN(PSI_T_LBRACE); goto start; }
339 "}" { NEWTOKEN(PSI_T_RBRACE); goto start; }
340 "[" { NEWTOKEN(PSI_T_LBRACKET); goto start; }
341 "]" { NEWTOKEN(PSI_T_RBRACKET); goto start; }
342 "!=" { NEWTOKEN(PSI_T_CMP_NE); goto start; }
343 "==" { NEWTOKEN(PSI_T_CMP_EQ); goto start; }
344 "&&" { NEWTOKEN(PSI_T_AND); goto start; }
345 "||" { NEWTOKEN(PSI_T_OR); goto start; }
346 "=" { NEWTOKEN(PSI_T_EQUALS); goto start; }
347 "*" { NEWTOKEN(PSI_T_ASTERISK); goto start; }
348 "~" { NEWTOKEN(PSI_T_TILDE); goto start; }
349 "!" { NEWTOKEN(PSI_T_NOT); goto start; }
350 "%" { NEWTOKEN(PSI_T_MODULO); goto start; }
351 "&" { NEWTOKEN(PSI_T_AMPERSAND); goto start; }
352 "+" { NEWTOKEN(PSI_T_PLUS); goto start; }
353 "-" { NEWTOKEN(PSI_T_MINUS); goto start; }
354 "/" { NEWTOKEN(PSI_T_SLASH); goto start; }
355 "\\" { NEWTOKEN(PSI_T_BSLASH); goto start; }
356 "|" { NEWTOKEN(PSI_T_PIPE); goto start; }
357 "^" { NEWTOKEN(PSI_T_CARET); goto start; }
358 "<<" { NEWTOKEN(PSI_T_LSHIFT); goto start; }
359 ">>" { NEWTOKEN(PSI_T_RSHIFT); goto start; }
360 "<=" { NEWTOKEN(PSI_T_CMP_LE); goto start; }
361 ">=" { NEWTOKEN(PSI_T_CMP_GE); goto start; }
362 "<" { NEWTOKEN(PSI_T_LCHEVR); goto start; }
363 ">" { NEWTOKEN(PSI_T_RCHEVR); goto start; }
364 "." { NEWTOKEN(PSI_T_PERIOD); goto start; }
365 "..." { NEWTOKEN(PSI_T_ELLIPSIS); goto start; }
366 "?" { NEWTOKEN(PSI_T_IIF); goto start; }
367 "pragma" { NEWTOKEN(PSI_T_PRAGMA); goto start; }
368 "pragma" W+ "once" { NEWTOKEN(PSI_T_PRAGMA_ONCE); goto start; }
369 "__restrict" { NEWTOKEN(PSI_T_CPP_RESTRICT); goto start; }
370 "__extension__" { NEWTOKEN(PSI_T_CPP_EXTENSION); goto start; }
371 "__asm__" { NEWTOKEN(PSI_T_CPP_ASM); goto start; }
372 "line" { NEWTOKEN(PSI_T_LINE); goto start; }
373 "typedef" { NEWTOKEN(PSI_T_TYPEDEF); goto start; }
374 "struct" { NEWTOKEN(PSI_T_STRUCT); goto start; }
375 "union" { NEWTOKEN(PSI_T_UNION); goto start; }
376 "enum" { NEWTOKEN(PSI_T_ENUM); goto start; }
377 "const" { NEWTOKEN(PSI_T_CONST); goto start; }
378 "void" { NEWTOKEN(PSI_T_VOID); goto start; }
379 "bool" { NEWTOKEN(PSI_T_BOOL); goto start; }
380 "char" { NEWTOKEN(PSI_T_CHAR); goto start; }
381 "short" { NEWTOKEN(PSI_T_SHORT); goto start; }
382 "int" { NEWTOKEN(PSI_T_INT); goto start; }
383 "long" { NEWTOKEN(PSI_T_LONG); goto start; }
384 "float" { NEWTOKEN(PSI_T_FLOAT); goto start; }
385 "double" { NEWTOKEN(PSI_T_DOUBLE); goto start; }
386 "int8_t" { NEWTOKEN(PSI_T_INT8); goto start; }
387 "uint8_t" { NEWTOKEN(PSI_T_UINT8); goto start; }
388 "int16_t" { NEWTOKEN(PSI_T_INT16); goto start; }
389 "uint16_t" { NEWTOKEN(PSI_T_UINT16); goto start; }
390 "int32_t" { NEWTOKEN(PSI_T_INT32); goto start; }
391 "uint32_t" { NEWTOKEN(PSI_T_UINT32); goto start; }
392 "int64_t" { NEWTOKEN(PSI_T_INT64); goto start; }
393 "uint64_t" { NEWTOKEN(PSI_T_UINT64); goto start; }
394 "unsigned" { NEWTOKEN(PSI_T_UNSIGNED); goto start; }
395 "signed" { NEWTOKEN(PSI_T_SIGNED); goto start; }
396 'IF' { NEWTOKEN(PSI_T_IF); goto start; }
397 'IFDEF' { NEWTOKEN(PSI_T_IFDEF); goto start; }
398 'IFNDEF' { NEWTOKEN(PSI_T_IFNDEF); goto start; }
399 'ELSE' { NEWTOKEN(PSI_T_ELSE); goto start; }
400 'ELIF' { NEWTOKEN(PSI_T_ELIF); goto start; }
401 'ENDIF' { NEWTOKEN(PSI_T_ENDIF); goto start; }
402 'DEFINE' { NEWTOKEN(PSI_T_DEFINE); goto start; }
403 'DEFINED' { NEWTOKEN(PSI_T_DEFINED); goto start; }
404 'UNDEF' { NEWTOKEN(PSI_T_UNDEF); goto start; }
405 'WARNING' { NEWTOKEN(PSI_T_WARNING); goto start; }
406 'ERROR' { NEWTOKEN(PSI_T_ERROR); goto start; }
407 'INCLUDE' { NEWTOKEN(PSI_T_INCLUDE); goto start; }
408 'INCLUDE_NEXT' { NEWTOKEN(PSI_T_INCLUDE_NEXT); goto start; }
409 'TRUE' { NEWTOKEN(PSI_T_TRUE); goto start; }
410 'FALSE' { NEWTOKEN(PSI_T_FALSE); goto start; }
411 'NULL' { NEWTOKEN(PSI_T_NULL); goto start; }
412 'MIXED' { NEWTOKEN(PSI_T_MIXED); goto start; }
413 'CALLABLE' { NEWTOKEN(PSI_T_CALLABLE); goto start; }
414 'STRING' { NEWTOKEN(PSI_T_STRING); goto start; }
415 'ARRAY' { NEWTOKEN(PSI_T_ARRAY); goto start; }
416 'OBJECT' { NEWTOKEN(PSI_T_OBJECT); goto start; }
417 'CALLBACK' { NEWTOKEN(PSI_T_CALLBACK); goto start; }
418 'STATIC' { NEWTOKEN(PSI_T_STATIC); goto start; }
419 'FUNCTION' { NEWTOKEN(PSI_T_FUNCTION); goto start; }
420 'LIB' { NEWTOKEN(PSI_T_LIB); goto start; }
421 'LET' { NEWTOKEN(PSI_T_LET); goto start; }
422 'SET' { NEWTOKEN(PSI_T_SET); goto start; }
423 'PRE_ASSERT' { NEWTOKEN(PSI_T_PRE_ASSERT); goto start; }
424 'POST_ASSERT' { NEWTOKEN(PSI_T_POST_ASSERT); goto start; }
425 'RETURN' { NEWTOKEN(PSI_T_RETURN); goto start; }
426 'FREE' { NEWTOKEN(PSI_T_FREE); goto start; }
427 'TEMP' { NEWTOKEN(PSI_T_TEMP); goto start; }
428 'STRLEN' { NEWTOKEN(PSI_T_STRLEN); goto start; }
429 'STRVAL' { NEWTOKEN(PSI_T_STRVAL); goto start; }
430 'PATHVAL' { NEWTOKEN(PSI_T_PATHVAL); goto start; }
431 'INTVAL' { NEWTOKEN(PSI_T_INTVAL); goto start; }
432 'FLOATVAL' { NEWTOKEN(PSI_T_FLOATVAL); goto start; }
433 'BOOLVAL' { NEWTOKEN(PSI_T_BOOLVAL); goto start; }
434 'ARRVAL' { NEWTOKEN(PSI_T_ARRVAL); goto start; }
435 'OBJVAL' { NEWTOKEN(PSI_T_OBJVAL); goto start; }
436 'ZVAL' { NEWTOKEN(PSI_T_ZVAL); goto start; }
437 'COUNT' { NEWTOKEN(PSI_T_COUNT); goto start; }
438 'CALLOC' { NEWTOKEN(PSI_T_CALLOC); goto start; }
439 'TO_OBJECT' { NEWTOKEN(PSI_T_TO_OBJECT); goto start; }
440 'TO_ARRAY' { NEWTOKEN(PSI_T_TO_ARRAY); goto start; }
441 'TO_STRING' { NEWTOKEN(PSI_T_TO_STRING); goto start; }
442 'TO_INT' { NEWTOKEN(PSI_T_TO_INT); goto start; }
443 'TO_FLOAT' { NEWTOKEN(PSI_T_TO_FLOAT); goto start; }
444 'TO_BOOL' { NEWTOKEN(PSI_T_TO_BOOL); goto start; }
445 NAME { NEWTOKEN(PSI_T_NAME); goto start; }
446 NSNAME { NEWTOKEN(PSI_T_NSNAME); goto start; }
447 DOLLAR_NAME { NEWTOKEN(PSI_T_DOLLAR_NAME); goto start; }
448 CPP_HEADER { tok += 1; cur -= 1; NEWTOKEN(PSI_T_CPP_HEADER); cur += 1; goto start; }
449 CPP_ATTRIBUTE { parens = 2; goto cpp_attribute; }
450 EOL { NEWTOKEN(PSI_T_EOL); NEWLINE(); goto start; }
451 SP+ { NEWTOKEN(PSI_T_WHITESPACE); goto start; }
452 [^] { NEWTOKEN(-2); goto error; }
453 * { NEWTOKEN(-1); goto error; }
454
455 */
456
457 character: ;
458 /*!re2c
459
460 EOL { NEWLINE(); goto character; }
461 "\\" { escaped = !escaped; goto character; }
462 "'" {
463 if (escaped) {
464 escaped = false;
465 goto character;
466 }
467 cur -= 1;
468 NEWTOKEN(PSI_T_QUOTED_CHAR);
469 cur += 1;
470 token->flags = char_width;
471 goto start;
472 }
473 * { escaped = false; goto character; }
474
475 */
476
477 string: ;
478 /*!re2c
479
480 EOL { NEWLINE(); goto string; }
481 "\\" { escaped = !escaped; goto string; }
482 "\"" {
483 if (escaped) {
484 escaped = false;
485 goto string;
486 }
487 cur -= 1;
488 NEWTOKEN(PSI_T_QUOTED_STRING);
489 cur += 1;
490 token->flags = char_width;
491 goto start;
492 }
493 * { escaped = false; goto string; }
494
495 */
496
497 comment: ;
498 /*!re2c
499
500 EOL { NEWLINE(); goto comment; }
501 "*" "/" { NEWTOKEN(PSI_T_COMMENT); goto start; }
502 * { goto comment; }
503
504 */
505
506 comment_sl: ;
507 /*!re2c
508
509 EOL { NEWTOKEN(PSI_T_COMMENT); NEWLINE(); goto start; }
510 * { goto comment_sl; }
511
512 */
513
514 cpp_attribute: ;
515
516 /*!re2c
517
518 "(" { ++parens; goto cpp_attribute; }
519 ")" { if (parens == 1) { NEWTOKEN(PSI_T_CPP_ATTRIBUTE); goto start; } else { --parens; goto cpp_attribute; } }
520 EOL { NEWLINE(); goto cpp_attribute; }
521 * { goto cpp_attribute; }
522
523 */
524 error: ;
525
526 P->error(PSI_DATA(P), token, PSI_WARNING, "PSI syntax error: unexpected input (%d) '%.*s' at col %tu",
527 token->type, token->size, token->text, tok - eol + 1);
528 psi_plist_free(tokens);
529 return NULL;
530
531 done:
532
533 PSI_DEBUG_PRINT(P, "PSI: EOF cur=%p lim=%p\n", cur, lim);
534
535 return tokens;
536 }