2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 * The Verilog frontend.
22 * This frontend is using the AST frontend library (see frontends/ast/).
23 * Thus this frontend does not generate RTLIL code directly but creates an
24 * AST directly from the Verilog parse tree and then passes this AST to
25 * the AST frontend library.
29 * This is the actual bison parser for Verilog code. The AST ist created directly
30 * from the bison reduce functions here. Note that this code uses a few global
31 * variables to hold the state of the AST generator and therefore this parser is
39 #include "frontends/verilog/verilog_frontend.h"
40 #include "kernel/log.h"
44 using namespace VERILOG_FRONTEND;
47 namespace VERILOG_FRONTEND {
49 std::map<std::string, int> port_stubs;
50 std::map<std::string, AstNode*> attr_list, default_attr_list;
51 std::map<std::string, AstNode*> *albuf;
52 std::vector<AstNode*> ast_stack;
53 struct AstNode *astbuf1, *astbuf2, *astbuf3;
54 struct AstNode *current_function_or_task;
55 struct AstNode *current_ast, *current_ast_mod;
56 int current_function_or_task_port_id;
57 std::vector<char> case_type_stack;
58 bool do_not_require_port_stubs;
59 bool default_nettype_wire;
60 bool sv_mode, formal_mode, lib_mode;
61 bool norestrict_mode, assume_asserts_mode;
62 bool current_wire_rand, current_wire_const;
67 static void append_attr(AstNode *ast, std::map<std::string, AstNode*> *al)
69 for (auto &it : *al) {
70 if (ast->attributes.count(it.first) > 0)
71 delete ast->attributes[it.first];
72 ast->attributes[it.first] = it.second;
77 static void append_attr_clone(AstNode *ast, std::map<std::string, AstNode*> *al)
79 for (auto &it : *al) {
80 if (ast->attributes.count(it.first) > 0)
81 delete ast->attributes[it.first];
82 ast->attributes[it.first] = it.second->clone();
86 static void free_attr(std::map<std::string, AstNode*> *al)
95 %name-prefix "frontend_verilog_yy"
99 struct YOSYS_NAMESPACE_PREFIX AST::AstNode *ast;
100 std::map<std::string, YOSYS_NAMESPACE_PREFIX AST::AstNode*> *al;
104 %token <string> TOK_STRING TOK_ID TOK_CONSTVAL TOK_REALVAL TOK_PRIMITIVE
105 %token ATTR_BEGIN ATTR_END DEFATTR_BEGIN DEFATTR_END
106 %token TOK_MODULE TOK_ENDMODULE TOK_PARAMETER TOK_LOCALPARAM TOK_DEFPARAM
107 %token TOK_PACKAGE TOK_ENDPACKAGE TOK_PACKAGESEP
108 %token TOK_INPUT TOK_OUTPUT TOK_INOUT TOK_WIRE TOK_REG
109 %token TOK_INTEGER TOK_SIGNED TOK_ASSIGN TOK_ALWAYS TOK_INITIAL
110 %token TOK_BEGIN TOK_END TOK_IF TOK_ELSE TOK_FOR TOK_WHILE TOK_REPEAT
111 %token TOK_DPI_FUNCTION TOK_POSEDGE TOK_NEGEDGE TOK_OR
112 %token TOK_CASE TOK_CASEX TOK_CASEZ TOK_ENDCASE TOK_DEFAULT
113 %token TOK_FUNCTION TOK_ENDFUNCTION TOK_TASK TOK_ENDTASK
114 %token TOK_GENERATE TOK_ENDGENERATE TOK_GENVAR TOK_REAL
115 %token TOK_SYNOPSYS_FULL_CASE TOK_SYNOPSYS_PARALLEL_CASE
116 %token TOK_SUPPLY0 TOK_SUPPLY1 TOK_TO_SIGNED TOK_TO_UNSIGNED
117 %token TOK_POS_INDEXED TOK_NEG_INDEXED TOK_ASSERT TOK_ASSUME
118 %token TOK_RESTRICT TOK_COVER TOK_PROPERTY TOK_ENUM TOK_TYPEDEF
119 %token TOK_RAND TOK_CONST TOK_CHECKER TOK_ENDCHECKER TOK_EVENTUALLY
120 %token TOK_INCREMENT TOK_DECREMENT TOK_UNIQUE TOK_PRIORITY
122 %type <ast> range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int
123 %type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list
124 %type <string> opt_label tok_prim_wrapper hierarchical_id
125 %type <boolean> opt_signed unique_case_attr
126 %type <al> attr case_attr
128 // operator precedence from low to high
134 %left OP_EQ OP_NE OP_EQX OP_NEX
135 %left '<' OP_LE OP_GE '>'
136 %left OP_SHL OP_SHR OP_SSHL OP_SSHR
142 %define parse.error verbose
143 %define parse.lac full
152 ast_stack.push_back(current_ast);
154 ast_stack.pop_back();
155 log_assert(GetSize(ast_stack) == 0);
156 for (auto &it : default_attr_list)
158 default_attr_list.clear();
164 task_func_decl design |
166 localparam_decl design |
172 for (auto &it : attr_list)
175 for (auto &it : default_attr_list)
176 attr_list[it.first] = it.second->clone();
178 std::map<std::string, AstNode*> *al = new std::map<std::string, AstNode*>;
184 attr_opt ATTR_BEGIN opt_attr_list ATTR_END |
189 for (auto &it : default_attr_list)
191 default_attr_list.clear();
192 for (auto &it : attr_list)
196 default_attr_list = attr_list;
201 attr_list | /* empty */;
205 attr_list ',' attr_assign;
209 if (attr_list.count(*$1) != 0)
210 delete attr_list[*$1];
211 attr_list[*$1] = AstNode::mkconst_int(1, false);
214 hierarchical_id '=' expr {
215 if (attr_list.count(*$1) != 0)
216 delete attr_list[*$1];
225 hierarchical_id TOK_PACKAGESEP TOK_ID {
226 if ($3->substr(0, 1) == "\\")
227 *$1 += "::" + $3->substr(1);
233 hierarchical_id '.' TOK_ID {
234 if ($3->substr(0, 1) == "\\")
235 *$1 += "." + $3->substr(1);
243 attr TOK_MODULE TOK_ID {
244 do_not_require_port_stubs = false;
245 AstNode *mod = new AstNode(AST_MODULE);
246 ast_stack.back()->children.push_back(mod);
247 ast_stack.push_back(mod);
248 current_ast_mod = mod;
252 append_attr(mod, $1);
254 } module_para_opt module_args_opt ';' module_body TOK_ENDMODULE {
255 if (port_stubs.size() != 0)
256 frontend_verilog_yyerror("Missing details for module port `%s'.",
257 port_stubs.begin()->first.c_str());
258 ast_stack.pop_back();
259 log_assert(ast_stack.size() == 1);
260 current_ast_mod = NULL;
264 '#' '(' { astbuf1 = nullptr; } module_para_list { if (astbuf1) delete astbuf1; } ')' | /* empty */;
267 single_module_para | module_para_list ',' single_module_para;
272 if (astbuf1) delete astbuf1;
273 astbuf1 = new AstNode(AST_PARAMETER);
274 astbuf1->children.push_back(AstNode::mkconst_int(0, true));
275 } param_signed param_integer param_range single_param_decl |
277 if (astbuf1) delete astbuf1;
278 astbuf1 = new AstNode(AST_LOCALPARAM);
279 astbuf1->children.push_back(AstNode::mkconst_int(0, true));
280 } param_signed param_integer param_range single_param_decl |
284 '(' ')' | /* empty */ | '(' module_args optional_comma ')';
287 module_arg | module_args ',' module_arg;
292 module_arg_opt_assignment:
294 if (ast_stack.back()->children.size() > 0 && ast_stack.back()->children.back()->type == AST_WIRE) {
295 AstNode *wire = new AstNode(AST_IDENTIFIER);
296 wire->str = ast_stack.back()->children.back()->str;
297 if (ast_stack.back()->children.back()->is_reg)
298 ast_stack.back()->children.push_back(new AstNode(AST_INITIAL, new AstNode(AST_BLOCK, new AstNode(AST_ASSIGN_LE, wire, $2))));
300 ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, wire, $2));
302 frontend_verilog_yyerror("Syntax error.");
308 if (ast_stack.back()->children.size() > 0 && ast_stack.back()->children.back()->type == AST_WIRE) {
309 AstNode *node = ast_stack.back()->children.back()->clone();
311 node->port_id = ++port_counter;
312 ast_stack.back()->children.push_back(node);
314 if (port_stubs.count(*$1) != 0)
315 frontend_verilog_yyerror("Duplicate module port `%s'.", $1->c_str());
316 port_stubs[*$1] = ++port_counter;
319 } module_arg_opt_assignment |
320 attr wire_type range TOK_ID {
323 node->port_id = ++port_counter;
325 node->children.push_back($3);
326 if (!node->is_input && !node->is_output)
327 frontend_verilog_yyerror("Module port `%s' is neither input nor output.", $4->c_str());
328 if (node->is_reg && node->is_input && !node->is_output && !sv_mode)
329 frontend_verilog_yyerror("Input port `%s' is declared as register.", $4->c_str());
330 ast_stack.back()->children.push_back(node);
331 append_attr(node, $1);
333 } module_arg_opt_assignment |
335 do_not_require_port_stubs = true;
339 attr TOK_PACKAGE TOK_ID {
340 AstNode *mod = new AstNode(AST_PACKAGE);
341 ast_stack.back()->children.push_back(mod);
342 ast_stack.push_back(mod);
343 current_ast_mod = mod;
345 append_attr(mod, $1);
346 } ';' package_body TOK_ENDPACKAGE {
347 ast_stack.pop_back();
348 current_ast_mod = NULL;
352 package_body package_body_stmt |;
358 '#' TOK_ID { delete $2; } |
359 '#' TOK_CONSTVAL { delete $2; } |
360 '#' '(' expr ')' { delete $3; } |
361 '#' '(' expr ':' expr ':' expr ')' { delete $3; delete $5; delete $7; };
364 non_opt_delay | /* empty */;
368 astbuf3 = new AstNode(AST_WIRE);
369 current_wire_rand = false;
370 current_wire_const = false;
371 } wire_type_token_list delay {
375 wire_type_token_list:
376 wire_type_token | wire_type_token_list wire_type_token;
380 astbuf3->is_input = true;
383 astbuf3->is_output = true;
386 astbuf3->is_input = true;
387 astbuf3->is_output = true;
392 astbuf3->is_reg = true;
395 astbuf3->is_reg = true;
396 astbuf3->range_left = 31;
397 astbuf3->range_right = 0;
398 astbuf3->is_signed = true;
401 astbuf3->type = AST_GENVAR;
402 astbuf3->is_reg = true;
403 astbuf3->range_left = 31;
404 astbuf3->range_right = 0;
407 astbuf3->is_signed = true;
410 current_wire_rand = true;
413 current_wire_const = true;
417 '[' expr ':' expr ']' {
418 $$ = new AstNode(AST_RANGE);
419 $$->children.push_back($2);
420 $$->children.push_back($4);
422 '[' expr TOK_POS_INDEXED expr ']' {
423 $$ = new AstNode(AST_RANGE);
424 $$->children.push_back(new AstNode(AST_SUB, new AstNode(AST_ADD, $2->clone(), $4), AstNode::mkconst_int(1, true)));
425 $$->children.push_back(new AstNode(AST_ADD, $2, AstNode::mkconst_int(0, true)));
427 '[' expr TOK_NEG_INDEXED expr ']' {
428 $$ = new AstNode(AST_RANGE);
429 $$->children.push_back(new AstNode(AST_ADD, $2, AstNode::mkconst_int(0, true)));
430 $$->children.push_back(new AstNode(AST_SUB, new AstNode(AST_ADD, $2->clone(), AstNode::mkconst_int(1, true)), $4));
433 $$ = new AstNode(AST_RANGE);
434 $$->children.push_back($2);
438 non_opt_range non_opt_range {
439 $$ = new AstNode(AST_MULTIRANGE, $1, $2);
441 non_opt_multirange non_opt_range {
443 $$->children.push_back($2);
456 non_opt_multirange { $$ = $1; };
463 $$ = new AstNode(AST_RANGE);
464 $$->children.push_back(AstNode::mkconst_int(31, true));
465 $$->children.push_back(AstNode::mkconst_int(0, true));
466 $$->is_signed = true;
470 module_body module_body_stmt |
471 /* the following line makes the generate..endgenrate keywords optional */
472 module_body gen_stmt |
476 task_func_decl | param_decl | localparam_decl | defparam_decl | wire_decl | assign_stmt | cell_stmt |
477 always_stmt | TOK_GENERATE module_gen_body TOK_ENDGENERATE | defattr | assert_property | checker_decl;
480 TOK_CHECKER TOK_ID ';' {
481 AstNode *node = new AstNode(AST_GENBLOCK);
483 ast_stack.back()->children.push_back(node);
484 ast_stack.push_back(node);
485 } module_body TOK_ENDCHECKER {
487 ast_stack.pop_back();
491 attr TOK_DPI_FUNCTION TOK_ID TOK_ID {
492 current_function_or_task = new AstNode(AST_DPI_FUNCTION, AstNode::mkconst_str(*$3), AstNode::mkconst_str(*$4));
493 current_function_or_task->str = *$4;
494 append_attr(current_function_or_task, $1);
495 ast_stack.back()->children.push_back(current_function_or_task);
498 } opt_dpi_function_args ';' {
499 current_function_or_task = NULL;
501 attr TOK_DPI_FUNCTION TOK_ID '=' TOK_ID TOK_ID {
502 current_function_or_task = new AstNode(AST_DPI_FUNCTION, AstNode::mkconst_str(*$5), AstNode::mkconst_str(*$3));
503 current_function_or_task->str = *$6;
504 append_attr(current_function_or_task, $1);
505 ast_stack.back()->children.push_back(current_function_or_task);
509 } opt_dpi_function_args ';' {
510 current_function_or_task = NULL;
512 attr TOK_DPI_FUNCTION TOK_ID ':' TOK_ID '=' TOK_ID TOK_ID {
513 current_function_or_task = new AstNode(AST_DPI_FUNCTION, AstNode::mkconst_str(*$7), AstNode::mkconst_str(*$3 + ":" + RTLIL::unescape_id(*$5)));
514 current_function_or_task->str = *$8;
515 append_attr(current_function_or_task, $1);
516 ast_stack.back()->children.push_back(current_function_or_task);
521 } opt_dpi_function_args ';' {
522 current_function_or_task = NULL;
524 attr TOK_TASK TOK_ID {
525 current_function_or_task = new AstNode(AST_TASK);
526 current_function_or_task->str = *$3;
527 append_attr(current_function_or_task, $1);
528 ast_stack.back()->children.push_back(current_function_or_task);
529 ast_stack.push_back(current_function_or_task);
530 current_function_or_task_port_id = 1;
532 } task_func_args_opt ';' task_func_body TOK_ENDTASK {
533 current_function_or_task = NULL;
534 ast_stack.pop_back();
536 attr TOK_FUNCTION opt_signed range_or_signed_int TOK_ID {
537 current_function_or_task = new AstNode(AST_FUNCTION);
538 current_function_or_task->str = *$5;
539 append_attr(current_function_or_task, $1);
540 ast_stack.back()->children.push_back(current_function_or_task);
541 ast_stack.push_back(current_function_or_task);
542 AstNode *outreg = new AstNode(AST_WIRE);
544 outreg->is_signed = $3;
546 outreg->children.push_back($4);
547 outreg->is_signed = $3 || $4->is_signed;
548 $4->is_signed = false;
550 current_function_or_task->children.push_back(outreg);
551 current_function_or_task_port_id = 1;
553 } task_func_args_opt ';' task_func_body TOK_ENDFUNCTION {
554 current_function_or_task = NULL;
555 ast_stack.pop_back();
560 current_function_or_task->children.push_back(AstNode::mkconst_str(*$1));
565 current_function_or_task->children.push_back(AstNode::mkconst_str(*$1));
569 opt_dpi_function_args:
570 '(' dpi_function_args ')' |
574 dpi_function_args ',' dpi_function_arg |
575 dpi_function_args ',' |
588 '(' ')' | /* empty */ | '(' {
592 } task_func_args optional_comma {
600 task_func_port | task_func_args ',' task_func_port;
603 attr wire_type range {
613 if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) {
615 frontend_verilog_yyerror("Syntax error.");
617 astbuf2 = new AstNode(AST_RANGE);
618 astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_left, true));
619 astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_right, true));
622 if (astbuf2 && astbuf2->children.size() != 2)
623 frontend_verilog_yyerror("Syntax error.");
624 } wire_name | wire_name;
627 task_func_body behavioral_stmt |
632 astbuf1->is_signed = true;
637 if (astbuf1->children.size() != 1)
638 frontend_verilog_yyerror("Syntax error.");
639 astbuf1->children.push_back(new AstNode(AST_RANGE));
640 astbuf1->children.back()->children.push_back(AstNode::mkconst_int(31, true));
641 astbuf1->children.back()->children.push_back(AstNode::mkconst_int(0, true));
642 astbuf1->is_signed = true;
647 if (astbuf1->children.size() != 1)
648 frontend_verilog_yyerror("Syntax error.");
649 astbuf1->children.push_back(new AstNode(AST_REALVALUE));
655 if (astbuf1->children.size() != 1)
656 frontend_verilog_yyerror("Syntax error.");
657 astbuf1->children.push_back($1);
663 astbuf1 = new AstNode(AST_PARAMETER);
664 astbuf1->children.push_back(AstNode::mkconst_int(0, true));
665 } param_signed param_integer param_real param_range param_decl_list ';' {
671 astbuf1 = new AstNode(AST_LOCALPARAM);
672 astbuf1->children.push_back(AstNode::mkconst_int(0, true));
673 } param_signed param_integer param_real param_range param_decl_list ';' {
678 single_param_decl | param_decl_list ',' single_param_decl;
682 if (astbuf1 == nullptr)
683 frontend_verilog_yyerror("syntax error");
684 AstNode *node = astbuf1->clone();
686 delete node->children[0];
687 node->children[0] = $3;
688 ast_stack.back()->children.push_back(node);
693 TOK_DEFPARAM defparam_decl_list ';';
696 single_defparam_decl | defparam_decl_list ',' single_defparam_decl;
698 single_defparam_decl:
699 range rvalue '=' expr {
700 AstNode *node = new AstNode(AST_DEFPARAM);
701 node->children.push_back($2);
702 node->children.push_back($4);
704 node->children.push_back($1);
705 ast_stack.back()->children.push_back(node);
709 attr wire_type range {
713 if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) {
715 frontend_verilog_yyerror("Syntax error.");
717 astbuf2 = new AstNode(AST_RANGE);
718 astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_left, true));
719 astbuf2->children.push_back(AstNode::mkconst_int(astbuf1->range_right, true));
722 if (astbuf2 && astbuf2->children.size() != 2)
723 frontend_verilog_yyerror("Syntax error.");
730 attr TOK_SUPPLY0 TOK_ID {
731 ast_stack.back()->children.push_back(new AstNode(AST_WIRE));
732 ast_stack.back()->children.back()->str = *$3;
733 append_attr(ast_stack.back()->children.back(), $1);
734 ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, new AstNode(AST_IDENTIFIER), AstNode::mkconst_int(0, false, 1)));
735 ast_stack.back()->children.back()->children[0]->str = *$3;
737 } opt_supply_wires ';' |
738 attr TOK_SUPPLY1 TOK_ID {
739 ast_stack.back()->children.push_back(new AstNode(AST_WIRE));
740 ast_stack.back()->children.back()->str = *$3;
741 append_attr(ast_stack.back()->children.back(), $1);
742 ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, new AstNode(AST_IDENTIFIER), AstNode::mkconst_int(1, false, 1)));
743 ast_stack.back()->children.back()->children[0]->str = *$3;
745 } opt_supply_wires ';';
749 opt_supply_wires ',' TOK_ID {
750 AstNode *wire_node = ast_stack.back()->children.at(GetSize(ast_stack.back()->children)-2)->clone();
751 AstNode *assign_node = ast_stack.back()->children.at(GetSize(ast_stack.back()->children)-1)->clone();
752 wire_node->str = *$3;
753 assign_node->children[0]->str = *$3;
754 ast_stack.back()->children.push_back(wire_node);
755 ast_stack.back()->children.push_back(assign_node);
760 wire_name_and_opt_assign | wire_name_list ',' wire_name_and_opt_assign;
762 wire_name_and_opt_assign:
764 if (current_wire_rand) {
765 AstNode *wire = new AstNode(AST_IDENTIFIER);
766 AstNode *fcall = new AstNode(AST_FCALL);
767 wire->str = ast_stack.back()->children.back()->str;
768 fcall->str = current_wire_const ? "\\$anyconst" : "\\$anyseq";
769 fcall->attributes["\\reg"] = AstNode::mkconst_str(RTLIL::unescape_id(wire->str));
770 ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, wire, fcall));
774 AstNode *wire = new AstNode(AST_IDENTIFIER);
775 wire->str = ast_stack.back()->children.back()->str;
777 ast_stack.back()->children.push_back(new AstNode(AST_INITIAL, new AstNode(AST_BLOCK, new AstNode(AST_ASSIGN_LE, wire, $3))));
779 ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, wire, $3));
783 TOK_ID range_or_multirange {
784 if (astbuf1 == nullptr)
785 frontend_verilog_yyerror("Syntax error.");
786 AstNode *node = astbuf1->clone();
788 append_attr_clone(node, albuf);
790 node->children.push_back(astbuf2->clone());
792 if (node->is_input || node->is_output)
793 frontend_verilog_yyerror("Syntax error.");
795 AstNode *rng = new AstNode(AST_RANGE);
796 rng->children.push_back(AstNode::mkconst_int(0, true));
797 rng->children.push_back(AstNode::mkconst_int(0, true));
798 node->children.push_back(rng);
800 node->type = AST_MEMORY;
801 node->children.push_back($2);
803 if (current_function_or_task == NULL) {
804 if (do_not_require_port_stubs && (node->is_input || node->is_output) && port_stubs.count(*$1) == 0) {
805 port_stubs[*$1] = ++port_counter;
807 if (port_stubs.count(*$1) != 0) {
808 if (!node->is_input && !node->is_output)
809 frontend_verilog_yyerror("Module port `%s' is neither input nor output.", $1->c_str());
810 if (node->is_reg && node->is_input && !node->is_output && !sv_mode)
811 frontend_verilog_yyerror("Input port `%s' is declared as register.", $1->c_str());
812 node->port_id = port_stubs[*$1];
813 port_stubs.erase(*$1);
815 if (node->is_input || node->is_output)
816 frontend_verilog_yyerror("Module port `%s' is not declared in module header.", $1->c_str());
819 if (node->is_input || node->is_output)
820 node->port_id = current_function_or_task_port_id++;
822 ast_stack.back()->children.push_back(node);
827 TOK_ASSIGN delay assign_expr_list ';';
830 assign_expr | assign_expr_list ',' assign_expr;
834 ast_stack.back()->children.push_back(new AstNode(AST_ASSIGN, $1, $3));
839 astbuf1 = new AstNode(AST_CELL);
840 append_attr(astbuf1, $1);
841 astbuf1->children.push_back(new AstNode(AST_CELLTYPE));
842 astbuf1->children[0]->str = *$2;
844 } cell_parameter_list_opt cell_list ';' {
847 attr tok_prim_wrapper delay {
848 astbuf1 = new AstNode(AST_PRIMITIVE);
850 append_attr(astbuf1, $1);
861 $$ = new std::string("or");
866 cell_list ',' single_cell;
870 astbuf2 = astbuf1->clone();
871 if (astbuf2->type != AST_PRIMITIVE)
874 ast_stack.back()->children.push_back(astbuf2);
875 } '(' cell_port_list ')' |
876 TOK_ID non_opt_range {
877 astbuf2 = astbuf1->clone();
878 if (astbuf2->type != AST_PRIMITIVE)
881 ast_stack.back()->children.push_back(new AstNode(AST_CELLARRAY, $2, astbuf2));
882 } '(' cell_port_list ')';
886 prim_list ',' single_prim;
891 astbuf2 = astbuf1->clone();
892 ast_stack.back()->children.push_back(astbuf2);
893 } '(' cell_port_list ')';
895 cell_parameter_list_opt:
896 '#' '(' cell_parameter_list ')' | /* empty */;
899 cell_parameter | cell_parameter_list ',' cell_parameter;
904 AstNode *node = new AstNode(AST_PARASET);
905 astbuf1->children.push_back(node);
906 node->children.push_back($1);
908 '.' TOK_ID '(' expr ')' {
909 AstNode *node = new AstNode(AST_PARASET);
911 astbuf1->children.push_back(node);
912 node->children.push_back($4);
917 cell_port_list_rules {
918 // remove empty args from end of list
919 while (!astbuf2->children.empty()) {
920 AstNode *node = astbuf2->children.back();
921 if (node->type != AST_ARGUMENT) break;
922 if (!node->children.empty()) break;
923 if (!node->str.empty()) break;
924 astbuf2->children.pop_back();
929 bool has_positional_args = false;
930 bool has_named_args = false;
931 for (auto node : astbuf2->children) {
932 if (node->type != AST_ARGUMENT) continue;
933 if (node->str.empty())
934 has_positional_args = true;
936 has_named_args = true;
939 if (has_positional_args && has_named_args)
940 frontend_verilog_yyerror("Mix of positional and named cell ports.");
943 cell_port_list_rules:
944 cell_port | cell_port_list_rules ',' cell_port;
948 AstNode *node = new AstNode(AST_ARGUMENT);
949 astbuf2->children.push_back(node);
952 AstNode *node = new AstNode(AST_ARGUMENT);
953 astbuf2->children.push_back(node);
954 node->children.push_back($1);
956 '.' TOK_ID '(' expr ')' {
957 AstNode *node = new AstNode(AST_ARGUMENT);
959 astbuf2->children.push_back(node);
960 node->children.push_back($4);
964 AstNode *node = new AstNode(AST_ARGUMENT);
966 astbuf2->children.push_back(node);
972 AstNode *node = new AstNode(AST_ALWAYS);
973 append_attr(node, $1);
974 ast_stack.back()->children.push_back(node);
975 ast_stack.push_back(node);
977 AstNode *block = new AstNode(AST_BLOCK);
978 ast_stack.back()->children.push_back(block);
979 ast_stack.push_back(block);
981 ast_stack.pop_back();
982 ast_stack.pop_back();
985 AstNode *node = new AstNode(AST_INITIAL);
986 append_attr(node, $1);
987 ast_stack.back()->children.push_back(node);
988 ast_stack.push_back(node);
989 AstNode *block = new AstNode(AST_BLOCK);
990 ast_stack.back()->children.push_back(block);
991 ast_stack.push_back(block);
993 ast_stack.pop_back();
994 ast_stack.pop_back();
998 '@' '(' always_events ')' |
1000 '@' ATTR_BEGIN ')' |
1007 always_events TOK_OR always_event |
1008 always_events ',' always_event;
1012 AstNode *node = new AstNode(AST_POSEDGE);
1013 ast_stack.back()->children.push_back(node);
1014 node->children.push_back($2);
1017 AstNode *node = new AstNode(AST_NEGEDGE);
1018 ast_stack.back()->children.push_back(node);
1019 node->children.push_back($2);
1022 AstNode *node = new AstNode(AST_EDGE);
1023 ast_stack.back()->children.push_back(node);
1024 node->children.push_back($1);
1036 TOK_ASSERT '(' expr ')' ';' {
1037 ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $3));
1039 TOK_ASSUME '(' expr ')' ';' {
1040 ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $3));
1042 TOK_ASSERT '(' TOK_EVENTUALLY expr ')' ';' {
1043 ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $4));
1045 TOK_ASSUME '(' TOK_EVENTUALLY expr ')' ';' {
1046 ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $4));
1048 TOK_COVER '(' expr ')' ';' {
1049 ast_stack.back()->children.push_back(new AstNode(AST_COVER, $3));
1051 TOK_COVER '(' ')' ';' {
1052 ast_stack.back()->children.push_back(new AstNode(AST_COVER, AstNode::mkconst_int(1, false)));
1055 ast_stack.back()->children.push_back(new AstNode(AST_COVER, AstNode::mkconst_int(1, false)));
1057 TOK_RESTRICT '(' expr ')' ';' {
1058 if (norestrict_mode)
1061 ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $3));
1063 TOK_RESTRICT '(' TOK_EVENTUALLY expr ')' ';' {
1064 if (norestrict_mode)
1067 ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $4));
1071 TOK_ASSERT TOK_PROPERTY '(' expr ')' ';' {
1072 ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_ASSUME : AST_ASSERT, $4));
1074 TOK_ASSUME TOK_PROPERTY '(' expr ')' ';' {
1075 ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $4));
1077 TOK_ASSERT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' {
1078 ast_stack.back()->children.push_back(new AstNode(assume_asserts_mode ? AST_FAIR : AST_LIVE, $5));
1080 TOK_ASSUME TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' {
1081 ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $5));
1083 TOK_COVER TOK_PROPERTY '(' expr ')' ';' {
1084 ast_stack.back()->children.push_back(new AstNode(AST_COVER, $4));
1086 TOK_RESTRICT TOK_PROPERTY '(' expr ')' ';' {
1087 if (norestrict_mode)
1090 ast_stack.back()->children.push_back(new AstNode(AST_ASSUME, $4));
1092 TOK_RESTRICT TOK_PROPERTY '(' TOK_EVENTUALLY expr ')' ';' {
1093 if (norestrict_mode)
1096 ast_stack.back()->children.push_back(new AstNode(AST_FAIR, $5));
1099 simple_behavioral_stmt:
1100 lvalue '=' delay expr {
1101 AstNode *node = new AstNode(AST_ASSIGN_EQ, $1, $4);
1102 ast_stack.back()->children.push_back(node);
1104 lvalue TOK_INCREMENT {
1105 AstNode *node = new AstNode(AST_ASSIGN_EQ, $1, new AstNode(AST_ADD, $1->clone(), AstNode::mkconst_int(1, true)));
1106 ast_stack.back()->children.push_back(node);
1108 lvalue TOK_DECREMENT {
1109 AstNode *node = new AstNode(AST_ASSIGN_EQ, $1, new AstNode(AST_SUB, $1->clone(), AstNode::mkconst_int(1, true)));
1110 ast_stack.back()->children.push_back(node);
1112 lvalue OP_LE delay expr {
1113 AstNode *node = new AstNode(AST_ASSIGN_LE, $1, $4);
1114 ast_stack.back()->children.push_back(node);
1117 // this production creates the obligatory if-else shift/reduce conflict
1119 defattr | assert | wire_decl | param_decl | localparam_decl |
1120 non_opt_delay behavioral_stmt |
1121 simple_behavioral_stmt ';' | ';' |
1122 hierarchical_id attr {
1123 AstNode *node = new AstNode(AST_TCALL);
1126 ast_stack.back()->children.push_back(node);
1127 ast_stack.push_back(node);
1128 append_attr(node, $2);
1130 ast_stack.pop_back();
1132 attr TOK_BEGIN opt_label {
1133 AstNode *node = new AstNode(AST_BLOCK);
1134 ast_stack.back()->children.push_back(node);
1135 ast_stack.push_back(node);
1136 append_attr(node, $1);
1139 } behavioral_stmt_list TOK_END opt_label {
1140 if ($3 != NULL && $7 != NULL && *$3 != *$7)
1141 frontend_verilog_yyerror("Syntax error.");
1146 ast_stack.pop_back();
1149 AstNode *node = new AstNode(AST_FOR);
1150 ast_stack.back()->children.push_back(node);
1151 ast_stack.push_back(node);
1152 append_attr(node, $1);
1153 } simple_behavioral_stmt ';' expr {
1154 ast_stack.back()->children.push_back($7);
1155 } ';' simple_behavioral_stmt ')' {
1156 AstNode *block = new AstNode(AST_BLOCK);
1157 ast_stack.back()->children.push_back(block);
1158 ast_stack.push_back(block);
1160 ast_stack.pop_back();
1161 ast_stack.pop_back();
1163 attr TOK_WHILE '(' expr ')' {
1164 AstNode *node = new AstNode(AST_WHILE);
1165 ast_stack.back()->children.push_back(node);
1166 ast_stack.push_back(node);
1167 append_attr(node, $1);
1168 AstNode *block = new AstNode(AST_BLOCK);
1169 ast_stack.back()->children.push_back($4);
1170 ast_stack.back()->children.push_back(block);
1171 ast_stack.push_back(block);
1173 ast_stack.pop_back();
1174 ast_stack.pop_back();
1176 attr TOK_REPEAT '(' expr ')' {
1177 AstNode *node = new AstNode(AST_REPEAT);
1178 ast_stack.back()->children.push_back(node);
1179 ast_stack.push_back(node);
1180 append_attr(node, $1);
1181 AstNode *block = new AstNode(AST_BLOCK);
1182 ast_stack.back()->children.push_back($4);
1183 ast_stack.back()->children.push_back(block);
1184 ast_stack.push_back(block);
1186 ast_stack.pop_back();
1187 ast_stack.pop_back();
1189 attr TOK_IF '(' expr ')' {
1190 AstNode *node = new AstNode(AST_CASE);
1191 AstNode *block = new AstNode(AST_BLOCK);
1192 AstNode *cond = new AstNode(AST_COND, AstNode::mkconst_int(1, false, 1), block);
1193 ast_stack.back()->children.push_back(node);
1194 node->children.push_back(new AstNode(AST_REDUCE_BOOL, $4));
1195 node->children.push_back(cond);
1196 ast_stack.push_back(node);
1197 ast_stack.push_back(block);
1198 append_attr(node, $1);
1199 } behavioral_stmt optional_else {
1200 ast_stack.pop_back();
1201 ast_stack.pop_back();
1203 case_attr case_type '(' expr ')' {
1204 AstNode *node = new AstNode(AST_CASE, $4);
1205 ast_stack.back()->children.push_back(node);
1206 ast_stack.push_back(node);
1207 append_attr(node, $1);
1208 } opt_synopsys_attr case_body TOK_ENDCASE {
1209 case_type_stack.pop_back();
1210 ast_stack.pop_back();
1217 TOK_PRIORITY case_attr {
1220 TOK_UNIQUE case_attr {
1225 attr unique_case_attr {
1226 if ($2) (*$1)["\\parallel_case"] = AstNode::mkconst_int(1, false);
1232 case_type_stack.push_back(0);
1235 case_type_stack.push_back('x');
1238 case_type_stack.push_back('z');
1242 opt_synopsys_attr TOK_SYNOPSYS_FULL_CASE {
1243 if (ast_stack.back()->attributes.count("\\full_case") == 0)
1244 ast_stack.back()->attributes["\\full_case"] = AstNode::mkconst_int(1, false);
1246 opt_synopsys_attr TOK_SYNOPSYS_PARALLEL_CASE {
1247 if (ast_stack.back()->attributes.count("\\parallel_case") == 0)
1248 ast_stack.back()->attributes["\\parallel_case"] = AstNode::mkconst_int(1, false);
1252 behavioral_stmt_list:
1253 behavioral_stmt_list behavioral_stmt |
1258 AstNode *block = new AstNode(AST_BLOCK);
1259 AstNode *cond = new AstNode(AST_COND, new AstNode(AST_DEFAULT), block);
1260 ast_stack.pop_back();
1261 ast_stack.back()->children.push_back(cond);
1262 ast_stack.push_back(block);
1267 case_body case_item |
1272 AstNode *node = new AstNode(
1273 case_type_stack.size() && case_type_stack.back() == 'x' ? AST_CONDX :
1274 case_type_stack.size() && case_type_stack.back() == 'z' ? AST_CONDZ : AST_COND);
1275 ast_stack.back()->children.push_back(node);
1276 ast_stack.push_back(node);
1278 AstNode *block = new AstNode(AST_BLOCK);
1279 ast_stack.back()->children.push_back(block);
1280 ast_stack.push_back(block);
1281 case_type_stack.push_back(0);
1283 case_type_stack.pop_back();
1284 ast_stack.pop_back();
1285 ast_stack.pop_back();
1289 gen_case_body gen_case_item |
1294 AstNode *node = new AstNode(
1295 case_type_stack.size() && case_type_stack.back() == 'x' ? AST_CONDX :
1296 case_type_stack.size() && case_type_stack.back() == 'z' ? AST_CONDZ : AST_COND);
1297 ast_stack.back()->children.push_back(node);
1298 ast_stack.push_back(node);
1300 case_type_stack.push_back(0);
1301 } gen_stmt_or_null {
1302 case_type_stack.pop_back();
1303 ast_stack.pop_back();
1307 case_expr_list ':' |
1312 ast_stack.back()->children.push_back(new AstNode(AST_DEFAULT));
1315 ast_stack.back()->children.push_back($1);
1317 case_expr_list ',' expr {
1318 ast_stack.back()->children.push_back($3);
1322 hierarchical_id '[' expr ']' '.' rvalue {
1323 $$ = new AstNode(AST_PREFIX, $3, $6);
1327 hierarchical_id range {
1328 $$ = new AstNode(AST_IDENTIFIER, $2);
1331 if ($2 == nullptr && ($$->str == "\\$initstate" || $$->str == "\\$anyconst" || $$->str == "\\$anyseq"))
1332 $$->type = AST_FCALL;
1334 hierarchical_id non_opt_multirange {
1335 $$ = new AstNode(AST_IDENTIFIER, $2);
1344 '{' lvalue_concat_list '}' {
1350 $$ = new AstNode(AST_CONCAT);
1351 $$->children.push_back($1);
1353 expr ',' lvalue_concat_list {
1355 $$->children.push_back($1);
1359 '(' arg_list optional_comma ')' |
1368 arg_list ',' single_arg;
1372 ast_stack.back()->children.push_back($1);
1376 module_gen_body gen_stmt_or_module_body_stmt |
1379 gen_stmt_or_module_body_stmt:
1380 gen_stmt | module_body_stmt;
1382 // this production creates the obligatory if-else shift/reduce conflict
1385 AstNode *node = new AstNode(AST_GENFOR);
1386 ast_stack.back()->children.push_back(node);
1387 ast_stack.push_back(node);
1388 } simple_behavioral_stmt ';' expr {
1389 ast_stack.back()->children.push_back($6);
1390 } ';' simple_behavioral_stmt ')' gen_stmt_block {
1391 ast_stack.pop_back();
1393 TOK_IF '(' expr ')' {
1394 AstNode *node = new AstNode(AST_GENIF);
1395 ast_stack.back()->children.push_back(node);
1396 ast_stack.push_back(node);
1397 ast_stack.back()->children.push_back($3);
1398 } gen_stmt_block opt_gen_else {
1399 ast_stack.pop_back();
1401 case_type '(' expr ')' {
1402 AstNode *node = new AstNode(AST_GENCASE, $3);
1403 ast_stack.back()->children.push_back(node);
1404 ast_stack.push_back(node);
1405 } gen_case_body TOK_ENDCASE {
1406 case_type_stack.pop_back();
1407 ast_stack.pop_back();
1409 TOK_BEGIN opt_label {
1410 AstNode *node = new AstNode(AST_GENBLOCK);
1411 node->str = $2 ? *$2 : std::string();
1412 ast_stack.back()->children.push_back(node);
1413 ast_stack.push_back(node);
1414 } module_gen_body TOK_END opt_label {
1419 ast_stack.pop_back();
1424 AstNode *node = new AstNode(AST_GENBLOCK);
1425 ast_stack.back()->children.push_back(node);
1426 ast_stack.push_back(node);
1427 } gen_stmt_or_module_body_stmt {
1428 ast_stack.pop_back();
1432 gen_stmt_block | ';';
1435 TOK_ELSE gen_stmt_or_null | /* empty */;
1441 basic_expr '?' attr expr ':' expr {
1442 $$ = new AstNode(AST_TERNARY);
1443 $$->children.push_back($1);
1444 $$->children.push_back($4);
1445 $$->children.push_back($6);
1446 append_attr($$, $3);
1453 '(' expr ')' TOK_CONSTVAL {
1454 if ($4->substr(0, 1) != "'")
1455 frontend_verilog_yyerror("Syntax error.");
1457 AstNode *val = const2ast(*$4, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode);
1459 log_error("Value conversion failed: `%s'\n", $4->c_str());
1460 $$ = new AstNode(AST_TO_BITS, bits, val);
1463 hierarchical_id TOK_CONSTVAL {
1464 if ($2->substr(0, 1) != "'")
1465 frontend_verilog_yyerror("Syntax error.");
1466 AstNode *bits = new AstNode(AST_IDENTIFIER);
1468 AstNode *val = const2ast(*$2, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode);
1470 log_error("Value conversion failed: `%s'\n", $2->c_str());
1471 $$ = new AstNode(AST_TO_BITS, bits, val);
1475 TOK_CONSTVAL TOK_CONSTVAL {
1476 $$ = const2ast(*$1 + *$2, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode);
1477 if ($$ == NULL || (*$2)[0] != '\'')
1478 log_error("Value conversion failed: `%s%s'\n", $1->c_str(), $2->c_str());
1483 $$ = const2ast(*$1, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode);
1485 log_error("Value conversion failed: `%s'\n", $1->c_str());
1489 $$ = new AstNode(AST_REALVALUE);
1490 char *p = (char*)malloc(GetSize(*$1) + 1), *q;
1491 for (int i = 0, j = 0; j < GetSize(*$1); j++)
1492 if ((*$1)[j] != '_')
1493 p[i++] = (*$1)[j], p[i] = 0;
1494 $$->realvalue = strtod(p, &q);
1495 log_assert(*q == 0);
1500 $$ = AstNode::mkconst_str(*$1);
1503 hierarchical_id attr {
1504 AstNode *node = new AstNode(AST_FCALL);
1507 ast_stack.push_back(node);
1508 append_attr(node, $2);
1509 } '(' arg_list optional_comma ')' {
1510 $$ = ast_stack.back();
1511 ast_stack.pop_back();
1513 TOK_TO_SIGNED attr '(' expr ')' {
1514 $$ = new AstNode(AST_TO_SIGNED, $4);
1515 append_attr($$, $2);
1517 TOK_TO_UNSIGNED attr '(' expr ')' {
1518 $$ = new AstNode(AST_TO_UNSIGNED, $4);
1519 append_attr($$, $2);
1524 '(' expr ':' expr ':' expr ')' {
1529 '{' concat_list '}' {
1532 '{' expr '{' concat_list '}' '}' {
1533 $$ = new AstNode(AST_REPLICATE, $2, $4);
1535 '~' attr basic_expr %prec UNARY_OPS {
1536 $$ = new AstNode(AST_BIT_NOT, $3);
1537 append_attr($$, $2);
1539 basic_expr '&' attr basic_expr {
1540 $$ = new AstNode(AST_BIT_AND, $1, $4);
1541 append_attr($$, $3);
1543 basic_expr OP_NAND attr basic_expr {
1544 $$ = new AstNode(AST_BIT_NOT, new AstNode(AST_BIT_AND, $1, $4));
1545 append_attr($$, $3);
1547 basic_expr '|' attr basic_expr {
1548 $$ = new AstNode(AST_BIT_OR, $1, $4);
1549 append_attr($$, $3);
1551 basic_expr OP_NOR attr basic_expr {
1552 $$ = new AstNode(AST_BIT_NOT, new AstNode(AST_BIT_OR, $1, $4));
1553 append_attr($$, $3);
1555 basic_expr '^' attr basic_expr {
1556 $$ = new AstNode(AST_BIT_XOR, $1, $4);
1557 append_attr($$, $3);
1559 basic_expr OP_XNOR attr basic_expr {
1560 $$ = new AstNode(AST_BIT_XNOR, $1, $4);
1561 append_attr($$, $3);
1563 '&' attr basic_expr %prec UNARY_OPS {
1564 $$ = new AstNode(AST_REDUCE_AND, $3);
1565 append_attr($$, $2);
1567 OP_NAND attr basic_expr %prec UNARY_OPS {
1568 $$ = new AstNode(AST_REDUCE_AND, $3);
1569 append_attr($$, $2);
1570 $$ = new AstNode(AST_LOGIC_NOT, $$);
1572 '|' attr basic_expr %prec UNARY_OPS {
1573 $$ = new AstNode(AST_REDUCE_OR, $3);
1574 append_attr($$, $2);
1576 OP_NOR attr basic_expr %prec UNARY_OPS {
1577 $$ = new AstNode(AST_REDUCE_OR, $3);
1578 append_attr($$, $2);
1579 $$ = new AstNode(AST_LOGIC_NOT, $$);
1581 '^' attr basic_expr %prec UNARY_OPS {
1582 $$ = new AstNode(AST_REDUCE_XOR, $3);
1583 append_attr($$, $2);
1585 OP_XNOR attr basic_expr %prec UNARY_OPS {
1586 $$ = new AstNode(AST_REDUCE_XNOR, $3);
1587 append_attr($$, $2);
1589 basic_expr OP_SHL attr basic_expr {
1590 $$ = new AstNode(AST_SHIFT_LEFT, $1, $4);
1591 append_attr($$, $3);
1593 basic_expr OP_SHR attr basic_expr {
1594 $$ = new AstNode(AST_SHIFT_RIGHT, $1, $4);
1595 append_attr($$, $3);
1597 basic_expr OP_SSHL attr basic_expr {
1598 $$ = new AstNode(AST_SHIFT_SLEFT, $1, $4);
1599 append_attr($$, $3);
1601 basic_expr OP_SSHR attr basic_expr {
1602 $$ = new AstNode(AST_SHIFT_SRIGHT, $1, $4);
1603 append_attr($$, $3);
1605 basic_expr '<' attr basic_expr {
1606 $$ = new AstNode(AST_LT, $1, $4);
1607 append_attr($$, $3);
1609 basic_expr OP_LE attr basic_expr {
1610 $$ = new AstNode(AST_LE, $1, $4);
1611 append_attr($$, $3);
1613 basic_expr OP_EQ attr basic_expr {
1614 $$ = new AstNode(AST_EQ, $1, $4);
1615 append_attr($$, $3);
1617 basic_expr OP_NE attr basic_expr {
1618 $$ = new AstNode(AST_NE, $1, $4);
1619 append_attr($$, $3);
1621 basic_expr OP_EQX attr basic_expr {
1622 $$ = new AstNode(AST_EQX, $1, $4);
1623 append_attr($$, $3);
1625 basic_expr OP_NEX attr basic_expr {
1626 $$ = new AstNode(AST_NEX, $1, $4);
1627 append_attr($$, $3);
1629 basic_expr OP_GE attr basic_expr {
1630 $$ = new AstNode(AST_GE, $1, $4);
1631 append_attr($$, $3);
1633 basic_expr '>' attr basic_expr {
1634 $$ = new AstNode(AST_GT, $1, $4);
1635 append_attr($$, $3);
1637 basic_expr '+' attr basic_expr {
1638 $$ = new AstNode(AST_ADD, $1, $4);
1639 append_attr($$, $3);
1641 basic_expr '-' attr basic_expr {
1642 $$ = new AstNode(AST_SUB, $1, $4);
1643 append_attr($$, $3);
1645 basic_expr '*' attr basic_expr {
1646 $$ = new AstNode(AST_MUL, $1, $4);
1647 append_attr($$, $3);
1649 basic_expr '/' attr basic_expr {
1650 $$ = new AstNode(AST_DIV, $1, $4);
1651 append_attr($$, $3);
1653 basic_expr '%' attr basic_expr {
1654 $$ = new AstNode(AST_MOD, $1, $4);
1655 append_attr($$, $3);
1657 basic_expr OP_POW attr basic_expr {
1658 $$ = new AstNode(AST_POW, $1, $4);
1659 append_attr($$, $3);
1661 '+' attr basic_expr %prec UNARY_OPS {
1662 $$ = new AstNode(AST_POS, $3);
1663 append_attr($$, $2);
1665 '-' attr basic_expr %prec UNARY_OPS {
1666 $$ = new AstNode(AST_NEG, $3);
1667 append_attr($$, $2);
1669 basic_expr OP_LAND attr basic_expr {
1670 $$ = new AstNode(AST_LOGIC_AND, $1, $4);
1671 append_attr($$, $3);
1673 basic_expr OP_LOR attr basic_expr {
1674 $$ = new AstNode(AST_LOGIC_OR, $1, $4);
1675 append_attr($$, $3);
1677 '!' attr basic_expr %prec UNARY_OPS {
1678 $$ = new AstNode(AST_LOGIC_NOT, $3);
1679 append_attr($$, $2);
1684 $$ = new AstNode(AST_CONCAT, $1);
1686 expr ',' concat_list {
1688 $$->children.push_back($1);