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 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 296 static void xfail(void) { longjmp(parser_exception, 1); } 297 298 static void next_token(void) { token = yylex(); } 299 300 static inline int is_token(token_type_t tok) { return (token == tok); } 301 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 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 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 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 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 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 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 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 458 static int is_params(void) { return is_token(TOKEN_LPAREN); } 459 460 static void 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 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 922 static int is_attribute(void) { return is_token(TOKEN_LBRACKET); } 923 924 static npl_attribute_list_t ** 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 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 * 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 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 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 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 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 * 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 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 1077 static int is_formatting(void) { return is_token(TOKEN_ASSIGN); } 1078 1079 /* Formatting = "=", Expression ; */ 1080 static npl_expression_t * 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 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 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 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 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 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 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 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 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 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 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