xref: /netbsd-src/external/bsd/elftosb/dist/elftosb2/elftosb_parser.y (revision 993229b6fea628ff8b1fa09146c80b0cfb2768eb)
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 
yyerror(YYLTYPE * yylloc,ElftosbLexer * lexer,CommandFileASTNode ** resultAST,const char * error)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