1 /* 2 * Copyright (c) Freescale Semiconductor, Inc. All rights reserved. 3 * See included license file for license details. 4 */ 5 6 /* write header with token defines */ 7 %defines 8 9 /* make it reentrant */ 10 %pure-parser 11 12 /* put more info in error messages */ 13 %error-verbose 14 15 /* enable location processing */ 16 %locations 17 18 %{ 19 #include "ElftosbLexer.h" 20 #include "ElftosbAST.h" 21 #include "Logging.h" 22 #include "Blob.h" 23 #include "format_string.h" 24 #include "Value.h" 25 #include "ConversionController.h" 26 27 using namespace elftosb; 28 29 //! Our special location type. 30 #define YYLTYPE token_loc_t 31 32 // this indicates that we're using our own type. it should be unset automatically 33 // but that's not working for some reason with the .hpp file. 34 #if defined(YYLTYPE_IS_TRIVIAL) 35 #undef YYLTYPE_IS_TRIVIAL 36 #define YYLTYPE_IS_TRIVIAL 0 37 #endif 38 39 //! Default location action 40 #define YYLLOC_DEFAULT(Current, Rhs, N) \ 41 do { \ 42 if (N) \ 43 { \ 44 (Current).m_firstLine = YYRHSLOC(Rhs, 1).m_firstLine; \ 45 (Current).m_lastLine = YYRHSLOC(Rhs, N).m_lastLine; \ 46 } \ 47 else \ 48 { \ 49 (Current).m_firstLine = (Current).m_lastLine = YYRHSLOC(Rhs, 0).m_lastLine; \ 50 } \ 51 } while (0) 52 53 //! Forward declaration of yylex(). 54 static int yylex(YYSTYPE * lvalp, YYLTYPE * yylloc, ElftosbLexer * lexer); 55 56 // Forward declaration of error handling function. 57 static void yyerror(YYLTYPE * yylloc, ElftosbLexer * lexer, CommandFileASTNode ** resultAST, const char * error); 58 59 %} 60 61 /* symbol types */ 62 %union { 63 int m_num; 64 elftosb::SizedIntegerValue * m_int; 65 Blob * m_blob; 66 std::string * m_str; 67 elftosb::ASTNode * m_ast; // must use full name here because this is put into *.tab.hpp 68 } 69 70 /* extra parameters for the parser and lexer */ 71 %parse-param {ElftosbLexer * lexer} 72 %parse-param {CommandFileASTNode ** resultAST} 73 %lex-param {ElftosbLexer * lexer} 74 75 /* token definitions */ 76 %token <m_str> TOK_IDENT "identifier" 77 %token <m_str> TOK_STRING_LITERAL "string" 78 %token <m_int> TOK_INT_LITERAL "integer" 79 %token <m_str> TOK_SECTION_NAME "section name" 80 %token <m_str> TOK_SOURCE_NAME "source name" 81 %token <m_blob> TOK_BLOB "binary object" 82 %token '(' 83 %token ')' 84 %token '{' 85 %token '}' 86 %token '[' 87 %token ']' 88 %token '=' 89 %token ',' 90 %token ';' 91 %token ':' 92 %token '>' 93 %token '.' 94 %token TOK_DOT_DOT ".." 95 %token '~' 96 %token '&' 97 %token '|' 98 %token '<' 99 %token '>' 100 %token '!' 101 %token TOK_AND "&&" 102 %token TOK_OR "||" 103 %token TOK_GEQ ">=" 104 %token TOK_LEQ "<=" 105 %token TOK_EQ "==" 106 %token TOK_NEQ "!=" 107 %token TOK_POWER "**" 108 %token TOK_LSHIFT "<<" 109 %token TOK_RSHIFT ">>" 110 %token <m_int> TOK_INT_SIZE "integer size" 111 %token TOK_OPTIONS "options" 112 %token TOK_CONSTANTS "constants" 113 %token TOK_SOURCES "sources" 114 %token TOK_FILTERS "filters" 115 %token TOK_SECTION "section" 116 %token TOK_EXTERN "extern" 117 %token TOK_FROM "from" 118 %token TOK_RAW "raw" 119 %token TOK_LOAD "load" 120 %token TOK_JUMP "jump" 121 %token TOK_CALL "call" 122 %token TOK_MODE "mode" 123 %token TOK_IF "if" 124 %token TOK_ELSE "else" 125 %token TOK_DEFINED "defined" 126 %token TOK_INFO "info" 127 %token TOK_WARNING "warning" 128 %token TOK_ERROR "error" 129 %token TOK_SIZEOF "sizeof" 130 %token TOK_DCD "dcd" 131 %token TOK_HAB "hab" 132 %token TOK_IVT "ivt" 133 134 /* operator precedence */ 135 %left "&&" "||" 136 %left '>' '<' ">=" "<=" "==" "!=" 137 %left '|' 138 %left '^' 139 %left '&' 140 %left "<<" ">>" 141 %left "**" 142 %left '+' '-' 143 %left '*' '/' '%' 144 %left '.' 145 %right UNARY_OP 146 147 /* nonterminal types - most nonterminal symbols are subclasses of ASTNode */ 148 %type <m_ast> command_file blocks_list pre_section_block options_block const_def_list const_def_list_elem 149 %type <m_ast> const_def const_expr expr int_const_expr unary_expr int_value constants_block 150 %type <m_ast> sources_block source_def_list source_def_list_elem source_def 151 %type <m_ast> section_defs section_def section_contents full_stmt_list full_stmt_list_elem 152 %type <m_ast> basic_stmt load_stmt call_stmt from_stmt load_data load_target call_target 153 %type <m_ast> address_or_range load_target_opt call_arg_opt basic_stmt_list basic_stmt_list_elem 154 %type <m_ast> source_attr_list source_attr_list_elem source_attrs_opt 155 %type <m_ast> section_list section_list_elem symbol_ref mode_stmt 156 %type <m_ast> section_options_opt source_attr_list_opt 157 %type <m_ast> if_stmt else_opt message_stmt 158 %type <m_ast> bool_expr ivt_def assignment_list_opt 159 160 %type <m_num> call_or_jump dcd_opt 161 162 %destructor { delete $$; } TOK_IDENT TOK_STRING_LITERAL TOK_SECTION_NAME TOK_SOURCE_NAME TOK_BLOB TOK_INT_SIZE TOK_INT_LITERAL 163 164 %% 165 166 command_file : blocks_list section_defs 167 { 168 CommandFileASTNode * commandFile = new CommandFileASTNode(); 169 commandFile->setBlocks(dynamic_cast<ListASTNode*>($1)); 170 commandFile->setSections(dynamic_cast<ListASTNode*>($2)); 171 commandFile->setLocation(@1, @2); 172 *resultAST = commandFile; 173 } 174 ; 175 176 blocks_list : pre_section_block 177 { 178 ListASTNode * list = new ListASTNode(); 179 list->appendNode($1); 180 $$ = list; 181 } 182 | blocks_list pre_section_block 183 { 184 dynamic_cast<ListASTNode*>($1)->appendNode($2); 185 $$ = $1; 186 } 187 ; 188 189 pre_section_block 190 : options_block { $$ = $1; } 191 | constants_block { $$ = $1; } 192 | sources_block { $$ = $1; } 193 ; 194 195 options_block : "options" '{' const_def_list '}' 196 { 197 $$ = new OptionsBlockASTNode(dynamic_cast<ListASTNode *>($3)); 198 } 199 ; 200 201 constants_block : "constants" '{' const_def_list '}' 202 { 203 $$ = new ConstantsBlockASTNode(dynamic_cast<ListASTNode *>($3)); 204 } 205 ; 206 207 const_def_list : const_def_list_elem 208 { 209 ListASTNode * list = new ListASTNode(); 210 list->appendNode($1); 211 $$ = list; 212 } 213 | const_def_list const_def_list_elem 214 { 215 dynamic_cast<ListASTNode*>($1)->appendNode($2); 216 $$ = $1; 217 } 218 ; 219 220 const_def_list_elem : const_def ';' { $$ = $1; } 221 | /* empty */ { $$ = NULL; } 222 ; 223 224 const_def : TOK_IDENT '=' const_expr 225 { 226 $$ = new AssignmentASTNode($1, $3); 227 $$->setLocation(@1, @3); 228 } 229 ; 230 231 sources_block : "sources" '{' source_def_list '}' 232 { 233 $$ = new SourcesBlockASTNode(dynamic_cast<ListASTNode *>($3)); 234 } 235 ; 236 237 source_def_list : source_def_list_elem 238 { 239 ListASTNode * list = new ListASTNode(); 240 list->appendNode($1); 241 $$ = list; 242 } 243 | source_def_list source_def_list_elem 244 { 245 dynamic_cast<ListASTNode*>($1)->appendNode($2); 246 $$ = $1; 247 } 248 ; 249 250 source_def_list_elem 251 : source_def source_attrs_opt ';' 252 { 253 // tell the lexer that this is the name of a source file 254 SourceDefASTNode * node = dynamic_cast<SourceDefASTNode*>($1); 255 if ($2) 256 { 257 node->setAttributes(dynamic_cast<ListASTNode*>($2)); 258 } 259 node->setLocation(node->getLocation(), @3); 260 lexer->addSourceName(node->getName()); 261 $$ = $1; 262 } 263 | /* empty */ { $$ = NULL; } 264 ; 265 266 source_def : TOK_IDENT '=' TOK_STRING_LITERAL 267 { 268 $$ = new PathSourceDefASTNode($1, $3); 269 $$->setLocation(@1, @3); 270 } 271 | TOK_IDENT '=' "extern" '(' int_const_expr ')' 272 { 273 $$ = new ExternSourceDefASTNode($1, dynamic_cast<ExprASTNode*>($5)); 274 $$->setLocation(@1, @6); 275 } 276 ; 277 278 source_attrs_opt 279 : '(' source_attr_list ')' { $$ = $2; } 280 | /* empty */ { $$ = NULL; } 281 ; 282 283 source_attr_list 284 : source_attr_list_elem 285 { 286 ListASTNode * list = new ListASTNode(); 287 list->appendNode($1); 288 $$ = list; 289 } 290 | source_attr_list ',' source_attr_list_elem 291 { 292 dynamic_cast<ListASTNode*>($1)->appendNode($3); 293 $$ = $1; 294 } 295 ; 296 297 source_attr_list_elem 298 : TOK_IDENT '=' const_expr 299 { 300 $$ = new AssignmentASTNode($1, $3); 301 $$->setLocation(@1, @3); 302 } 303 ; 304 305 section_defs : section_def 306 { 307 ListASTNode * list = new ListASTNode(); 308 list->appendNode($1); 309 $$ = list; 310 } 311 | section_defs section_def 312 { 313 dynamic_cast<ListASTNode*>($1)->appendNode($2); 314 $$ = $1; 315 } 316 ; 317 318 section_def : "section" '(' int_const_expr section_options_opt ')' section_contents 319 { 320 SectionContentsASTNode * sectionNode = dynamic_cast<SectionContentsASTNode*>($6); 321 if (sectionNode) 322 { 323 ExprASTNode * exprNode = dynamic_cast<ExprASTNode*>($3); 324 sectionNode->setSectionNumberExpr(exprNode); 325 sectionNode->setOptions(dynamic_cast<ListASTNode*>($4)); 326 sectionNode->setLocation(@1, sectionNode->getLocation()); 327 } 328 $$ = $6; 329 } 330 ; 331 332 section_options_opt 333 : ';' source_attr_list_opt 334 { 335 $$ = $2; 336 } 337 | /* empty */ 338 { 339 $$ = NULL; 340 } 341 ; 342 343 source_attr_list_opt 344 : source_attr_list 345 { 346 $$ = $1; 347 } 348 | /* empty */ 349 { 350 $$ = NULL; 351 } 352 ; 353 354 section_contents 355 : "<=" load_data ';' 356 { 357 DataSectionContentsASTNode * dataSection = new DataSectionContentsASTNode($2); 358 dataSection->setLocation(@1, @3); 359 $$ = dataSection; 360 } 361 | '{' full_stmt_list '}' 362 { 363 ListASTNode * listNode = dynamic_cast<ListASTNode*>($2); 364 $$ = new BootableSectionContentsASTNode(listNode); 365 $$->setLocation(@1, @3); 366 } 367 ; 368 369 full_stmt_list : full_stmt_list_elem 370 { 371 ListASTNode * list = new ListASTNode(); 372 list->appendNode($1); 373 $$ = list; 374 } 375 | full_stmt_list full_stmt_list_elem 376 { 377 dynamic_cast<ListASTNode*>($1)->appendNode($2); 378 $$ = $1; 379 } 380 ; 381 382 full_stmt_list_elem 383 : basic_stmt ';' { $$ = $1; } 384 | from_stmt { $$ = $1; } 385 | if_stmt { $$ = $1; } 386 | /* empty */ { $$ = NULL; } 387 ; 388 389 basic_stmt_list : basic_stmt_list_elem 390 { 391 ListASTNode * list = new ListASTNode(); 392 list->appendNode($1); 393 $$ = list; 394 } 395 | basic_stmt_list basic_stmt_list_elem 396 { 397 dynamic_cast<ListASTNode*>($1)->appendNode($2); 398 $$ = $1; 399 } 400 ; 401 402 basic_stmt_list_elem 403 : basic_stmt ';' { $$ = $1; } 404 | if_stmt { $$ = $1; } 405 | /* empty */ { $$ = NULL; } 406 ; 407 408 basic_stmt : load_stmt { $$ = $1; } 409 | call_stmt { $$ = $1; } 410 | mode_stmt { $$ = $1; } 411 | message_stmt { $$ = $1; } 412 ; 413 414 load_stmt : "load" dcd_opt load_data load_target_opt 415 { 416 LoadStatementASTNode * stmt = new LoadStatementASTNode(); 417 stmt->setData($3); 418 stmt->setTarget($4); 419 // set dcd load flag if the "dcd" keyword was present. 420 if ($2) 421 { 422 stmt->setDCDLoad(true); 423 } 424 // set char locations for the statement 425 if ($4) 426 { 427 stmt->setLocation(@1, @4); 428 } 429 else 430 { 431 stmt->setLocation(@1, @3); 432 } 433 $$ = stmt; 434 } 435 ; 436 437 dcd_opt : "dcd" 438 { 439 if (!elftosb::g_enableHABSupport) 440 { 441 yyerror(&yylloc, lexer, resultAST, "HAB features not supported with the selected family"); 442 YYABORT; 443 } 444 445 $$ = 1; 446 } 447 | /* empty */ { $$ = 0; } 448 449 load_data : int_const_expr 450 { 451 $$ = $1; 452 } 453 | TOK_STRING_LITERAL 454 { 455 $$ = new StringConstASTNode($1); 456 $$->setLocation(@1); 457 } 458 | TOK_SOURCE_NAME 459 { 460 $$ = new SourceASTNode($1); 461 $$->setLocation(@1); 462 } 463 | section_list 464 { 465 $$ = new SectionMatchListASTNode(dynamic_cast<ListASTNode*>($1)); 466 $$->setLocation(@1); 467 } 468 | section_list "from" TOK_SOURCE_NAME 469 { 470 $$ = new SectionMatchListASTNode(dynamic_cast<ListASTNode*>($1), $3); 471 $$->setLocation(@1, @3); 472 } 473 | TOK_SOURCE_NAME '[' section_list ']' 474 { 475 $$ = new SectionMatchListASTNode(dynamic_cast<ListASTNode*>($3), $1); 476 $$->setLocation(@1, @4); 477 } 478 | TOK_BLOB 479 { 480 $$ = new BlobConstASTNode($1); 481 $$->setLocation(@1); 482 } 483 | ivt_def 484 { 485 } 486 ; 487 488 section_list : section_list_elem 489 { 490 ListASTNode * list = new ListASTNode(); 491 list->appendNode($1); 492 $$ = list; 493 } 494 | section_list ',' section_list_elem 495 { 496 dynamic_cast<ListASTNode*>($1)->appendNode($3); 497 $$ = $1; 498 } 499 ; 500 501 section_list_elem 502 : TOK_SECTION_NAME 503 { 504 $$ = new SectionASTNode($1, SectionASTNode::kInclude); 505 $$->setLocation(@1); 506 } 507 | '~' TOK_SECTION_NAME 508 { 509 $$ = new SectionASTNode($2, SectionASTNode::kExclude); 510 $$->setLocation(@1, @2); 511 } 512 ; 513 514 load_target_opt : '>' load_target 515 { 516 $$ = $2; 517 } 518 | /* empty */ 519 { 520 $$ = new NaturalLocationASTNode(); 521 // $$->setLocation(); 522 } 523 ; 524 525 load_target : '.' 526 { 527 $$ = new NaturalLocationASTNode(); 528 $$->setLocation(@1); 529 } 530 | address_or_range 531 { 532 $$ = $1; 533 } 534 ; 535 536 ivt_def : "ivt" '(' assignment_list_opt ')' 537 { 538 IVTConstASTNode * ivt = new IVTConstASTNode(); 539 if ($3) 540 { 541 ivt->setFieldAssignments(dynamic_cast<ListASTNode*>($3)); 542 } 543 ivt->setLocation(@1, @4); 544 $$ = ivt; 545 } 546 ; 547 548 assignment_list_opt : source_attr_list { $$ = $1; } 549 | /* empty */ { $$ = NULL; } 550 ; 551 552 call_stmt : call_or_jump call_target call_arg_opt 553 { 554 CallStatementASTNode * stmt = new CallStatementASTNode(); 555 switch ($1) 556 { 557 case 1: 558 stmt->setCallType(CallStatementASTNode::kCallType); 559 break; 560 case 2: 561 stmt->setCallType(CallStatementASTNode::kJumpType); 562 break; 563 default: 564 yyerror(&yylloc, lexer, resultAST, "invalid call_or_jump value"); 565 YYABORT; 566 break; 567 } 568 stmt->setTarget($2); 569 stmt->setArgument($3); 570 stmt->setIsHAB(false); 571 if ($3) 572 { 573 stmt->setLocation(@1, @3); 574 } 575 else 576 { 577 stmt->setLocation(@1, @2); 578 } 579 $$ = stmt; 580 } 581 | "hab" call_or_jump address_or_range call_arg_opt 582 { 583 if (!elftosb::g_enableHABSupport) 584 { 585 yyerror(&yylloc, lexer, resultAST, "HAB features not supported with the selected family"); 586 YYABORT; 587 } 588 589 CallStatementASTNode * stmt = new CallStatementASTNode(); 590 switch ($2) 591 { 592 case 1: 593 stmt->setCallType(CallStatementASTNode::kCallType); 594 break; 595 case 2: 596 stmt->setCallType(CallStatementASTNode::kJumpType); 597 break; 598 default: 599 yyerror(&yylloc, lexer, resultAST, "invalid call_or_jump value"); 600 YYABORT; 601 break; 602 } 603 stmt->setTarget($3); 604 stmt->setArgument($4); 605 stmt->setIsHAB(true); 606 if ($4) 607 { 608 stmt->setLocation(@1, @4); 609 } 610 else 611 { 612 stmt->setLocation(@1, @3); 613 } 614 $$ = stmt; 615 } 616 ; 617 618 call_or_jump : "call" { $$ = 1; } 619 | "jump" { $$ = 2; } 620 ; 621 622 call_target : TOK_SOURCE_NAME 623 { 624 $$ = new SymbolASTNode(NULL, $1); 625 $$->setLocation(@1); 626 } 627 | int_const_expr 628 { 629 $$ = new AddressRangeASTNode($1, NULL); 630 $$->setLocation($1); 631 } 632 ; 633 634 call_arg_opt : '(' int_const_expr ')' { $$ = $2; } 635 | '(' ')' { $$ = NULL; } 636 | /* empty */ { $$ = NULL; } 637 ; 638 639 from_stmt : "from" TOK_SOURCE_NAME '{' basic_stmt_list '}' 640 { 641 $$ = new FromStatementASTNode($2, dynamic_cast<ListASTNode*>($4)); 642 $$->setLocation(@1, @5); 643 } 644 ; 645 646 mode_stmt : "mode" int_const_expr 647 { 648 $$ = new ModeStatementASTNode(dynamic_cast<ExprASTNode*>($2)); 649 $$->setLocation(@1, @2); 650 } 651 ; 652 653 message_stmt : "info" TOK_STRING_LITERAL 654 { 655 $$ = new MessageStatementASTNode(MessageStatementASTNode::kInfo, $2); 656 $$->setLocation(@1, @2); 657 } 658 | "warning" TOK_STRING_LITERAL 659 { 660 $$ = new MessageStatementASTNode(MessageStatementASTNode::kWarning, $2); 661 $$->setLocation(@1, @2); 662 } 663 | "error" TOK_STRING_LITERAL 664 { 665 $$ = new MessageStatementASTNode(MessageStatementASTNode::kError, $2); 666 $$->setLocation(@1, @2); 667 } 668 ; 669 670 if_stmt : "if" bool_expr '{' full_stmt_list '}' else_opt 671 { 672 IfStatementASTNode * ifStmt = new IfStatementASTNode(); 673 ifStmt->setConditionExpr(dynamic_cast<ExprASTNode*>($2)); 674 ifStmt->setIfStatements(dynamic_cast<ListASTNode*>($4)); 675 ifStmt->setElseStatements(dynamic_cast<ListASTNode*>($6)); 676 ifStmt->setLocation(@1, @6); 677 $$ = ifStmt; 678 } 679 ; 680 681 else_opt : "else" '{' full_stmt_list '}' 682 { 683 $$ = $3; 684 } 685 | "else" if_stmt 686 { 687 ListASTNode * list = new ListASTNode(); 688 list->appendNode($2); 689 $$ = list; 690 $$->setLocation(@1, @2); 691 } 692 | /* empty */ { $$ = NULL; } 693 ; 694 695 address_or_range : int_const_expr 696 { 697 $$ = new AddressRangeASTNode($1, NULL); 698 $$->setLocation($1); 699 } 700 | int_const_expr ".." int_const_expr 701 { 702 $$ = new AddressRangeASTNode($1, $3); 703 $$->setLocation(@1, @3); 704 } 705 ; 706 707 const_expr : bool_expr 708 { 709 $$ = $1; 710 } 711 | TOK_STRING_LITERAL 712 { 713 $$ = new StringConstASTNode($1); 714 $$->setLocation(@1); 715 } 716 ; 717 718 bool_expr : int_const_expr 719 { 720 $$ = $1; 721 } 722 | bool_expr '<' bool_expr 723 { 724 ExprASTNode * left = dynamic_cast<ExprASTNode*>($1); 725 ExprASTNode * right = dynamic_cast<ExprASTNode*>($3); 726 $$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kLessThan, right); 727 $$->setLocation(@1, @3); 728 } 729 | bool_expr '>' bool_expr 730 { 731 ExprASTNode * left = dynamic_cast<ExprASTNode*>($1); 732 ExprASTNode * right = dynamic_cast<ExprASTNode*>($3); 733 $$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kGreaterThan, right); 734 $$->setLocation(@1, @3); 735 } 736 | bool_expr ">=" bool_expr 737 { 738 ExprASTNode * left = dynamic_cast<ExprASTNode*>($1); 739 ExprASTNode * right = dynamic_cast<ExprASTNode*>($3); 740 $$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kGreaterThanEqual, right); 741 $$->setLocation(@1, @3); 742 } 743 | bool_expr "<=" bool_expr 744 { 745 ExprASTNode * left = dynamic_cast<ExprASTNode*>($1); 746 ExprASTNode * right = dynamic_cast<ExprASTNode*>($3); 747 $$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kLessThanEqual, right); 748 $$->setLocation(@1, @3); 749 } 750 | bool_expr "==" bool_expr 751 { 752 ExprASTNode * left = dynamic_cast<ExprASTNode*>($1); 753 ExprASTNode * right = dynamic_cast<ExprASTNode*>($3); 754 $$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kEqual, right); 755 $$->setLocation(@1, @3); 756 } 757 | bool_expr "!=" bool_expr 758 { 759 ExprASTNode * left = dynamic_cast<ExprASTNode*>($1); 760 ExprASTNode * right = dynamic_cast<ExprASTNode*>($3); 761 $$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kNotEqual, right); 762 $$->setLocation(@1, @3); 763 } 764 | bool_expr "&&" bool_expr 765 { 766 ExprASTNode * left = dynamic_cast<ExprASTNode*>($1); 767 ExprASTNode * right = dynamic_cast<ExprASTNode*>($3); 768 $$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kBooleanAnd, right); 769 $$->setLocation(@1, @3); 770 } 771 | bool_expr "||" bool_expr 772 { 773 ExprASTNode * left = dynamic_cast<ExprASTNode*>($1); 774 ExprASTNode * right = dynamic_cast<ExprASTNode*>($3); 775 $$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kBooleanOr, right); 776 $$->setLocation(@1, @3); 777 } 778 | '!' bool_expr %prec UNARY_OP 779 { 780 $$ = new BooleanNotExprASTNode(dynamic_cast<ExprASTNode*>($2)); 781 $$->setLocation(@1, @2); 782 } 783 | TOK_IDENT '(' TOK_SOURCE_NAME ')' 784 { 785 $$ = new SourceFileFunctionASTNode($1, $3); 786 $$->setLocation(@1, @4); 787 } 788 | '(' bool_expr ')' 789 { 790 $$ = $2; 791 $$->setLocation(@1, @3); 792 } 793 | "defined" '(' TOK_IDENT ')' 794 { 795 $$ = new DefinedOperatorASTNode($3); 796 $$->setLocation(@1, @4); 797 } 798 ; 799 800 int_const_expr : expr { $$ = $1; } 801 ; 802 803 symbol_ref : TOK_SOURCE_NAME ':' TOK_IDENT 804 { 805 $$ = new SymbolASTNode($3, $1); 806 $$->setLocation(@1, @3); 807 } 808 | ':' TOK_IDENT 809 { 810 $$ = new SymbolASTNode($2); 811 $$->setLocation(@1, @2); 812 } 813 ; 814 815 816 expr : int_value 817 { 818 $$ = $1; 819 } 820 | TOK_IDENT 821 { 822 $$ = new VariableExprASTNode($1); 823 $$->setLocation(@1); 824 } 825 | symbol_ref 826 { 827 $$ = new SymbolRefExprASTNode(dynamic_cast<SymbolASTNode*>($1)); 828 $$->setLocation(@1); 829 } 830 /* | expr '..' expr 831 { 832 ExprASTNode * left = dynamic_cast<ExprASTNode*>($1); 833 ExprASTNode * right = dynamic_cast<ExprASTNode*>($3); 834 $$ = new RangeExprASTNode(left, right); 835 } 836 */ | expr '+' expr 837 { 838 ExprASTNode * left = dynamic_cast<ExprASTNode*>($1); 839 ExprASTNode * right = dynamic_cast<ExprASTNode*>($3); 840 $$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kAdd, right); 841 $$->setLocation(@1, @3); 842 } 843 | expr '-' expr 844 { 845 ExprASTNode * left = dynamic_cast<ExprASTNode*>($1); 846 ExprASTNode * right = dynamic_cast<ExprASTNode*>($3); 847 $$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kSubtract, right); 848 $$->setLocation(@1, @3); 849 } 850 | expr '*' expr 851 { 852 ExprASTNode * left = dynamic_cast<ExprASTNode*>($1); 853 ExprASTNode * right = dynamic_cast<ExprASTNode*>($3); 854 $$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kMultiply, right); 855 $$->setLocation(@1, @3); 856 } 857 | expr '/' expr 858 { 859 ExprASTNode * left = dynamic_cast<ExprASTNode*>($1); 860 ExprASTNode * right = dynamic_cast<ExprASTNode*>($3); 861 $$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kDivide, right); 862 $$->setLocation(@1, @3); 863 } 864 | expr '%' expr 865 { 866 ExprASTNode * left = dynamic_cast<ExprASTNode*>($1); 867 ExprASTNode * right = dynamic_cast<ExprASTNode*>($3); 868 $$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kModulus, right); 869 $$->setLocation(@1, @3); 870 } 871 | expr "**" expr 872 { 873 ExprASTNode * left = dynamic_cast<ExprASTNode*>($1); 874 ExprASTNode * right = dynamic_cast<ExprASTNode*>($3); 875 $$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kPower, right); 876 $$->setLocation(@1, @3); 877 } 878 | expr '&' expr 879 { 880 ExprASTNode * left = dynamic_cast<ExprASTNode*>($1); 881 ExprASTNode * right = dynamic_cast<ExprASTNode*>($3); 882 $$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kBitwiseAnd, right); 883 $$->setLocation(@1, @3); 884 } 885 | expr '|' expr 886 { 887 ExprASTNode * left = dynamic_cast<ExprASTNode*>($1); 888 ExprASTNode * right = dynamic_cast<ExprASTNode*>($3); 889 $$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kBitwiseOr, right); 890 $$->setLocation(@1, @3); 891 } 892 | expr '^' expr 893 { 894 ExprASTNode * left = dynamic_cast<ExprASTNode*>($1); 895 ExprASTNode * right = dynamic_cast<ExprASTNode*>($3); 896 $$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kBitwiseXor, right); 897 $$->setLocation(@1, @3); 898 } 899 | expr "<<" expr 900 { 901 ExprASTNode * left = dynamic_cast<ExprASTNode*>($1); 902 ExprASTNode * right = dynamic_cast<ExprASTNode*>($3); 903 $$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kShiftLeft, right); 904 $$->setLocation(@1, @3); 905 } 906 | expr ">>" expr 907 { 908 ExprASTNode * left = dynamic_cast<ExprASTNode*>($1); 909 ExprASTNode * right = dynamic_cast<ExprASTNode*>($3); 910 $$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kShiftRight, right); 911 $$->setLocation(@1, @3); 912 } 913 | unary_expr 914 { 915 $$ = $1; 916 } 917 | expr '.' TOK_INT_SIZE 918 { 919 $$ = new IntSizeExprASTNode(dynamic_cast<ExprASTNode*>($1), $3->getWordSize()); 920 $$->setLocation(@1, @3); 921 } 922 | '(' expr ')' 923 { 924 $$ = $2; 925 $$->setLocation(@1, @3); 926 } 927 | "sizeof" '(' symbol_ref ')' 928 { 929 $$ = new SizeofOperatorASTNode(dynamic_cast<SymbolASTNode*>($3)); 930 $$->setLocation(@1, @4); 931 } 932 | "sizeof" '(' TOK_IDENT ')' 933 { 934 $$ = new SizeofOperatorASTNode($3); 935 $$->setLocation(@1, @4); 936 } 937 | "sizeof" '(' TOK_SOURCE_NAME ')' 938 { 939 $$ = new SizeofOperatorASTNode($3); 940 $$->setLocation(@1, @4); 941 } 942 ; 943 944 unary_expr : '+' expr %prec UNARY_OP 945 { 946 $$ = $2; 947 } 948 | '-' expr %prec UNARY_OP 949 { 950 $$ = new NegativeExprASTNode(dynamic_cast<ExprASTNode*>($2)); 951 $$->setLocation(@1, @2); 952 } 953 ; 954 955 int_value : TOK_INT_LITERAL 956 { 957 $$ = new IntConstExprASTNode($1->getValue(), $1->getWordSize()); 958 $$->setLocation(@1); 959 } 960 ; 961 962 %% 963 964 /* code goes here */ 965 966 static int yylex(YYSTYPE * lvalp, YYLTYPE * yylloc, ElftosbLexer * lexer) 967 { 968 int token = lexer->yylex(); 969 *yylloc = lexer->getLocation(); 970 lexer->getSymbolValue(lvalp); 971 return token; 972 } 973 974 static void yyerror(YYLTYPE * yylloc, ElftosbLexer * lexer, CommandFileASTNode ** resultAST, const char * error) 975 { 976 throw syntax_error(format_string("line %d: %s\n", yylloc->m_firstLine, error)); 977 } 978 979