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