1 /*
2 * Copyright 2012-2013, Jakub Zawadzki <darkjames-ws@darkjames.pl>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7 %option noyywrap
8 %option nounput
9
10 %option noyy_scan_buffer
11 %option noyy_scan_bytes
12 %option noyy_scan_string
13
14 %option yylineno
15 %option never-interactive
16
17 %option case-insensitive
18
19 %{
20 #define YY_DECL static token_type_t yylex(void)
21
22 #include <setjmp.h>
23 #include "ast.h"
24 #include "xmem.h"
25
26 typedef enum {
27 TOKEN_ERROR = -1,
28 TOKEN_EOF = 0,
29
30 TOKEN_INCLUDE,
31 TOKEN_STRUCT,
32 TOKEN_PRIVATE_STRUCT,
33 TOKEN_CONST,
34 TOKEN_PROTOCOL,
35
36 TOKEN_WHILE,
37
38 TOKEN_DYNAMIC_SWITCH,
39 TOKEN_SWITCH,
40 TOKEN_TABLE,
41 TOKEN_CASE,
42 TOKEN_DEFAULT,
43
44 TOKEN_ID,
45 TOKEN_STR,
46 TOKEN_CHAR,
47 TOKEN_DIGIT,
48 TOKEN_FLOAT,
49
50 TOKEN_LPAREN,
51 TOKEN_RPAREN,
52 TOKEN_LBRACKET,
53 TOKEN_RBRACKET,
54 TOKEN_LCURLY,
55 TOKEN_RCURLY,
56
57 TOKEN_ANDAND,
58 TOKEN_OROR,
59
60 TOKEN_EQUAL,
61 TOKEN_NOTEQUAL,
62 TOKEN_NOTEQUAL2,
63
64 TOKEN_LEQUAL,
65 TOKEN_GEQUAL,
66
67 TOKEN_ASSIGN,
68 TOKEN_ASSIGN_PLUS,
69 TOKEN_PLUS,
70 TOKEN_MINUS,
71 TOKEN_MULTIPLY,
72 TOKEN_DIV,
73 TOKEN_LOGIC_OR,
74 TOKEN_OR,
75 TOKEN_LOGIC_AND,
76 TOKEN_AND,
77 TOKEN_NOT,
78 TOKEN_NEG,
79 TOKEN_XOR,
80
81 TOKEN_SHL,
82 TOKEN_SHR,
83
84 TOKEN_PERCENT,
85 TOKEN_DOLLAR,
86 TOKEN_COND,
87 TOKEN_COLON,
88
89 TOKEN_SEMICOLON,
90 TOKEN_DOT,
91 TOKEN_COMMA,
92
93 TOKEN_LESS,
94 TOKEN_GREATER,
95
96 TOKEN_NUMBER,
97 TOKEN_UNSIGNED_NUMBER,
98 TOKEN_DECIMAL,
99 TOKEN_TIME,
100 TOKEN_BYTE_ORDER,
101 TOKEN_DISPLAY_FORMAT,
102 TOKEN_SIZE
103
104 } token_type_t;
105
106 %}
107
108 %x cppcomment
109 %x lch
110 %x lstr
111 %x lstrescape
112
113 DIGIT10 [0-9]
114 DIGIT16 [0-9a-fA-F]
115
116 ID [_a-zA-Z][_a-zA-Z0-9]*
117
118 %%
119
120 include return TOKEN_INCLUDE;
121 struct return TOKEN_STRUCT;
122 _struct return TOKEN_PRIVATE_STRUCT;
123
124 const return TOKEN_CONST;
125 protocol return TOKEN_PROTOCOL;
126
127 while return TOKEN_WHILE;
128
129 DynamicSwitch return TOKEN_DYNAMIC_SWITCH;
130 switch return TOKEN_SWITCH;
131 table return TOKEN_TABLE;
132 case return TOKEN_CASE;
133 default return TOKEN_DEFAULT;
134
135 Number return TOKEN_NUMBER;
136 UnsignedNumber return TOKEN_UNSIGNED_NUMBER;
137 Decimal return TOKEN_DECIMAL;
138 Time return TOKEN_TIME;
139 ByteOrder return TOKEN_BYTE_ORDER;
140 DisplayFormat return TOKEN_DISPLAY_FORMAT;
141 Size return TOKEN_SIZE;
142
143 "(" return TOKEN_LPAREN;
144 ")" return TOKEN_RPAREN;
145 "[" return TOKEN_LBRACKET;
146 "]" return TOKEN_RBRACKET;
147 "{" return TOKEN_LCURLY;
148 "}" return TOKEN_RCURLY;
149
150 and return TOKEN_ANDAND;
151 or return TOKEN_OROR;
152
153 "==" return TOKEN_EQUAL;
154 "!=" return TOKEN_NOTEQUAL;
155 "<>" return TOKEN_NOTEQUAL2;
156
157 ">=" return TOKEN_GEQUAL;
158 "<=" return TOKEN_LEQUAL;
159
160 "+=" return TOKEN_ASSIGN_PLUS;
161 "=" return TOKEN_ASSIGN;
162 "+" return TOKEN_PLUS;
163 "-" return TOKEN_MINUS;
164 "*" return TOKEN_MULTIPLY;
165 "/" return TOKEN_DIV;
166 "||" return TOKEN_LOGIC_OR;
167 "|" return TOKEN_OR;
168 "&&" return TOKEN_LOGIC_AND;
169 "&" return TOKEN_AND;
170 "!" return TOKEN_NOT;
171 "~" return TOKEN_NEG;
172 "^" return TOKEN_XOR;
173 "<<" return TOKEN_SHL;
174 ">>" return TOKEN_SHR;
175 "%" return TOKEN_PERCENT;
176 "$" return TOKEN_DOLLAR;
177 "?" return TOKEN_COND;
178
179 ";" return TOKEN_SEMICOLON;
180 "." return TOKEN_DOT;
181 "," return TOKEN_COMMA;
182 ":" return TOKEN_COLON;
183
184 "<" return TOKEN_LESS;
185 ">" return TOKEN_GREATER;
186
187 "'" yymore(); BEGIN(lch);
188 <lch>{
189 "'" BEGIN(INITIAL); return TOKEN_CHAR;
190 "\n" return TOKEN_ERROR;
191 . yymore();
192 }
193
194 "\"" yymore(); BEGIN(lstr);
195 <lstr>{
196 "\"" BEGIN(INITIAL); return TOKEN_STR;
197 "\\" yymore(); BEGIN(lstrescape);
198 "\n" return TOKEN_ERROR;
199 . yymore();
200 }
201
202 <lstrescape>{
203 "\n" return TOKEN_ERROR;
204 . yymore(); BEGIN(lstr);
205 }
206
207 "//" BEGIN(cppcomment);
208 <cppcomment>{
209 "\n" BEGIN(INITIAL);
210 . ;
211 }
212
213 "/*" {
214 int nested = 1;
215 int ch, last_ch;
216
217 last_ch = '*';
218
219 /* XXX, can comments be nested? (can't be determinated by current example file set) */
220
221 do {
222 ch = input();
223
224 if (last_ch == '*' && ch == '/')
225 nested--;
226
227 if (last_ch == '/' && ch == '*')
228 nested++;
229
230 if (ch == EOF)
231 return TOKEN_ERROR;
232
233 last_ch = ch;
234
235 } while(nested);
236 }
237
238 {ID} return TOKEN_ID;
239 {DIGIT10}+"."{DIGIT10}* return TOKEN_FLOAT;
240 {DIGIT10}+ return TOKEN_DIGIT;
241 "0x"{DIGIT16}+ return TOKEN_DIGIT;
242
243 [[:space:]] ;
244
245 . return TOKEN_ERROR;
246
247 %%
248
249 static const char *yyfilename;
250 static int token;
251
token_name(token_type_t tok)252 static const char *token_name(token_type_t tok) {
253 static char buf[64];
254
255 switch (tok) {
256 case TOKEN_EOF: return "<<eof>>";
257 case TOKEN_ERROR: return "<<error>>";
258
259 case TOKEN_ID:
260 return "<ID>";
261 case TOKEN_STR:
262 return "<STR>";
263 case TOKEN_CHAR:
264 return "<CHAR>";
265 case TOKEN_DIGIT:
266 return "<DIGIT>";
267 case TOKEN_FLOAT:
268 return "<FLOAT>";
269
270 case TOKEN_STRUCT:
271 return "struct";
272 case TOKEN_PRIVATE_STRUCT:
273 return "_struct";
274 case TOKEN_CONST:
275 return "const";
276 case TOKEN_WHILE:
277 return "while";
278 case TOKEN_SWITCH:
279 return "switch";
280 case TOKEN_DYNAMIC_SWITCH:
281 return "dynamic switch";
282 case TOKEN_CASE:
283 return "case";
284
285 /* ... */
286 default:
287 ;
288 }
289
290 snprintf(buf, sizeof(buf), "<token #%d>", tok);
291 return buf;
292 }
293
294 static jmp_buf parser_exception;
295
xfail(void)296 static void xfail(void) { longjmp(parser_exception, 1); }
297
next_token(void)298 static void next_token(void) { token = yylex(); }
299
is_token(token_type_t tok)300 static inline int is_token(token_type_t tok) { return (token == tok); }
301
_strange(int line)302 static void _strange(int line) {
303 fprintf(stdout, "?!?!? %s:%d got: %d (%s) @%s:%d\n", __FILE__, line, token, yytext, yyfilename, yylineno);
304 }
305 #define strange() _strange(__LINE__)
306
_nomatch(int line)307 static void _nomatch(int line) {
308 fprintf(stdout, "!!!! %s:%d got: %d (%s) @%s:%d\n", __FILE__, line, token, yytext, yyfilename, yylineno);
309 xfail();
310 }
311 #define nomatch() _nomatch(__LINE__)
312
_accept(token_type_t tok,int line)313 static void _accept(token_type_t tok, int line) {
314 if (tok != token) {
315 fprintf(stdout, "%s:%d got: %d (%s) expected %s @%s:%d\n", __FILE__, line, token, yytext, token_name(tok), yyfilename, yylineno);
316 xfail();
317 }
318 next_token();
319 }
320 #define accept(tok) _accept(tok, __LINE__)
321
is_id(void)322 static int is_id(void) {
323 /* Some NPL files use keyword as ID (sucks...) */
324 return
325 is_token(TOKEN_PROTOCOL) ||
326 is_token(TOKEN_SIZE) ||
327 is_token(TOKEN_DEFAULT) ||
328 is_token(TOKEN_NUMBER) ||
329 is_token(TOKEN_DECIMAL) ||
330 is_token(TOKEN_TIME) ||
331 is_token(TOKEN_BYTE_ORDER) ||
332 is_token(TOKEN_OROR) || is_token(TOKEN_ANDAND) ||
333 is_token(TOKEN_STRUCT) || is_token(TOKEN_TABLE) ||
334 is_token(TOKEN_ID);
335 }
336
_accept_id(int line)337 static char *_accept_id(int line) {
338 char *id;
339
340 if (!is_id()) {
341 fprintf(stdout, "%s:%d got: %d (%s) expected %s @%s:%d\n", __FILE__, line, token, yytext, token_name(TOKEN_ID), yyfilename, yylineno);
342 xfail();
343 }
344
345 id = xstrdup(yytext);
346 next_token();
347
348 return id;
349 }
350
351 #define accept_id() _accept_id(__LINE__)
352
_accept_int(int line)353 static unsigned int _accept_int(int line) {
354 unsigned int num;
355
356 if (token != TOKEN_DIGIT) {
357 fprintf(stdout, "%s:%d got: %d (%s) expected %s @%s:%d\n", __FILE__, line, token, yytext, token_name(TOKEN_DIGIT), yyfilename, yylineno);
358 xfail();
359 }
360
361 if (yytext[0] == '0' && yytext[1] == 'x')
362 num = strtol(yytext + 2, NULL, 16);
363 else
364 num = strtol(yytext, NULL, 10);
365
366 next_token();
367
368 return num;
369 }
370
371 #define accept_int() _accept_int(__LINE__)
372
373
_accept_str(int line)374 static char *_accept_str(int line) {
375 size_t len;
376 char *str;
377
378 if (token != TOKEN_STR) {
379 fprintf(stdout, "%s:%d got: %d (%s) expected %s @%s:%d\n", __FILE__, line, token, yytext, token_name(TOKEN_STR), yyfilename, yylineno);
380 xfail();
381 }
382
383 len = strlen(yytext);
384
385 if (len < 2 || yytext[0] != '"' || yytext[len-1] != '"')
386 xfail();
387 #if 0
388 char *ptr;
389 size_t i;
390
391 ptr = str = xmalloc(len-2+1);
392 for (i = 1; i < len-1; i++) {
393 if (yytext[i] == '\\') {
394 i++;
395
396 if (yytext[i] == '0' && yytext[i+1] == 'x') {
397 i += 2;
398
399 // XXX
400 *ptr++ = yytext[i];
401 } else
402 switch (yytext[i]) {
403 case '0':
404 *ptr++ = '\0';
405 break;
406 case '\\':
407 *ptr++ = '\\';
408 break;
409 case 'r':
410 *ptr++ = '\r';
411 break;
412 case 'n':
413 *ptr++ = '\n';
414 break;
415 case 't':
416 *ptr++ = '\t';
417 break;
418
419 case '"':
420 *ptr++ = '"';
421 break;
422 case '\'':
423 *ptr++ = '\'';
424 break;
425
426 default:
427 fprintf(stdout, "unrecog: %c @ %d\n", yytext[i], yylineno);
428 *ptr++ = yytext[i];
429 }
430
431 } else
432 *ptr++ = yytext[i];
433 }
434
435 *ptr = '\0';
436 #else
437 len -= 2;
438 /* escaping is done almost like in C so don't unescape (cause it'd require escaping later...) */
439 str = xmalloc(len + 1);
440 memcpy(str, yytext + 1, len);
441 str[len] = '\0';
442 #endif
443
444 next_token();
445
446 return str;
447 }
448 #define accept_str() _accept_str(__LINE__)
449
is_token_accept(token_type_t tok)450 static int is_token_accept(token_type_t tok) {
451 if (is_token(tok)) {
452 next_token();
453 return 1;
454 }
455 return 0;
456 }
457
is_params(void)458 static int is_params(void) { return is_token(TOKEN_LPAREN); }
459
460 static void
parse_params(npl_params_t * p)461 parse_params(npl_params_t *p)
462 {
463 int i = 0;
464
465 accept(TOKEN_LPAREN);
466 do {
467 if (i == NPL_PARAMS_MAX) {
468 fprintf(stdout, "i == NPL_PARAMS_MAX");
469 xfail();
470 }
471
472 p->args[i++] = accept_id();
473
474 } while (is_token_accept(TOKEN_COMMA));
475 accept(TOKEN_RPAREN);
476
477 p->count = i;
478 }
479
480 static void parse_expression(npl_expression_t *expr);
481 static npl_expression_t *xparse_expression(void);
482
483 static void
parse_primary(npl_expression_t * expr)484 parse_primary(npl_expression_t *expr)
485 {
486 if (is_id()) {
487 expr->type = EXPRESSION_ID;
488 expr->id.id = accept_id();
489 return;
490 }
491
492 if (is_token(TOKEN_DIGIT)) {
493 expr->type = EXPRESSION_INT;
494 expr->num.digit = accept_int();
495 return;
496 }
497
498 if (is_token(TOKEN_FLOAT)) {
499 // XXX ast
500 accept(TOKEN_FLOAT);
501 expr->type = -1;
502 return;
503 }
504
505 if (is_token(TOKEN_CHAR)) {
506 // XXX ast
507 accept(TOKEN_CHAR);
508 expr->type = -2;
509 return;
510 }
511
512 if (is_token(TOKEN_STR)) {
513 expr->type = EXPRESSION_STR;
514 expr->str.str = accept_str();
515 return;
516 }
517
518 if (is_token_accept(TOKEN_LPAREN)) {
519 parse_expression(expr);
520 accept(TOKEN_RPAREN);
521 return;
522 }
523
524 nomatch();
525 }
526
527 /* ExpressionList = Expression, { ",", Expression } ; */
528 static void
parse_expression_list(npl_expression_list_t ** ptr)529 parse_expression_list(npl_expression_list_t **ptr)
530 {
531 do {
532 npl_expression_list_t *cur = xnew(npl_expression_list_t);
533
534 *ptr = cur;
535 ptr = &(cur->next);
536 cur->expr = xparse_expression();
537
538 } while (is_token_accept(TOKEN_COMMA));
539
540 *ptr = NULL;
541 }
542
543 static void
parse_expression1(npl_expression_t * expr)544 parse_expression1(npl_expression_t *expr)
545 {
546 parse_primary(expr);
547
548 do {
549 if (is_token_accept(TOKEN_LPAREN)) { /* foo() */
550 npl_expression_t *fun = xdup(npl_expression_t, expr);
551 npl_expression_list_t *args = NULL;
552
553 if (!is_token(TOKEN_RPAREN))
554 parse_expression_list(&args);
555 accept(TOKEN_RPAREN);
556
557 expr->type = EXPRESSION_CALL;
558 expr->call.fn = fun;
559 expr->call.args = args;
560
561 } else if (is_token_accept(TOKEN_DOLLAR)) { /* arr$[field1, field2, ...] */
562 npl_expression_t *base = xdup(npl_expression_t, expr);
563 npl_expression_list_t *indexes;
564
565 accept(TOKEN_LBRACKET);
566 parse_expression_list(&indexes);
567 accept(TOKEN_RBRACKET);
568
569 expr->type = EXPRESSION_MULTI_INDEX;
570 expr->aarr.base = base;
571 expr->aarr.indexes = indexes;
572
573 } else if (is_token_accept(TOKEN_LBRACKET)) { /* arr[10] */
574 npl_expression_t *base = xdup(npl_expression_t, expr);
575 npl_expression_t *idx;
576
577 idx = xparse_expression();
578 accept(TOKEN_RBRACKET);
579
580 expr->type = EXPRESSION_INDEX;
581 expr->arr.base = base;
582 expr->arr.index = idx;
583
584 } else if (is_token_accept(TOKEN_DOT)) {
585 npl_expression_t *base = xdup(npl_expression_t, expr);
586 char *field;
587
588 field = accept_id();
589
590 expr->type = EXPRESSION_FIELD;
591 expr->fld.base = base;
592 expr->fld.field = field;
593
594 } else
595 break;
596
597 } while (1);
598 }
599
600 static void
parse_expression2(npl_expression_t * expr)601 parse_expression2(npl_expression_t *expr)
602 {
603 npl_op1_t op;
604
605 do {
606 op =
607 (is_token_accept(TOKEN_MINUS)) ? OP1_MINUS :
608 (is_token_accept(TOKEN_NOT)) ? OP1_NOT :
609 (is_token_accept(TOKEN_NEG)) ? OP1_NEG :
610 OP1_INVALID;
611
612 if (op != OP1_INVALID) {
613 expr->type = EXPRESSION_UNARY;
614 expr->u.operator = op;
615
616 expr = expr->u.operand = xnew(npl_expression_t);
617 }
618 } while (op != OP1_INVALID);
619
620 parse_expression1(expr);
621 }
622
623 static void
parse_expression3(npl_expression_t * expr)624 parse_expression3(npl_expression_t *expr)
625 {
626 npl_op2_t op;
627
628 parse_expression2(expr);
629 again:
630 op =
631 (is_token_accept(TOKEN_MULTIPLY)) ? OP2_MULTIPLY :
632 (is_token_accept(TOKEN_DIV)) ? OP2_DIV :
633 (is_token_accept(TOKEN_PERCENT)) ? OP2_MOD :
634 OP2_INVALID;
635
636 if (op != OP2_INVALID) {
637 npl_expression_t *operand = xdup(npl_expression_t, expr);
638 npl_expression_t *e;
639
640 expr->b.operand2 = e = xnew(npl_expression_t);
641 parse_expression3(e);
642
643 expr->b.operator = op;
644 expr->b.operand1 = operand;
645 expr->type = EXPRESSION_BINARY;
646 goto again;
647 }
648 }
649
650 static void
parse_expression4(npl_expression_t * expr)651 parse_expression4(npl_expression_t *expr)
652 {
653 npl_op2_t op;
654
655 parse_expression3(expr);
656 again:
657 op =
658 (is_token_accept(TOKEN_PLUS)) ? OP2_PLUS :
659 (is_token_accept(TOKEN_MINUS)) ? OP2_MINUS :
660 OP2_INVALID;
661
662 if (op != OP2_INVALID) {
663 npl_expression_t *operand = xdup(npl_expression_t, expr);
664 npl_expression_t *e;
665
666 expr->b.operand2 = e = xnew(npl_expression_t);
667 parse_expression4(e);
668
669 expr->b.operator = op;
670 expr->b.operand1 = operand;
671 expr->type = EXPRESSION_BINARY;
672 goto again;
673 }
674 }
675
676 static void
parse_expression5(npl_expression_t * expr)677 parse_expression5(npl_expression_t *expr)
678 {
679 npl_op2_t op;
680
681 parse_expression4(expr);
682 again:
683 op =
684 (is_token_accept(TOKEN_SHL)) ? OP2_SHL :
685 (is_token_accept(TOKEN_SHR)) ? OP2_SHR :
686 OP2_INVALID;
687
688 if (op != OP2_INVALID) {
689 npl_expression_t *operand = xdup(npl_expression_t, expr);
690 npl_expression_t *e;
691
692 expr->b.operand2 = e = xnew(npl_expression_t);
693 parse_expression5(e);
694
695 expr->b.operator = op;
696 expr->b.operand1 = operand;
697 expr->type = EXPRESSION_BINARY;
698 goto again;
699 }
700 }
701
702 static void
parse_expression6(npl_expression_t * expr)703 parse_expression6(npl_expression_t *expr)
704 {
705 npl_op2_t op;
706
707 parse_expression5(expr);
708 again:
709 op =
710 (is_token_accept(TOKEN_LESS)) ? OP2_LESS :
711 (is_token_accept(TOKEN_GREATER)) ? OP2_GREATER :
712 (is_token_accept(TOKEN_LEQUAL)) ? OP2_LEQUAL :
713 (is_token_accept(TOKEN_GEQUAL)) ? OP2_GEQUAL :
714 OP2_INVALID;
715
716 if (op != OP2_INVALID) {
717 npl_expression_t *operand = xdup(npl_expression_t, expr);
718 npl_expression_t *e;
719
720 expr->b.operand2 = e = xnew(npl_expression_t);
721 parse_expression6(e);
722
723 expr->b.operator = op;
724 expr->b.operand1 = operand;
725 expr->type = EXPRESSION_BINARY;
726 goto again;
727 }
728 }
729
730 static void
parse_expression7(npl_expression_t * expr)731 parse_expression7(npl_expression_t *expr)
732 {
733 npl_op2_t op;
734
735 parse_expression6(expr);
736 again:
737 op =
738 (is_token_accept(TOKEN_EQUAL)) ? OP2_EQUAL :
739 (is_token_accept(TOKEN_NOTEQUAL)) ? OP2_NOTEQUAL :
740 (is_token_accept(TOKEN_NOTEQUAL2)) ? OP2_NOTEQUAL :
741 OP2_INVALID;
742
743 if (op != OP2_INVALID) {
744 npl_expression_t *operand = xdup(npl_expression_t, expr);
745 npl_expression_t *e;
746
747 expr->b.operand2 = e = xnew(npl_expression_t);
748 parse_expression7(e);
749
750 expr->b.operator = op;
751 expr->b.operand1 = operand;
752 expr->type = EXPRESSION_BINARY;
753 goto again;
754 }
755 }
756
757 static void
parse_expression8(npl_expression_t * expr)758 parse_expression8(npl_expression_t *expr)
759 {
760 parse_expression7(expr);
761 again:
762 if (is_token_accept(TOKEN_AND)) {
763 npl_expression_t *operand = xdup(npl_expression_t, expr);
764 npl_expression_t *e;
765
766 expr->b.operand2 = e = xnew(npl_expression_t);
767 parse_expression8(e);
768
769 expr->b.operator = OP2_AND;
770 expr->b.operand1 = operand;
771 expr->type = EXPRESSION_BINARY;
772 goto again;
773 }
774 }
775
776 static void
parse_expression9(npl_expression_t * expr)777 parse_expression9(npl_expression_t *expr)
778 {
779 parse_expression8(expr);
780 again:
781 if (is_token_accept(TOKEN_XOR)) {
782 npl_expression_t *operand = xdup(npl_expression_t, expr);
783 npl_expression_t *e;
784
785 expr->b.operand2 = e = xnew(npl_expression_t);
786 parse_expression9(e);
787
788 expr->b.operator = OP2_XOR;
789 expr->b.operand1 = operand;
790 expr->type = EXPRESSION_BINARY;
791 goto again;
792 }
793 }
794
795 static void
parse_expression10(npl_expression_t * expr)796 parse_expression10(npl_expression_t *expr)
797 {
798 parse_expression9(expr);
799 again:
800 if (is_token_accept(TOKEN_OR)) {
801 npl_expression_t *operand = xdup(npl_expression_t, expr);
802 npl_expression_t *e;
803
804 expr->b.operand2 = e = xnew(npl_expression_t);
805 parse_expression10(e);
806
807 expr->b.operator = OP2_OR;
808 expr->b.operand1 = operand;
809 expr->type = EXPRESSION_BINARY;
810 goto again;
811 }
812 }
813
814 static void
parse_expression11(npl_expression_t * expr)815 parse_expression11(npl_expression_t *expr)
816 {
817 npl_op2_t op;
818
819 parse_expression10(expr);
820 again:
821 op =
822 (is_token_accept(TOKEN_LOGIC_AND)) ? OP2_LOGIC_AND :
823 (is_token_accept(TOKEN_ANDAND)) ? OP2_LOGIC_AND :
824 OP2_INVALID;
825
826 if (op != OP2_INVALID) {
827 npl_expression_t *operand = xdup(npl_expression_t, expr);
828 npl_expression_t *e;
829
830 expr->b.operand2 = e = xnew(npl_expression_t);
831 parse_expression11(e);
832
833 expr->b.operator = op;
834 expr->b.operand1 = operand;
835 expr->type = EXPRESSION_BINARY;
836 goto again;
837 }
838 }
839
840 static void
parse_expression12(npl_expression_t * expr)841 parse_expression12(npl_expression_t *expr)
842 {
843 npl_op2_t op;
844
845 parse_expression11(expr);
846 again:
847 op =
848 (is_token_accept(TOKEN_LOGIC_OR)) ? OP2_LOGIC_OR :
849 (is_token_accept(TOKEN_OROR)) ? OP2_LOGIC_OR :
850 OP2_INVALID;
851
852 if (op != OP2_INVALID) {
853 npl_expression_t *operand = xdup(npl_expression_t, expr);
854 npl_expression_t *e;
855
856 expr->b.operand2 = e = xnew(npl_expression_t);
857 parse_expression12(e);
858
859 expr->b.operator = op;
860 expr->b.operand1 = operand;
861 expr->type = EXPRESSION_BINARY;
862 goto again;
863 }
864 }
865
866 static void
parse_expression13(npl_expression_t * expr)867 parse_expression13(npl_expression_t *expr)
868 {
869 parse_expression12(expr);
870
871 if (is_token_accept(TOKEN_COND)) {
872 npl_expression_t *operand = xdup(npl_expression_t, expr);
873 npl_expression_t *e;
874
875 expr->c.test_expr = operand;
876
877 e = xnew(npl_expression_t);
878 parse_expression(e);
879 expr->c.true_expr = e;
880 accept(TOKEN_COLON);
881
882 e = xnew(npl_expression_t);
883 parse_expression13(e);
884 expr->c.false_expr = e;
885
886 expr->type = EXPRESSION_COND;
887 }
888 }
889
890 static npl_expression_t *
xparse_expression(void)891 xparse_expression(void)
892 {
893 npl_expression_t *expr = xnew(npl_expression_t);
894
895 parse_expression(expr);
896 return expr;
897 }
898
899 static void
parse_expression(npl_expression_t * expr)900 parse_expression(npl_expression_t *expr)
901 {
902 npl_op2_t op;
903
904 parse_expression13(expr);
905
906 op =
907 (is_token_accept(TOKEN_ASSIGN)) ? OP2_ASSIGN :
908 (is_token_accept(TOKEN_ASSIGN_PLUS)) ? OP2_ASSIGN_PLUS :
909 OP2_INVALID;
910
911 if (op != OP2_INVALID) {
912 npl_expression_t *operand = xdup(npl_expression_t, expr);
913
914 expr->b.operand2 = xparse_expression();
915
916 expr->b.operator = op;
917 expr->b.operand1 = operand;
918 expr->type = EXPRESSION_BINARY;
919 }
920 }
921
is_attribute(void)922 static int is_attribute(void) { return is_token(TOKEN_LBRACKET); }
923
924 static npl_attribute_list_t **
pparse_attributes(npl_attribute_list_t ** ptr)925 pparse_attributes(npl_attribute_list_t **ptr)
926 {
927 accept(TOKEN_LBRACKET);
928
929 do {
930 npl_attribute_list_t *cur = xnew(npl_attribute_list_t);
931
932 *ptr = cur;
933 ptr = &(cur->next);
934 cur->expr = xparse_expression();
935
936 if (is_token_accept(TOKEN_SEMICOLON))
937 { }
938 else if (is_token_accept(TOKEN_COMMA))
939 { }
940 }
941 while (!is_token(TOKEN_RBRACKET));
942 // while (is_token_accept(TOKEN_COMMA));
943
944 accept(TOKEN_RBRACKET);
945 return ptr;
946 }
947
948 static void
parse_all_attributes(npl_attribute_list_t ** attr_ptr)949 parse_all_attributes(npl_attribute_list_t **attr_ptr)
950 {
951 while (is_attribute())
952 attr_ptr = pparse_attributes(attr_ptr);
953 *attr_ptr = NULL;
954 }
955
956 static void parse_statement(npl_statement_t *st);
957
958 static npl_statement_t *
xparse_statement(void)959 xparse_statement(void)
960 {
961 npl_statement_t *st = xnew(npl_statement_t);
962
963 parse_statement(st);
964 return st;
965 }
966
967 static void
parse_switch_body(npl_switch_t * sw)968 parse_switch_body(npl_switch_t *sw)
969 {
970 struct npl_switch_case **ptr = &sw->cases;
971
972 while (is_token(TOKEN_CASE)) {
973 struct npl_switch_case *cur = xnew(struct npl_switch_case);
974
975 *ptr = cur;
976
977 ptr = &(cur->next);
978
979 accept(TOKEN_CASE);
980 parse_expression(&cur->e);
981 accept(TOKEN_COLON);
982
983 if (!is_token(TOKEN_CASE) && !is_token(TOKEN_DEFAULT)) {
984 cur->st = xparse_statement();
985 is_token_accept(TOKEN_SEMICOLON);
986 }
987 }
988 *ptr = NULL;
989
990 if (is_token_accept(TOKEN_DEFAULT)) {
991 accept(TOKEN_COLON);
992 sw->default_st = xparse_statement();
993 }
994 }
995
996 static void
parse_switch(npl_switch_t * sw)997 parse_switch(npl_switch_t *sw)
998 {
999 accept(TOKEN_SWITCH);
1000
1001 if (is_token_accept(TOKEN_LPAREN)) {
1002 sw->switch_expr = xparse_expression();
1003 accept(TOKEN_RPAREN);
1004 }
1005
1006 accept(TOKEN_LCURLY);
1007 parse_switch_body(sw);
1008 accept(TOKEN_RCURLY);
1009 is_token_accept(TOKEN_SEMICOLON);
1010 }
1011
1012 static void
parse_dynamic_switch(npl_switch_t * sw)1013 parse_dynamic_switch(npl_switch_t *sw)
1014 {
1015 accept(TOKEN_DYNAMIC_SWITCH);
1016
1017 sw->switch_expr = xparse_expression();
1018
1019 accept(TOKEN_LCURLY);
1020 parse_switch_body(sw);
1021 accept(TOKEN_RCURLY);
1022 is_token_accept(TOKEN_SEMICOLON);
1023 }
1024
is_statement(void)1025 static int is_statement(void) {
1026 return
1027 is_token(TOKEN_WHILE) ||
1028 is_token(TOKEN_TABLE) ||
1029 is_token(TOKEN_STRUCT) || is_token(TOKEN_PRIVATE_STRUCT) ||
1030 is_token(TOKEN_SWITCH) || is_token(TOKEN_DYNAMIC_SWITCH) ||
1031 is_id() || is_attribute() ||
1032 #if 1
1033 is_token(TOKEN_SEMICOLON) ||
1034 #endif
1035 0
1036 ;
1037 }
1038
1039 /* Statements = { Statement } ; */
1040 static struct _npl_statements *
xparse_statements(void)1041 xparse_statements(void)
1042 {
1043 struct _npl_statements *ret;
1044 struct _npl_statements **ptr = &ret;
1045
1046 while (is_statement()) {
1047 struct _npl_statements *cur = xnew(struct _npl_statements);
1048
1049 parse_statement(&cur->st);
1050
1051 *ptr = cur;
1052 ptr = &(cur->next);
1053 }
1054 *ptr = NULL;
1055
1056 return ret;
1057 }
1058
1059 static void
parse_while(npl_statement_t * st)1060 parse_while(npl_statement_t *st)
1061 {
1062 accept(TOKEN_WHILE);
1063
1064 if (is_id())
1065 st->w.id = accept_id();
1066
1067 accept(TOKEN_LBRACKET);
1068 parse_expression(&st->w.expr);
1069 accept(TOKEN_RBRACKET);
1070
1071 accept(TOKEN_LCURLY);
1072 st->w.sts = xparse_statements();
1073 accept(TOKEN_RCURLY);
1074 is_token_accept(TOKEN_SEMICOLON);
1075 }
1076
is_formatting(void)1077 static int is_formatting(void) { return is_token(TOKEN_ASSIGN); }
1078
1079 /* Formatting = "=", Expression ; */
1080 static npl_expression_t *
xparse_formatting(void)1081 xparse_formatting(void)
1082 {
1083 npl_expression_t *format;
1084
1085 accept(TOKEN_ASSIGN);
1086
1087 format = xnew(npl_expression_t);
1088 parse_expression(format);
1089 return format;
1090 }
1091
1092 static void parse_table(npl_table_t *);
1093 static void parse_struct(npl_struct_t *s, int statement);
1094
1095 static void
parse_statement(npl_statement_t * st)1096 parse_statement(npl_statement_t *st)
1097 {
1098 parse_all_attributes(&st->attr_list);
1099
1100 if (is_token(TOKEN_WHILE)) {
1101 parse_while(st);
1102 st->type = STATEMENT_WHILE;
1103 return;
1104 }
1105
1106 if (is_token(TOKEN_TABLE)) {
1107 parse_table(&st->t.data);
1108 st->type = STATEMENT_TABLE;
1109 return;
1110 }
1111
1112 if (is_token(TOKEN_STRUCT) || is_token(TOKEN_PRIVATE_STRUCT)) {
1113 parse_struct(&st->s.data, 1);
1114 st->type = STATEMENT_STRUCT;
1115 return;
1116 }
1117
1118 if (is_token(TOKEN_SWITCH)) {
1119 parse_switch(&(st->sw.data));
1120 st->type = STATEMENT_SWITCH;
1121 return;
1122 }
1123
1124 if (is_token(TOKEN_DYNAMIC_SWITCH)) {
1125 parse_dynamic_switch(&(st->sw.data));
1126 st->type = STATEMENT_DYNAMIC_SWITCH;
1127 return;
1128 }
1129 #if 1
1130 if (is_token(TOKEN_SEMICOLON)) {
1131 accept(TOKEN_SEMICOLON);
1132 st->type = -3;
1133 return;
1134 }
1135 #endif
1136
1137 st->type = STATEMENT_FIELD;
1138 st->f.t_id = accept_id();
1139
1140 if (is_token_accept(TOKEN_LPAREN)) {
1141 parse_expression_list(&st->f.params);
1142 accept(TOKEN_RPAREN);
1143
1144 } else
1145 st->f.params = NULL;
1146
1147 st->f.id = accept_id();
1148 if (is_token_accept(TOKEN_COLON))
1149 st->f.bits = accept_int();
1150
1151 else if (is_token_accept(TOKEN_LBRACKET)) {
1152 st->f.arr = xparse_expression();
1153 accept(TOKEN_RBRACKET);
1154 }
1155
1156 if (is_formatting())
1157 st->f.format = xparse_formatting();
1158
1159 if (is_token_accept(TOKEN_LCURLY)) {
1160 st->f.sts = xparse_statements();
1161 accept(TOKEN_RCURLY);
1162 is_token_accept(TOKEN_SEMICOLON);
1163 return;
1164 }
1165
1166 accept(TOKEN_SEMICOLON);
1167 }
1168
1169 /* Protocol = "protocol", ID, [Params], [Formatting], "{", Statements, "}", ";" ; */
1170 static void
parse_protocol(npl_protocol_t * p)1171 parse_protocol(npl_protocol_t *p)
1172 {
1173 accept(TOKEN_PROTOCOL);
1174 p->id = accept_id();
1175
1176 if (is_params())
1177 parse_params(&p->params);
1178
1179 if (is_formatting())
1180 p->format = xparse_formatting();
1181
1182 accept(TOKEN_LCURLY);
1183 p->sts = xparse_statements();
1184 accept(TOKEN_RCURLY);
1185 is_token_accept(TOKEN_SEMICOLON);
1186 }
1187
1188 static void
parse_struct(npl_struct_t * s,int statement)1189 parse_struct(npl_struct_t *s, int statement)
1190 {
1191 if (is_token_accept(TOKEN_STRUCT))
1192 s->private = 0;
1193 else if (is_token_accept(TOKEN_PRIVATE_STRUCT))
1194 s->private = 1;
1195 else
1196 nomatch();
1197
1198 if (!statement || is_id())
1199 s->id = accept_id();
1200
1201 if (is_params())
1202 parse_params(&s->params);
1203
1204 if (statement) {
1205 if (is_token_accept(TOKEN_LBRACKET)) {
1206 s->count_expr = xparse_expression();
1207 accept(TOKEN_RBRACKET);
1208 }
1209 }
1210
1211 if (is_formatting())
1212 s->format = xparse_formatting();
1213
1214 accept(TOKEN_LCURLY);
1215 s->sts = xparse_statements();
1216 accept(TOKEN_RCURLY);
1217 is_token_accept(TOKEN_SEMICOLON);
1218 }
1219
1220 /* Table = "table", ID, [Params], "{", "switch", [ "(", Expr, ")" ], {TableCase}, [DefaultCase], "}", ";" ;
1221
1222 DefaultCase = "default", ":", Expression", ";" ;
1223 */
1224 static void
parse_table(npl_table_t * t)1225 parse_table(npl_table_t *t)
1226 {
1227 accept(TOKEN_TABLE);
1228 t->id = accept_id();
1229 if (is_params())
1230 parse_params(&t->params);
1231
1232 accept(TOKEN_LCURLY);
1233 {
1234 struct npl_table_case **ptr;
1235
1236 accept(TOKEN_SWITCH);
1237 if (is_token_accept(TOKEN_LPAREN)) {
1238 t->switch_expr = xparse_expression();
1239 accept(TOKEN_RPAREN);
1240 }
1241
1242 accept(TOKEN_LCURLY);
1243
1244 ptr = &(t->cases);
1245 while (is_token_accept(TOKEN_CASE)) {
1246 struct npl_table_case *cur;
1247
1248 cur = *ptr = xnew(struct npl_table_case);
1249 ptr = &(cur->next);
1250
1251 parse_expression(&(cur->e));
1252 accept(TOKEN_COLON);
1253
1254 while (is_token_accept(TOKEN_CASE)) {
1255 cur = *ptr = xnew(struct npl_table_case);
1256 ptr = &(cur->next);
1257
1258 parse_expression(&(cur->e));
1259 accept(TOKEN_COLON);
1260 }
1261 cur->return_expr = xparse_expression();
1262 accept(TOKEN_SEMICOLON);
1263 }
1264 *ptr = NULL;
1265
1266 if (is_token_accept(TOKEN_DEFAULT)) {
1267 accept(TOKEN_COLON);
1268 t->default_expr = xparse_expression();
1269 accept(TOKEN_SEMICOLON);
1270 }
1271 accept(TOKEN_RCURLY);
1272
1273 }
1274 accept(TOKEN_RCURLY);
1275 is_token_accept(TOKEN_SEMICOLON);
1276 }
1277
1278 static int
is_type(void)1279 is_type(void)
1280 {
1281 return
1282 is_token(TOKEN_DECIMAL) ||
1283 is_token(TOKEN_NUMBER) ||
1284 is_token(TOKEN_TIME) ||
1285 is_token(TOKEN_UNSIGNED_NUMBER);
1286 }
1287
1288 /* Type = BasicType, ID, [Params], "{", {TypeAttr}, "}" ;
1289
1290 BasicType = "Decimal" | "Number" | "Time" | "UnsignedNumber" ;
1291
1292 TypeAttr = AttrName, "=", Expression ;
1293
1294 AttrName = "ByteOrder" | "DisplayFormat" | "Size" ;
1295 */
1296 static void
parse_type(npl_type_t * t)1297 parse_type(npl_type_t *t)
1298 {
1299 if (is_token_accept(TOKEN_DECIMAL))
1300 t->type = FIELD_DECIMAL;
1301 else if (is_token_accept(TOKEN_NUMBER))
1302 t->type = FIELD_NUMBER;
1303 else if (is_token_accept(TOKEN_TIME))
1304 t->type = FIELD_TIME;
1305 else if (is_token_accept(TOKEN_UNSIGNED_NUMBER))
1306 t->type = FIELD_UNSIGNED_NUMBER;
1307 else
1308 nomatch();
1309
1310 t->id = accept_id();
1311 if (is_params())
1312 parse_params(&t->params);
1313 accept(TOKEN_LCURLY);
1314
1315 while (!is_token(TOKEN_RCURLY)) {
1316 npl_expression_t **ptr;
1317
1318 if (is_token_accept(TOKEN_BYTE_ORDER))
1319 ptr = &t->byte_order;
1320 else if (is_token_accept(TOKEN_DISPLAY_FORMAT))
1321 ptr = &t->display_format;
1322 else if (is_token_accept(TOKEN_SIZE))
1323 ptr = &t->size;
1324 else
1325 nomatch();
1326 #if 0
1327 if (*ptr)
1328 fprintf(stdout, "already got %s attr!\n", str);
1329 #endif
1330 accept(TOKEN_ASSIGN);
1331 *ptr = xparse_expression();
1332
1333 if (is_token_accept(TOKEN_COMMA))
1334 { }
1335 else if (is_token_accept(TOKEN_SEMICOLON))
1336 { }
1337 }
1338 accept(TOKEN_RCURLY);
1339 }
1340
1341 /* Const = "const", ID, "=", Expression, ";" ; */
1342 static void
parse_const(npl_const_t * c)1343 parse_const(npl_const_t *c)
1344 {
1345 accept(TOKEN_CONST);
1346 c->id = accept_id();
1347 accept(TOKEN_ASSIGN);
1348 parse_expression(&c->expr);
1349 accept(TOKEN_SEMICOLON);
1350 }
1351
1352 /* Declaration = Attributes
1353 | Struct
1354 | Table
1355 | Const
1356 | Protocol
1357 | Type
1358 | ( "include", STR )
1359 ;
1360 */
1361 static void
parse_decl(npl_decl_t * d)1362 parse_decl(npl_decl_t *d)
1363 {
1364 parse_all_attributes(&d->attr_list);
1365
1366 if (is_token(TOKEN_STRUCT)) {
1367 d->type = DECL_STRUCT;
1368 parse_struct(&d->s.data, 0);
1369
1370 } else if (is_token(TOKEN_TABLE)) {
1371 d->type = DECL_TABLE;
1372 parse_table(&d->t.data);
1373
1374 } else if (is_token(TOKEN_CONST)) {
1375 d->type = DECL_CONST;
1376 parse_const(&d->c.data);
1377
1378 } else if (is_token(TOKEN_PROTOCOL)) {
1379 d->type = DECL_PROTOCOL;
1380 parse_protocol(&d->p.data);
1381
1382 } else if (is_type()) {
1383 d->type = DECL_TYPE;
1384 parse_type(&d->ty.data);
1385
1386 } else if (is_token_accept(TOKEN_INCLUDE)) {
1387 d->type = DECL_INCLUDE;
1388 d->i.file = accept_str(); /* XXX, it's C-escaped */ /* XXX, unix / vs dos \\ */
1389
1390 } else
1391 nomatch();
1392 }
1393
1394 /* NPL = { Declaration } ; */
1395 static void
parse_npl(npl_code_t * code)1396 parse_npl(npl_code_t *code)
1397 {
1398 struct _npl_decl_list **ptr = &(code->decls);
1399
1400 while (!is_token_accept(TOKEN_EOF)) {
1401 struct _npl_decl_list *cur = xnew(struct _npl_decl_list);
1402
1403 *ptr = cur;
1404 ptr = &(cur->next);
1405
1406 parse_decl(&cur->d);
1407 }
1408 *ptr = NULL;
1409 }
1410
1411 int
npl_parse_file(npl_code_t * code,FILE * f,const char * filename)1412 npl_parse_file(npl_code_t *code, FILE *f, const char *filename)
1413 {
1414 volatile int parse_ok = 0;
1415
1416 yyfilename = filename;
1417 yyin = f;
1418
1419 if (!setjmp(parser_exception)) {
1420 next_token();
1421 parse_npl(code);
1422 parse_ok = 1;
1423 }
1424
1425 yylex_destroy();
1426
1427 return (parse_ok == 1);
1428 }
1429
1430