Home | History | Annotate | Line # | Download | only in elftosb2
      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