3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-09-11 12:11:27 +00:00
This commit is contained in:
Xing Guo 2025-09-10 16:50:52 +00:00 committed by GitHub
commit 18b7f1a63a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -69,9 +69,10 @@
struct ParseState { struct ParseState {
int port_counter; int port_counter;
dict<std::string, int> port_stubs; dict<std::string, int> port_stubs;
dict<IdString, std::unique_ptr<AstNode>> *attr_list, default_attr_list; std::unique_ptr<dict<IdString, std::unique_ptr<AstNode>>> attr_list;
std::stack<dict<IdString, std::unique_ptr<AstNode>> *> attr_list_stack; dict<IdString, std::unique_ptr<AstNode>> default_attr_list;
dict<IdString, std::unique_ptr<AstNode>> *albuf; std::stack<std::unique_ptr<dict<IdString, std::unique_ptr<AstNode>>>> attr_list_stack;
std::unique_ptr<dict<IdString, std::unique_ptr<AstNode>>> albuf;
std::vector<UserTypeMap> user_type_stack; std::vector<UserTypeMap> user_type_stack;
dict<std::string, AstNode*> pkg_user_types; dict<std::string, AstNode*> pkg_user_types;
std::vector<AstNode*> ast_stack; std::vector<AstNode*> ast_stack;
@ -97,13 +98,16 @@
bool isInLocalScope(const std::string *name); bool isInLocalScope(const std::string *name);
void rewriteGenForDeclInit(AstNode *loop); void rewriteGenForDeclInit(AstNode *loop);
void ensureAsgnExprAllowed(const parser::location_type loc, bool sv_mode); void ensureAsgnExprAllowed(const parser::location_type loc, bool sv_mode);
const AstNode *addIncOrDecStmt(dict<IdString, std::unique_ptr<AstNode>> *stmt_attr, const AstNode *addIncOrDecStmt(std::unique_ptr<dict<IdString, std::unique_ptr<AstNode>>> stmt_attr,
std::unique_ptr<AstNode> lhs, std::unique_ptr<AstNode> lhs,
dict<IdString, std::unique_ptr<AstNode>> *op_attr, AST::AstNodeType op, std::unique_ptr<dict<IdString, std::unique_ptr<AstNode>>> op_attr, AST::AstNodeType op,
parser::location_type loc); parser::location_type loc);
std::unique_ptr<AstNode> addIncOrDecExpr(std::unique_ptr<AstNode> lhs, dict<IdString, std::unique_ptr<AstNode>> *attr, AST::AstNodeType op, parser::location_type loc, bool undo, bool sv_mode); std::unique_ptr<AstNode> addIncOrDecExpr(std::unique_ptr<AstNode> lhs,
std::unique_ptr<dict<IdString, std::unique_ptr<AstNode>>> attr,
AST::AstNodeType op, parser::location_type loc, bool undo, bool sv_mode);
// add a binary operator assignment statement, e.g., a += b // add a binary operator assignment statement, e.g., a += b
std::unique_ptr<AstNode> addAsgnBinopStmt(dict<IdString, std::unique_ptr<AstNode>> *attr, std::unique_ptr<AstNode> eq_lhs, AST::AstNodeType op, std::unique_ptr<AstNode> rhs); std::unique_ptr<AstNode> addAsgnBinopStmt(std::unique_ptr<dict<IdString, std::unique_ptr<AstNode>>> attr,
std::unique_ptr<AstNode> eq_lhs, AST::AstNodeType op, std::unique_ptr<AstNode> rhs);
}; };
struct ParseMode { struct ParseMode {
bool noassert = false; bool noassert = false;
@ -150,26 +154,20 @@
return Location(begin.begin, end.end); return Location(begin.begin, end.end);
} }
static void append_attr(AstNode *ast, dict<IdString, std::unique_ptr<AstNode>> *al) static void append_attr(AstNode *ast, std::unique_ptr<dict<IdString, std::unique_ptr<AstNode>>> al)
{ {
for (auto &it : *al) { for (auto &it : *al) {
ast->attributes[it.first] = std::move(it.second); ast->attributes[it.first] = std::move(it.second);
} }
delete al;
} }
static void append_attr_clone(AstNode *ast, dict<IdString, std::unique_ptr<AstNode>> *al) static void append_attr_clone(AstNode *ast, std::unique_ptr<dict<IdString, std::unique_ptr<AstNode>>> &al)
{ {
for (auto &it : *al) { for (auto &it : *al) {
ast->attributes[it.first] = it.second->clone(); ast->attributes[it.first] = it.second->clone();
} }
} }
static void free_attr(dict<IdString, std::unique_ptr<AstNode>> *al)
{
delete al;
}
static std::unique_ptr<AstNode> makeRange(parser::location_type loc, int msb = 31, int lsb = 0, bool isSigned = true) static std::unique_ptr<AstNode> makeRange(parser::location_type loc, int msb = 31, int lsb = 0, bool isSigned = true)
{ {
auto range = std::make_unique<AstNode>(loc, AST_RANGE); auto range = std::make_unique<AstNode>(loc, AST_RANGE);
@ -363,28 +361,31 @@
} }
// add a pre/post-increment/decrement statement // add a pre/post-increment/decrement statement
const AstNode *ParseState::addIncOrDecStmt(dict<IdString, std::unique_ptr<AstNode>> *stmt_attr, const AstNode *ParseState::addIncOrDecStmt(std::unique_ptr<dict<IdString, std::unique_ptr<AstNode>>> stmt_attr,
std::unique_ptr<AstNode> lhs, std::unique_ptr<AstNode> lhs,
dict<IdString, std::unique_ptr<AstNode>> *op_attr, AST::AstNodeType op, std::unique_ptr<dict<IdString, std::unique_ptr<AstNode>>> op_attr, AST::AstNodeType op,
Location loc) Location loc)
{ {
auto one = AstNode::mkconst_int(loc, 1, true); auto one = AstNode::mkconst_int(loc, 1, true);
auto rhs = std::make_unique<AstNode>(loc, op, lhs->clone(), std::move(one)); auto rhs = std::make_unique<AstNode>(loc, op, lhs->clone(), std::move(one));
if (op_attr != nullptr) if (op_attr)
append_attr(rhs.get(), op_attr); append_attr(rhs.get(), std::move(op_attr));
auto stmt_owned = std::make_unique<AstNode>(loc, AST_ASSIGN_EQ, std::move(lhs), std::move(rhs)); auto stmt_owned = std::make_unique<AstNode>(loc, AST_ASSIGN_EQ, std::move(lhs), std::move(rhs));
auto* stmt = stmt_owned.get(); auto* stmt = stmt_owned.get();
ast_stack.back()->children.push_back(std::move(stmt_owned)); ast_stack.back()->children.push_back(std::move(stmt_owned));
if (stmt_attr != nullptr) if (stmt_attr)
append_attr(stmt, stmt_attr); append_attr(stmt, std::move(stmt_attr));
return stmt; return stmt;
} }
// create a pre/post-increment/decrement expression, and add the corresponding statement // create a pre/post-increment/decrement expression, and add the corresponding statement
std::unique_ptr<AstNode> ParseState::addIncOrDecExpr(std::unique_ptr<AstNode> lhs, dict<IdString, std::unique_ptr<AstNode>> *attr, AST::AstNodeType op, Location loc, bool undo, bool sv_mode) std::unique_ptr<AstNode> ParseState::addIncOrDecExpr(std::unique_ptr<AstNode> lhs,
std::unique_ptr<dict<IdString,
std::unique_ptr<AstNode>>> attr,
AST::AstNodeType op, Location loc, bool undo, bool sv_mode)
{ {
ensureAsgnExprAllowed(loc, sv_mode); ensureAsgnExprAllowed(loc, sv_mode);
const AstNode *stmt = addIncOrDecStmt(nullptr, std::move(lhs), attr, op, loc); const AstNode *stmt = addIncOrDecStmt(nullptr, std::move(lhs), std::move(attr), op, loc);
log_assert(stmt->type == AST_ASSIGN_EQ); log_assert(stmt->type == AST_ASSIGN_EQ);
auto expr = stmt->children[0]->clone(); auto expr = stmt->children[0]->clone();
if (undo) { if (undo) {
@ -396,7 +397,8 @@
} }
// add a binary operator assignment statement, e.g., a += b // add a binary operator assignment statement, e.g., a += b
std::unique_ptr<AstNode> ParseState::addAsgnBinopStmt(dict<IdString, std::unique_ptr<AstNode>> *attr, std::unique_ptr<AstNode> eq_lhs, AST::AstNodeType op, std::unique_ptr<AstNode> rhs) std::unique_ptr<AstNode> ParseState::addAsgnBinopStmt(std::unique_ptr<dict<IdString, std::unique_ptr<AstNode>>> attr,
std::unique_ptr<AstNode> eq_lhs, AST::AstNodeType op, std::unique_ptr<AstNode> rhs)
{ {
Location loc = location_range(eq_lhs->location, rhs->location); Location loc = location_range(eq_lhs->location, rhs->location);
if (op == AST_SHIFT_LEFT || op == AST_SHIFT_RIGHT || if (op == AST_SHIFT_LEFT || op == AST_SHIFT_RIGHT ||
@ -409,8 +411,8 @@
auto stmt_owned = std::make_unique<AstNode>(loc, AST_ASSIGN_EQ, std::move(eq_lhs), std::move(eq_rhs_owned)); auto stmt_owned = std::make_unique<AstNode>(loc, AST_ASSIGN_EQ, std::move(eq_lhs), std::move(eq_rhs_owned));
auto* stmt = stmt_owned.get(); auto* stmt = stmt_owned.get();
ast_stack.back()->children.push_back(std::move(stmt_owned)); ast_stack.back()->children.push_back(std::move(stmt_owned));
if (attr != nullptr) if (attr)
append_attr(stmt, attr); append_attr(stmt, std::move(attr));
return ret_lhs; return ret_lhs;
} }
}; };
@ -460,7 +462,7 @@
using string_t = std::unique_ptr<std::string>; using string_t = std::unique_ptr<std::string>;
using ast_t = std::unique_ptr<YOSYS_NAMESPACE_PREFIX AST::AstNode>; using ast_t = std::unique_ptr<YOSYS_NAMESPACE_PREFIX AST::AstNode>;
using al_t = YOSYS_NAMESPACE_PREFIX dict<YOSYS_NAMESPACE_PREFIX RTLIL::IdString, std::unique_ptr<YOSYS_NAMESPACE_PREFIX AST::AstNode>>*; using al_t = std::unique_ptr<YOSYS_NAMESPACE_PREFIX dict<YOSYS_NAMESPACE_PREFIX RTLIL::IdString, std::unique_ptr<YOSYS_NAMESPACE_PREFIX AST::AstNode>>>;
using specify_target_ptr_t = std::unique_ptr<struct specify_target>; using specify_target_ptr_t = std::unique_ptr<struct specify_target>;
using specify_triple_ptr_t = std::unique_ptr<struct specify_triple>; using specify_triple_ptr_t = std::unique_ptr<struct specify_triple>;
using specify_rise_fall_ptr_t = std::unique_ptr<struct specify_rise_fall>; using specify_rise_fall_ptr_t = std::unique_ptr<struct specify_rise_fall>;
@ -613,15 +615,15 @@ design:
attr: attr:
{ {
if (extra->attr_list != nullptr) if (extra->attr_list)
extra->attr_list_stack.push(extra->attr_list); extra->attr_list_stack.push(std::move(extra->attr_list));
extra->attr_list = new dict<IdString, std::unique_ptr<AstNode>>; extra->attr_list = std::make_unique<dict<IdString, std::unique_ptr<AstNode>>>();
for (auto &it : extra->default_attr_list) for (auto &it : extra->default_attr_list)
(*extra->attr_list)[it.first] = it.second->clone(); (*extra->attr_list)[it.first] = it.second->clone();
} attr_opt { } attr_opt {
$$ = extra->attr_list; $$ = std::move(extra->attr_list);
if (!extra->attr_list_stack.empty()) { if (!extra->attr_list_stack.empty()) {
extra->attr_list = extra->attr_list_stack.top(); extra->attr_list = std::move(extra->attr_list_stack.top());
extra->attr_list_stack.pop(); extra->attr_list_stack.pop();
} else } else
extra->attr_list = nullptr; extra->attr_list = nullptr;
@ -636,14 +638,14 @@ attr_opt:
defattr: defattr:
DEFATTR_BEGIN { DEFATTR_BEGIN {
if (extra->attr_list != nullptr) if (extra->attr_list != nullptr)
extra->attr_list_stack.push(extra->attr_list); extra->attr_list_stack.push(std::move(extra->attr_list));
extra->attr_list = new dict<IdString, std::unique_ptr<AstNode>>; extra->attr_list = std::make_unique<dict<IdString, std::unique_ptr<AstNode>>>();
extra->default_attr_list.clear(); extra->default_attr_list.clear();
} opt_attr_list { } opt_attr_list {
extra->attr_list->swap(extra->default_attr_list); extra->attr_list->swap(extra->default_attr_list);
delete extra->attr_list; extra->attr_list.reset();
if (!extra->attr_list_stack.empty()) { if (!extra->attr_list_stack.empty()) {
extra->attr_list = extra->attr_list_stack.top(); extra->attr_list = std::move(extra->attr_list_stack.top());
extra->attr_list_stack.pop(); extra->attr_list_stack.pop();
} else } else
extra->attr_list = nullptr; extra->attr_list = nullptr;
@ -699,7 +701,7 @@ module:
extra->port_stubs.clear(); extra->port_stubs.clear();
extra->port_counter = 0; extra->port_counter = 0;
mod->str = *$4; mod->str = *$4;
append_attr(mod, $1); append_attr(mod, std::move($1));
} module_para_opt module_args_opt TOK_SEMICOL module_body TOK_ENDMODULE opt_label { } module_para_opt module_args_opt TOK_SEMICOL module_body TOK_ENDMODULE opt_label {
if (extra->port_stubs.size() != 0) if (extra->port_stubs.size() != 0)
err_at_loc(@7, "Missing details for module port `%s'.", err_at_loc(@7, "Missing details for module port `%s'.",
@ -723,12 +725,12 @@ single_module_para:
attr TOK_PARAMETER { attr TOK_PARAMETER {
extra->astbuf1 = std::make_unique<AstNode>(@$, AST_PARAMETER); extra->astbuf1 = std::make_unique<AstNode>(@$, AST_PARAMETER);
extra->astbuf1->children.push_back(AstNode::mkconst_int(@2, 0, true)); extra->astbuf1->children.push_back(AstNode::mkconst_int(@2, 0, true));
append_attr(extra->astbuf1.get(), $1); append_attr(extra->astbuf1.get(), std::move($1));
} param_type single_param_decl | } param_type single_param_decl |
attr TOK_LOCALPARAM { attr TOK_LOCALPARAM {
extra->astbuf1 = std::make_unique<AstNode>(@$, AST_LOCALPARAM); extra->astbuf1 = std::make_unique<AstNode>(@$, AST_LOCALPARAM);
extra->astbuf1->children.push_back(AstNode::mkconst_int(@2, 0, true)); extra->astbuf1->children.push_back(AstNode::mkconst_int(@2, 0, true));
append_attr(extra->astbuf1.get(), $1); append_attr(extra->astbuf1.get(), std::move($1));
} param_type single_param_decl | } param_type single_param_decl |
single_param_decl; single_param_decl;
@ -798,7 +800,7 @@ module_arg:
err_at_loc(@4, "Module port `%s' is neither input nor output.", $4->c_str()); err_at_loc(@4, "Module port `%s' is neither input nor output.", $4->c_str());
if (node->is_reg && node->is_input && !node->is_output && !mode->sv) if (node->is_reg && node->is_input && !node->is_output && !mode->sv)
err_at_loc(@4, "Input port `%s' is declared as register.", $4->c_str()); err_at_loc(@4, "Input port `%s' is declared as register.", $4->c_str());
append_attr(node.get(), $1); append_attr(node.get(), std::move($1));
extra->ast_stack.back()->children.push_back(std::move(node)); extra->ast_stack.back()->children.push_back(std::move(node));
} module_arg_opt_assignment | } module_arg_opt_assignment |
TOK_DOT TOK_DOT TOK_DOT { TOK_DOT TOK_DOT TOK_DOT {
@ -812,7 +814,7 @@ package:
AstNode* mod = extra->pushChild(std::make_unique<AstNode>(@$, AST_PACKAGE)); AstNode* mod = extra->pushChild(std::make_unique<AstNode>(@$, AST_PACKAGE));
extra->current_ast_mod = mod; extra->current_ast_mod = mod;
mod->str = *$4; mod->str = *$4;
append_attr(mod, $1); append_attr(mod, std::move($1));
} TOK_SEMICOL package_body TOK_ENDPACKAGE opt_label { } TOK_SEMICOL package_body TOK_ENDPACKAGE opt_label {
extra->ast_stack.pop_back(); extra->ast_stack.pop_back();
checkLabelsMatch(@9, "Package name", $4.get(), $9.get()); checkLabelsMatch(@9, "Package name", $4.get(), $9.get());
@ -1114,28 +1116,28 @@ task_func_decl:
attr TOK_DPI_FUNCTION TOK_ID TOK_ID { attr TOK_DPI_FUNCTION TOK_ID TOK_ID {
extra->current_function_or_task = extra->saveChild(std::make_unique<AstNode>(@$, AST_DPI_FUNCTION, AstNode::mkconst_str(@3, *$3), AstNode::mkconst_str(@4, *$4))); extra->current_function_or_task = extra->saveChild(std::make_unique<AstNode>(@$, AST_DPI_FUNCTION, AstNode::mkconst_str(@3, *$3), AstNode::mkconst_str(@4, *$4)));
extra->current_function_or_task->str = *$4; extra->current_function_or_task->str = *$4;
append_attr(extra->current_function_or_task, $1); append_attr(extra->current_function_or_task, std::move($1));
} opt_dpi_function_args TOK_SEMICOL { } opt_dpi_function_args TOK_SEMICOL {
extra->current_function_or_task = nullptr; extra->current_function_or_task = nullptr;
} | } |
attr TOK_DPI_FUNCTION TOK_ID TOK_EQ TOK_ID TOK_ID { attr TOK_DPI_FUNCTION TOK_ID TOK_EQ TOK_ID TOK_ID {
extra->current_function_or_task = extra->saveChild(std::make_unique<AstNode>(@$, AST_DPI_FUNCTION, AstNode::mkconst_str(@5, *$5), AstNode::mkconst_str(@3, *$3))); extra->current_function_or_task = extra->saveChild(std::make_unique<AstNode>(@$, AST_DPI_FUNCTION, AstNode::mkconst_str(@5, *$5), AstNode::mkconst_str(@3, *$3)));
extra->current_function_or_task->str = *$6; extra->current_function_or_task->str = *$6;
append_attr(extra->current_function_or_task, $1); append_attr(extra->current_function_or_task, std::move($1));
} opt_dpi_function_args TOK_SEMICOL { } opt_dpi_function_args TOK_SEMICOL {
extra->current_function_or_task = nullptr; extra->current_function_or_task = nullptr;
} | } |
attr TOK_DPI_FUNCTION TOK_ID TOK_COL TOK_ID TOK_EQ TOK_ID TOK_ID { attr TOK_DPI_FUNCTION TOK_ID TOK_COL TOK_ID TOK_EQ TOK_ID TOK_ID {
extra->current_function_or_task = extra->saveChild(std::make_unique<AstNode>(@$, AST_DPI_FUNCTION, AstNode::mkconst_str(@7, *$7), AstNode::mkconst_str(location_range(@3, @5), *$3 + ":" + RTLIL::unescape_id(*$5)))); extra->current_function_or_task = extra->saveChild(std::make_unique<AstNode>(@$, AST_DPI_FUNCTION, AstNode::mkconst_str(@7, *$7), AstNode::mkconst_str(location_range(@3, @5), *$3 + ":" + RTLIL::unescape_id(*$5))));
extra->current_function_or_task->str = *$8; extra->current_function_or_task->str = *$8;
append_attr(extra->current_function_or_task, $1); append_attr(extra->current_function_or_task, std::move($1));
} opt_dpi_function_args TOK_SEMICOL { } opt_dpi_function_args TOK_SEMICOL {
extra->current_function_or_task = nullptr; extra->current_function_or_task = nullptr;
} | } |
attr TOK_TASK opt_automatic TOK_ID { attr TOK_TASK opt_automatic TOK_ID {
extra->current_function_or_task = extra->pushChild(std::make_unique<AstNode>(@$, AST_TASK)); extra->current_function_or_task = extra->pushChild(std::make_unique<AstNode>(@$, AST_TASK));
extra->current_function_or_task->str = *$4; extra->current_function_or_task->str = *$4;
append_attr(extra->current_function_or_task, $1); append_attr(extra->current_function_or_task, std::move($1));
extra->current_function_or_task_port_id = 1; extra->current_function_or_task_port_id = 1;
} task_func_args_opt TOK_SEMICOL task_func_body TOK_ENDTASK { } task_func_args_opt TOK_SEMICOL task_func_body TOK_ENDTASK {
extra->current_function_or_task = nullptr; extra->current_function_or_task = nullptr;
@ -1149,7 +1151,7 @@ task_func_decl:
// function like a task. // function like a task.
extra->current_function_or_task = extra->pushChild(std::make_unique<AstNode>(@$, AST_TASK)); extra->current_function_or_task = extra->pushChild(std::make_unique<AstNode>(@$, AST_TASK));
extra->current_function_or_task->str = *$5; extra->current_function_or_task->str = *$5;
append_attr(extra->current_function_or_task, $1); append_attr(extra->current_function_or_task, std::move($1));
extra->current_function_or_task_port_id = 1; extra->current_function_or_task_port_id = 1;
} task_func_args_opt TOK_SEMICOL task_func_body TOK_ENDFUNCTION { } task_func_args_opt TOK_SEMICOL task_func_body TOK_ENDFUNCTION {
extra->current_function_or_task = nullptr; extra->current_function_or_task = nullptr;
@ -1158,7 +1160,7 @@ task_func_decl:
attr TOK_FUNCTION opt_automatic func_return_type TOK_ID { attr TOK_FUNCTION opt_automatic func_return_type TOK_ID {
extra->current_function_or_task = extra->pushChild(std::make_unique<AstNode>(@$, AST_FUNCTION)); extra->current_function_or_task = extra->pushChild(std::make_unique<AstNode>(@$, AST_FUNCTION));
extra->current_function_or_task->str = *$5; extra->current_function_or_task->str = *$5;
append_attr(extra->current_function_or_task, $1); append_attr(extra->current_function_or_task, std::move($1));
auto outreg = std::make_unique<AstNode>(@$, AST_WIRE); auto outreg = std::make_unique<AstNode>(@$, AST_WIRE);
outreg->str = *$5; outreg->str = *$5;
outreg->is_signed = false; outreg->is_signed = false;
@ -1240,7 +1242,7 @@ task_func_args_opt:
(void)extra->astbuf1.reset(); (void)extra->astbuf1.reset();
if (extra->astbuf2 != nullptr) if (extra->astbuf2 != nullptr)
(void)extra->astbuf2.reset(); (void)extra->astbuf2.reset();
free_attr(extra->albuf); extra->albuf.reset();
} TOK_RPAREN; } TOK_RPAREN;
task_func_args: task_func_args:
@ -1256,9 +1258,9 @@ task_func_port:
(void)extra->astbuf1.reset(); (void)extra->astbuf1.reset();
if (extra->astbuf2 != nullptr) if (extra->astbuf2 != nullptr)
(void)extra->astbuf2.reset(); (void)extra->astbuf2.reset();
free_attr(extra->albuf); extra->albuf.reset();
} }
extra->albuf = $1; extra->albuf = std::move($1);
extra->astbuf1 = std::move($2); extra->astbuf1 = std::move($2);
extra->astbuf2 = checkRange(extra->astbuf1.get(), std::move($3)); extra->astbuf2 = checkRange(extra->astbuf1.get(), std::move($3));
if (!extra->astbuf1->is_input && !extra->astbuf1->is_output) { if (!extra->astbuf1->is_input && !extra->astbuf1->is_output) {
@ -1272,7 +1274,7 @@ task_func_port:
if (!extra->astbuf1) { if (!extra->astbuf1) {
if (!mode->sv) if (!mode->sv)
err_at_loc(@$, "task/function argument direction missing"); err_at_loc(@$, "task/function argument direction missing");
extra->albuf = new dict<IdString, std::unique_ptr<AstNode>>; extra->albuf = std::make_unique<dict<IdString, std::unique_ptr<AstNode>>>();
extra->astbuf1 = std::make_unique<AstNode>(@$, AST_WIRE); extra->astbuf1 = std::make_unique<AstNode>(@$, AST_WIRE);
extra->current_wire_rand = false; extra->current_wire_rand = false;
extra->current_wire_const = false; extra->current_wire_const = false;
@ -1601,23 +1603,23 @@ state_dependent_path_declaration:
module_path_expression: module_path_expression:
module_path_primary module_path_primary
// Flatten out unary_operator to avoid shift/reduce conflict // Flatten out unary_operator to avoid shift/reduce conflict
| TOK_EXCL attr module_path_primary { free_attr($2); } | TOK_EXCL attr module_path_primary
| TOK_TILDE attr module_path_primary { free_attr($2); } | TOK_TILDE attr module_path_primary
| TOK_AMP attr module_path_primary { free_attr($2); } | TOK_AMP attr module_path_primary
| OP_NAND attr module_path_primary { free_attr($2); } | OP_NAND attr module_path_primary
| TOK_PIPE attr module_path_primary { free_attr($2); } | TOK_PIPE attr module_path_primary
| OP_NOR attr module_path_primary { free_attr($2); } | OP_NOR attr module_path_primary
| TOK_CARET attr module_path_primary { free_attr($2); } | TOK_CARET attr module_path_primary
| OP_XNOR attr module_path_primary { free_attr($2); } | OP_XNOR attr module_path_primary
// Flatten out binary_operator to avoid shift/reduce conflict // Flatten out binary_operator to avoid shift/reduce conflict
| module_path_expression OP_EQ attr module_path_expression { free_attr($3); } | module_path_expression OP_EQ attr module_path_expression
| module_path_expression OP_NE attr module_path_expression { free_attr($3); } | module_path_expression OP_NE attr module_path_expression
| module_path_expression OP_LAND attr module_path_expression { free_attr($3); } | module_path_expression OP_LAND attr module_path_expression
| module_path_expression OP_LOR attr module_path_expression { free_attr($3); } | module_path_expression OP_LOR attr module_path_expression
| module_path_expression TOK_AMP attr module_path_expression { free_attr($3); } | module_path_expression TOK_AMP attr module_path_expression
| module_path_expression TOK_PIPE attr module_path_expression { free_attr($3); } | module_path_expression TOK_PIPE attr module_path_expression
| module_path_expression TOK_CARET attr module_path_expression { free_attr($3); } | module_path_expression TOK_CARET attr module_path_expression
| module_path_expression OP_XNOR attr module_path_expression { free_attr($3); } | module_path_expression OP_XNOR attr module_path_expression
// | module_path_conditional_expression // | module_path_conditional_expression
; ;
@ -1760,7 +1762,7 @@ param_decl:
attr TOK_PARAMETER { attr TOK_PARAMETER {
extra->astbuf1 = std::make_unique<AstNode>(@$, AST_PARAMETER); extra->astbuf1 = std::make_unique<AstNode>(@$, AST_PARAMETER);
extra->astbuf1->children.push_back(AstNode::mkconst_int(@$, 0, true)); extra->astbuf1->children.push_back(AstNode::mkconst_int(@$, 0, true));
append_attr(extra->astbuf1.get(), $1); append_attr(extra->astbuf1.get(), std::move($1));
} param_type param_decl_list TOK_SEMICOL { } param_type param_decl_list TOK_SEMICOL {
(void)extra->astbuf1.reset(); (void)extra->astbuf1.reset();
}; };
@ -1769,7 +1771,7 @@ localparam_decl:
attr TOK_LOCALPARAM { attr TOK_LOCALPARAM {
extra->astbuf1 = std::make_unique<AstNode>(@$, AST_LOCALPARAM); extra->astbuf1 = std::make_unique<AstNode>(@$, AST_LOCALPARAM);
extra->astbuf1->children.push_back(AstNode::mkconst_int(@$, 0, true)); extra->astbuf1->children.push_back(AstNode::mkconst_int(@$, 0, true));
append_attr(extra->astbuf1.get(), $1); append_attr(extra->astbuf1.get(), std::move($1));
} param_type param_decl_list TOK_SEMICOL { } param_type param_decl_list TOK_SEMICOL {
(void)extra->astbuf1.reset(); (void)extra->astbuf1.reset();
}; };
@ -1925,7 +1927,7 @@ enum_decl: enum_type enum_var_list TOK_SEMICOL { }
struct_decl: struct_decl:
attr struct_type { attr struct_type {
append_attr(extra->astbuf2.get(), $1); append_attr(extra->astbuf2.get(), std::move($1));
} struct_var_list TOK_SEMICOL { } struct_var_list TOK_SEMICOL {
(void)extra->astbuf2.reset(); (void)extra->astbuf2.reset();
} }
@ -2031,26 +2033,26 @@ struct_var:
wire_decl: wire_decl:
attr wire_type range_or_multirange { attr wire_type range_or_multirange {
extra->albuf = $1; extra->albuf = std::move($1);
extra->astbuf1 = std::move($2); extra->astbuf1 = std::move($2);
extra->astbuf2 = checkRange(extra->astbuf1.get(), std::move($3)); extra->astbuf2 = checkRange(extra->astbuf1.get(), std::move($3));
} delay wire_name_list { } delay wire_name_list {
(void)extra->astbuf1.reset(); (void)extra->astbuf1.reset();
if (extra->astbuf2 != nullptr) if (extra->astbuf2 != nullptr)
(void)extra->astbuf2.reset(); (void)extra->astbuf2.reset();
free_attr(extra->albuf); extra->albuf.reset();
} TOK_SEMICOL | } TOK_SEMICOL |
attr TOK_SUPPLY0 TOK_ID { attr TOK_SUPPLY0 TOK_ID {
extra->ast_stack.back()->children.push_back(std::make_unique<AstNode>(@$, AST_WIRE)); extra->ast_stack.back()->children.push_back(std::make_unique<AstNode>(@$, AST_WIRE));
extra->ast_stack.back()->children.back()->str = *$3; extra->ast_stack.back()->children.back()->str = *$3;
append_attr(extra->ast_stack.back()->children.back().get(), $1); append_attr(extra->ast_stack.back()->children.back().get(), std::move($1));
extra->ast_stack.back()->children.push_back(std::make_unique<AstNode>(@$, AST_ASSIGN, std::make_unique<AstNode>(@$, AST_IDENTIFIER), AstNode::mkconst_int(@$, 0, false, 1))); extra->ast_stack.back()->children.push_back(std::make_unique<AstNode>(@$, AST_ASSIGN, std::make_unique<AstNode>(@$, AST_IDENTIFIER), AstNode::mkconst_int(@$, 0, false, 1)));
extra->ast_stack.back()->children.back()->children[0]->str = *$3; extra->ast_stack.back()->children.back()->children[0]->str = *$3;
} opt_supply_wires TOK_SEMICOL | } opt_supply_wires TOK_SEMICOL |
attr TOK_SUPPLY1 TOK_ID { attr TOK_SUPPLY1 TOK_ID {
extra->ast_stack.back()->children.push_back(std::make_unique<AstNode>(@$, AST_WIRE)); extra->ast_stack.back()->children.push_back(std::make_unique<AstNode>(@$, AST_WIRE));
extra->ast_stack.back()->children.back()->str = *$3; extra->ast_stack.back()->children.back()->str = *$3;
append_attr(extra->ast_stack.back()->children.back().get(), $1); append_attr(extra->ast_stack.back()->children.back().get(), std::move($1));
extra->ast_stack.back()->children.push_back(std::make_unique<AstNode>(@$, AST_ASSIGN, std::make_unique<AstNode>(@$, AST_IDENTIFIER), AstNode::mkconst_int(@$, 1, false, 1))); extra->ast_stack.back()->children.push_back(std::make_unique<AstNode>(@$, AST_ASSIGN, std::make_unique<AstNode>(@$, AST_IDENTIFIER), AstNode::mkconst_int(@$, 1, false, 1)));
extra->ast_stack.back()->children.back()->children[0]->str = *$3; extra->ast_stack.back()->children.back()->children[0]->str = *$3;
} opt_supply_wires TOK_SEMICOL; } opt_supply_wires TOK_SEMICOL;
@ -2243,7 +2245,7 @@ enum_struct_type:
cell_stmt: cell_stmt:
attr TOK_ID { attr TOK_ID {
extra->astbuf1 = std::make_unique<AstNode>(@$, AST_CELL); extra->astbuf1 = std::make_unique<AstNode>(@$, AST_CELL);
append_attr(extra->astbuf1.get(), $1); append_attr(extra->astbuf1.get(), std::move($1));
extra->astbuf1->children.push_back(std::make_unique<AstNode>(@$, AST_CELLTYPE)); extra->astbuf1->children.push_back(std::make_unique<AstNode>(@$, AST_CELLTYPE));
extra->astbuf1->children[0]->str = *$2; extra->astbuf1->children[0]->str = *$2;
} cell_parameter_list_opt cell_list TOK_SEMICOL { } cell_parameter_list_opt cell_list TOK_SEMICOL {
@ -2252,7 +2254,7 @@ cell_stmt:
attr tok_prim_wrapper delay { attr tok_prim_wrapper delay {
extra->astbuf1 = std::make_unique<AstNode>(@$, AST_PRIMITIVE); extra->astbuf1 = std::make_unique<AstNode>(@$, AST_PRIMITIVE);
extra->astbuf1->str = *$2; extra->astbuf1->str = *$2;
append_attr(extra->astbuf1.get(), $1); append_attr(extra->astbuf1.get(), std::move($1));
} prim_list TOK_SEMICOL { } prim_list TOK_SEMICOL {
(void)extra->astbuf1.reset(); (void)extra->astbuf1.reset();
}; };
@ -2378,26 +2380,22 @@ cell_port:
attr { attr {
auto node = std::make_unique<AstNode>(@$, AST_ARGUMENT); auto node = std::make_unique<AstNode>(@$, AST_ARGUMENT);
extra->cell_hack->children.push_back(std::move(node)); extra->cell_hack->children.push_back(std::move(node));
free_attr($1);
} | } |
attr expr { attr expr {
auto node = std::make_unique<AstNode>(@$, AST_ARGUMENT); auto node = std::make_unique<AstNode>(@$, AST_ARGUMENT);
node->children.push_back(std::move($2)); node->children.push_back(std::move($2));
extra->cell_hack->children.push_back(std::move(node)); extra->cell_hack->children.push_back(std::move(node));
free_attr($1);
} | } |
attr TOK_DOT TOK_ID TOK_LPAREN expr TOK_RPAREN { attr TOK_DOT TOK_ID TOK_LPAREN expr TOK_RPAREN {
auto node = std::make_unique<AstNode>(@$, AST_ARGUMENT); auto node = std::make_unique<AstNode>(@$, AST_ARGUMENT);
node->str = *$3; node->str = *$3;
node->children.push_back(std::move($5)); node->children.push_back(std::move($5));
extra->cell_hack->children.push_back(std::move(node)); extra->cell_hack->children.push_back(std::move(node));
free_attr($1);
} | } |
attr TOK_DOT TOK_ID TOK_LPAREN TOK_RPAREN { attr TOK_DOT TOK_ID TOK_LPAREN TOK_RPAREN {
auto node = std::make_unique<AstNode>(@$, AST_ARGUMENT); auto node = std::make_unique<AstNode>(@$, AST_ARGUMENT);
node->str = *$3; node->str = *$3;
extra->cell_hack->children.push_back(std::move(node)); extra->cell_hack->children.push_back(std::move(node));
free_attr($1);
} | } |
attr TOK_DOT TOK_ID { attr TOK_DOT TOK_ID {
auto node = std::make_unique<AstNode>(@$, AST_ARGUMENT); auto node = std::make_unique<AstNode>(@$, AST_ARGUMENT);
@ -2405,13 +2403,11 @@ cell_port:
node->children.push_back(std::make_unique<AstNode>(@$, AST_IDENTIFIER)); node->children.push_back(std::make_unique<AstNode>(@$, AST_IDENTIFIER));
node->children.back()->str = *$3; node->children.back()->str = *$3;
extra->cell_hack->children.push_back(std::move(node)); extra->cell_hack->children.push_back(std::move(node));
free_attr($1);
} | } |
attr TOK_WILDCARD_CONNECT { attr TOK_WILDCARD_CONNECT {
if (!mode->sv) if (!mode->sv)
err_at_loc(@2, "Wildcard port connections are only supported in SystemVerilog mode."); err_at_loc(@2, "Wildcard port connections are only supported in SystemVerilog mode.");
extra->cell_hack->attributes[ID::wildcard_port_conns] = AstNode::mkconst_int(@2, 1, false); extra->cell_hack->attributes[ID::wildcard_port_conns] = AstNode::mkconst_int(@2, 1, false);
free_attr($1);
}; };
always_comb_or_latch: always_comb_or_latch:
@ -2433,7 +2429,7 @@ always_or_always_ff:
always_stmt: always_stmt:
attr always_or_always_ff { attr always_or_always_ff {
AstNode* node = extra->pushChild(std::make_unique<AstNode>(@$, AST_ALWAYS)); AstNode* node = extra->pushChild(std::make_unique<AstNode>(@$, AST_ALWAYS));
append_attr(node, $1); append_attr(node, std::move($1));
if ($2) if ($2)
node->attributes[ID::always_ff] = AstNode::mkconst_int(@2, 1, false); node->attributes[ID::always_ff] = AstNode::mkconst_int(@2, 1, false);
} always_cond { } always_cond {
@ -2449,7 +2445,7 @@ always_stmt:
} | } |
attr always_comb_or_latch { attr always_comb_or_latch {
AstNode* node = extra->pushChild(std::make_unique<AstNode>(@$, AST_ALWAYS)); AstNode* node = extra->pushChild(std::make_unique<AstNode>(@$, AST_ALWAYS));
append_attr(node, $1); append_attr(node, std::move($1));
if ($2) if ($2)
node->attributes[ID::always_latch] = AstNode::mkconst_int(@2, 1, false); node->attributes[ID::always_latch] = AstNode::mkconst_int(@2, 1, false);
else else
@ -2461,7 +2457,7 @@ always_stmt:
} | } |
attr TOK_INITIAL { attr TOK_INITIAL {
AstNode* node = extra->pushChild(std::make_unique<AstNode>(@$, AST_INITIAL)); AstNode* node = extra->pushChild(std::make_unique<AstNode>(@$, AST_INITIAL));
append_attr(node, $1); append_attr(node, std::move($1));
(void)extra->pushChild(std::make_unique<AstNode>(@$, AST_BLOCK)); (void)extra->pushChild(std::make_unique<AstNode>(@$, AST_BLOCK));
} behavioral_stmt { } behavioral_stmt {
extra->ast_stack.pop_back(); extra->ast_stack.pop_back();
@ -2702,21 +2698,21 @@ simple_behavioral_stmt:
attr lvalue TOK_EQ delay expr { attr lvalue TOK_EQ delay expr {
AstNode* node = extra->saveChild(std::make_unique<AstNode>(@$, AST_ASSIGN_EQ, std::move($2), std::move($5))); AstNode* node = extra->saveChild(std::make_unique<AstNode>(@$, AST_ASSIGN_EQ, std::move($2), std::move($5)));
SET_AST_NODE_LOC(node, @2, @5); SET_AST_NODE_LOC(node, @2, @5);
append_attr(node, $1); append_attr(node, std::move($1));
} | } |
attr lvalue attr inc_or_dec_op { attr lvalue attr inc_or_dec_op {
extra->addIncOrDecStmt($1, std::move($2), $3, $4, location_range(@1, @4)); extra->addIncOrDecStmt(std::move($1), std::move($2), std::move($3), $4, location_range(@1, @4));
} | } |
attr inc_or_dec_op attr lvalue { attr inc_or_dec_op attr lvalue {
extra->addIncOrDecStmt($1, std::move($4), $3, $2, location_range(@1, @4)); extra->addIncOrDecStmt(std::move($1), std::move($4), std::move($3), $2, location_range(@1, @4));
} | } |
attr lvalue OP_LE delay expr { attr lvalue OP_LE delay expr {
AstNode* node = extra->saveChild(std::make_unique<AstNode>(@$, AST_ASSIGN_LE, std::move($2), std::move($5))); AstNode* node = extra->saveChild(std::make_unique<AstNode>(@$, AST_ASSIGN_LE, std::move($2), std::move($5)));
SET_AST_NODE_LOC(node, @2, @5); SET_AST_NODE_LOC(node, @2, @5);
append_attr(node, $1); append_attr(node, std::move($1));
} | } |
attr lvalue asgn_binop delay expr { attr lvalue asgn_binop delay expr {
(void)extra->addAsgnBinopStmt($1, std::move($2), $3, std::move($5)); (void)extra->addAsgnBinopStmt(std::move($1), std::move($2), $3, std::move($5));
}; };
asgn_binop: asgn_binop:
@ -2790,13 +2786,11 @@ behavioral_stmt:
defattr | assert | wire_decl | param_decl | localparam_decl | typedef_decl | defattr | assert | wire_decl | param_decl | localparam_decl | typedef_decl |
non_opt_delay behavioral_stmt | non_opt_delay behavioral_stmt |
simple_behavioral_stmt TOK_SEMICOL | simple_behavioral_stmt TOK_SEMICOL |
attr TOK_SEMICOL { attr TOK_SEMICOL |
free_attr($1);
} |
attr hierarchical_id { attr hierarchical_id {
AstNode* node = extra->pushChild(std::make_unique<AstNode>(@$, AST_TCALL)); AstNode* node = extra->pushChild(std::make_unique<AstNode>(@$, AST_TCALL));
node->str = *$2; node->str = *$2;
append_attr(node, $1); append_attr(node, std::move($1));
} opt_arg_list TOK_SEMICOL{ } opt_arg_list TOK_SEMICOL{
SET_AST_NODE_LOC(extra->ast_stack.back(), @2, @5); SET_AST_NODE_LOC(extra->ast_stack.back(), @2, @5);
extra->ast_stack.pop_back(); extra->ast_stack.pop_back();
@ -2804,7 +2798,7 @@ behavioral_stmt:
attr TOK_MSG_TASKS { attr TOK_MSG_TASKS {
AstNode* node = extra->pushChild(std::make_unique<AstNode>(@$, AST_TCALL)); AstNode* node = extra->pushChild(std::make_unique<AstNode>(@$, AST_TCALL));
node->str = *$2; node->str = *$2;
append_attr(node, $1); append_attr(node, std::move($1));
} opt_arg_list TOK_SEMICOL{ } opt_arg_list TOK_SEMICOL{
SET_AST_NODE_LOC(extra->ast_stack.back(), @2, @5); SET_AST_NODE_LOC(extra->ast_stack.back(), @2, @5);
extra->ast_stack.pop_back(); extra->ast_stack.pop_back();
@ -2813,7 +2807,7 @@ behavioral_stmt:
extra->enterTypeScope(); extra->enterTypeScope();
} opt_label { } opt_label {
AstNode* node = extra->pushChild(std::make_unique<AstNode>(@$, AST_BLOCK)); AstNode* node = extra->pushChild(std::make_unique<AstNode>(@$, AST_BLOCK));
append_attr(node, $1); append_attr(node, std::move($1));
if ($4 != nullptr) if ($4 != nullptr)
node->str = *$4; node->str = *$4;
} behavioral_stmt_list TOK_END opt_label { } behavioral_stmt_list TOK_END opt_label {
@ -2834,7 +2828,7 @@ behavioral_stmt:
} | } |
attr TOK_FOR TOK_LPAREN { attr TOK_FOR TOK_LPAREN {
AstNode* node = extra->pushChild(std::make_unique<AstNode>(@$, AST_FOR)); AstNode* node = extra->pushChild(std::make_unique<AstNode>(@$, AST_FOR));
append_attr(node, $1); append_attr(node, std::move($1));
} for_initialization TOK_SEMICOL expr { } for_initialization TOK_SEMICOL expr {
extra->ast_stack.back()->children.push_back(std::move($7)); extra->ast_stack.back()->children.push_back(std::move($7));
} TOK_SEMICOL simple_behavioral_stmt TOK_RPAREN { } TOK_SEMICOL simple_behavioral_stmt TOK_RPAREN {
@ -2848,7 +2842,7 @@ behavioral_stmt:
} | } |
attr TOK_WHILE TOK_LPAREN expr TOK_RPAREN { attr TOK_WHILE TOK_LPAREN expr TOK_RPAREN {
AstNode* node = extra->pushChild(std::make_unique<AstNode>(@$, AST_WHILE)); AstNode* node = extra->pushChild(std::make_unique<AstNode>(@$, AST_WHILE));
append_attr(node, $1); append_attr(node, std::move($1));
auto block_owned = std::make_unique<AstNode>(@$, AST_BLOCK); auto block_owned = std::make_unique<AstNode>(@$, AST_BLOCK);
auto* block = block_owned.get(); auto* block = block_owned.get();
extra->ast_stack.back()->children.push_back(std::move($4)); extra->ast_stack.back()->children.push_back(std::move($4));
@ -2861,7 +2855,7 @@ behavioral_stmt:
} | } |
attr TOK_REPEAT TOK_LPAREN expr TOK_RPAREN { attr TOK_REPEAT TOK_LPAREN expr TOK_RPAREN {
AstNode* node = extra->pushChild(std::make_unique<AstNode>(@$, AST_REPEAT)); AstNode* node = extra->pushChild(std::make_unique<AstNode>(@$, AST_REPEAT));
append_attr(node, $1); append_attr(node, std::move($1));
auto block_owned = std::make_unique<AstNode>(@$, AST_BLOCK); auto block_owned = std::make_unique<AstNode>(@$, AST_BLOCK);
auto* block = block_owned.get(); auto* block = block_owned.get();
extra->ast_stack.back()->children.push_back(std::move($4)); extra->ast_stack.back()->children.push_back(std::move($4));
@ -2896,11 +2890,9 @@ behavioral_stmt:
// not parallel "else if": begin new construction // not parallel "else if": begin new construction
node_owned = std::make_unique<AstNode>(@$, AST_CASE); node_owned = std::make_unique<AstNode>(@$, AST_CASE);
node = node_owned.get(); node = node_owned.get();
append_attr(node, $1); append_attr(node, std::move($1));
node->children.push_back(node->get_bool_attribute(ID::parallel_case) ? AstNode::mkconst_int(@$, 1, false, 1) : expr->clone()); node->children.push_back(node->get_bool_attribute(ID::parallel_case) ? AstNode::mkconst_int(@$, 1, false, 1) : expr->clone());
extra->ast_stack.back()->children.push_back(std::move(node_owned)); extra->ast_stack.back()->children.push_back(std::move(node_owned));
} else {
free_attr($1);
} }
auto block_owned = std::make_unique<AstNode>(@$, AST_BLOCK); auto block_owned = std::make_unique<AstNode>(@$, AST_BLOCK);
auto* block = block_owned.get(); auto* block = block_owned.get();
@ -2921,7 +2913,7 @@ behavioral_stmt:
} | } |
case_attr case_type TOK_LPAREN expr TOK_RPAREN { case_attr case_type TOK_LPAREN expr TOK_RPAREN {
AstNode* node = extra->pushChild(std::make_unique<AstNode>(@$, AST_CASE, std::move($4))); AstNode* node = extra->pushChild(std::make_unique<AstNode>(@$, AST_CASE, std::move($4)));
append_attr(node, $1); append_attr(node, std::move($1));
SET_AST_NODE_LOC(extra->ast_stack.back(), @4, @4); SET_AST_NODE_LOC(extra->ast_stack.back(), @4, @4);
} opt_synopsys_attr case_body TOK_ENDCASE { } opt_synopsys_attr case_body TOK_ENDCASE {
SET_AST_NODE_LOC(extra->ast_stack.back(), @2, @9); SET_AST_NODE_LOC(extra->ast_stack.back(), @2, @9);
@ -2931,21 +2923,21 @@ behavioral_stmt:
if_attr: if_attr:
attr { attr {
$$ = $1; $$ = std::move($1);
} | } |
attr TOK_UNIQUE0 { attr TOK_UNIQUE0 {
AstNode *context = extra->ast_stack.back(); AstNode *context = extra->ast_stack.back();
if (context && context->type == AST_BLOCK && context->get_bool_attribute(ID::promoted_if)) if (context && context->type == AST_BLOCK && context->get_bool_attribute(ID::promoted_if))
err_at_loc(@2, "unique0 keyword cannot be used for 'else if' branch."); err_at_loc(@2, "unique0 keyword cannot be used for 'else if' branch.");
(*$1)[ID::parallel_case] = AstNode::mkconst_int(@$, 1, false); (*$1)[ID::parallel_case] = AstNode::mkconst_int(@$, 1, false);
$$ = $1; $$ = std::move($1);
} | } |
attr TOK_PRIORITY { attr TOK_PRIORITY {
AstNode *context = extra->ast_stack.back(); AstNode *context = extra->ast_stack.back();
if (context && context->type == AST_BLOCK && context->get_bool_attribute(ID::promoted_if)) if (context && context->type == AST_BLOCK && context->get_bool_attribute(ID::promoted_if))
err_at_loc(@2, "priority keyword cannot be used for 'else if' branch."); err_at_loc(@2, "priority keyword cannot be used for 'else if' branch.");
(*$1)[ID::full_case] = AstNode::mkconst_int(@$, 1, false); (*$1)[ID::full_case] = AstNode::mkconst_int(@$, 1, false);
$$ = $1; $$ = std::move($1);
} | } |
attr TOK_UNIQUE { attr TOK_UNIQUE {
AstNode *context = extra->ast_stack.back(); AstNode *context = extra->ast_stack.back();
@ -2953,25 +2945,25 @@ if_attr:
err_at_loc(@2, "unique keyword cannot be used for 'else if' branch."); err_at_loc(@2, "unique keyword cannot be used for 'else if' branch.");
(*$1)[ID::full_case] = AstNode::mkconst_int(@$, 1, false); (*$1)[ID::full_case] = AstNode::mkconst_int(@$, 1, false);
(*$1)[ID::parallel_case] = AstNode::mkconst_int(@$, 1, false); (*$1)[ID::parallel_case] = AstNode::mkconst_int(@$, 1, false);
$$ = $1; $$ = std::move($1);
}; };
case_attr: case_attr:
attr { attr {
$$ = $1; $$ = std::move($1);
} | } |
attr TOK_UNIQUE0 { attr TOK_UNIQUE0 {
(*$1)[ID::parallel_case] = AstNode::mkconst_int(@$, 1, false); (*$1)[ID::parallel_case] = AstNode::mkconst_int(@$, 1, false);
$$ = $1; $$ = std::move($1);
} | } |
attr TOK_PRIORITY { attr TOK_PRIORITY {
(*$1)[ID::full_case] = AstNode::mkconst_int(@$, 1, false); (*$1)[ID::full_case] = AstNode::mkconst_int(@$, 1, false);
$$ = $1; $$ = std::move($1);
} | } |
attr TOK_UNIQUE { attr TOK_UNIQUE {
(*$1)[ID::full_case] = AstNode::mkconst_int(@$, 1, false); (*$1)[ID::full_case] = AstNode::mkconst_int(@$, 1, false);
(*$1)[ID::parallel_case] = AstNode::mkconst_int(@$, 1, false); (*$1)[ID::parallel_case] = AstNode::mkconst_int(@$, 1, false);
$$ = $1; $$ = std::move($1);
}; };
case_type: case_type:
@ -3139,9 +3131,7 @@ module_gen_body:
gen_stmt_or_module_body_stmt: gen_stmt_or_module_body_stmt:
gen_stmt | module_body_stmt | gen_stmt | module_body_stmt |
attr TOK_SEMICOL { attr TOK_SEMICOL;
free_attr($1);
};
genvar_identifier: genvar_identifier:
TOK_ID { TOK_ID {
@ -3240,10 +3230,10 @@ expr:
$$->children.push_back(std::move($4)); $$->children.push_back(std::move($4));
$$->children.push_back(std::move($6)); $$->children.push_back(std::move($6));
SET_AST_NODE_LOC($$.get(), @1, @$); SET_AST_NODE_LOC($$.get(), @1, @$);
append_attr($$.get(), $3); append_attr($$.get(), std::move($3));
} | } |
inc_or_dec_op attr rvalue { inc_or_dec_op attr rvalue {
$$ = extra->addIncOrDecExpr(std::move($3), $2, $1, location_range(@1, @3), false, mode->sv); $$ = extra->addIncOrDecExpr(std::move($3), std::move($2), $1, location_range(@1, @3), false, mode->sv);
} | } |
// TODO: Attributes are allowed in the middle here, but they create some // TODO: Attributes are allowed in the middle here, but they create some
// non-trivial conflicts that don't seem worth solving for now. // non-trivial conflicts that don't seem worth solving for now.
@ -3305,18 +3295,18 @@ basic_expr:
node->str = *$1; node->str = *$1;
extra->ast_stack.push_back(node); extra->ast_stack.push_back(node);
SET_AST_NODE_LOC(node, @1, @1); SET_AST_NODE_LOC(node, @1, @1);
append_attr(node, $2); append_attr(node, std::move($2));
} TOK_LPAREN arg_list optional_comma TOK_RPAREN { } TOK_LPAREN arg_list optional_comma TOK_RPAREN {
$$.reset(extra->ast_stack.back()); $$.reset(extra->ast_stack.back());
extra->ast_stack.pop_back(); extra->ast_stack.pop_back();
} | } |
TOK_TO_SIGNED attr TOK_LPAREN expr TOK_RPAREN { TOK_TO_SIGNED attr TOK_LPAREN expr TOK_RPAREN {
$$ = std::make_unique<AstNode>(@$, AST_TO_SIGNED, std::move($4)); $$ = std::make_unique<AstNode>(@$, AST_TO_SIGNED, std::move($4));
append_attr($$.get(), $2); append_attr($$.get(), std::move($2));
} | } |
TOK_TO_UNSIGNED attr TOK_LPAREN expr TOK_RPAREN { TOK_TO_UNSIGNED attr TOK_LPAREN expr TOK_RPAREN {
$$ = std::make_unique<AstNode>(@$, AST_TO_UNSIGNED, std::move($4)); $$ = std::make_unique<AstNode>(@$, AST_TO_UNSIGNED, std::move($4));
append_attr($$.get(), $2); append_attr($$.get(), std::move($2));
} | } |
TOK_LPAREN expr TOK_RPAREN { TOK_LPAREN expr TOK_RPAREN {
$$ = std::move($2); $$ = std::move($2);
@ -3333,47 +3323,47 @@ basic_expr:
TOK_TILDE attr basic_expr %prec UNARY_OPS { TOK_TILDE attr basic_expr %prec UNARY_OPS {
$$ = std::make_unique<AstNode>(@$, AST_BIT_NOT, std::move($3)); $$ = std::make_unique<AstNode>(@$, AST_BIT_NOT, std::move($3));
SET_AST_NODE_LOC($$.get(), @1, @3); SET_AST_NODE_LOC($$.get(), @1, @3);
append_attr($$.get(), $2); append_attr($$.get(), std::move($2));
} | } |
basic_expr TOK_AMP attr basic_expr { basic_expr TOK_AMP attr basic_expr {
$$ = std::make_unique<AstNode>(@$, AST_BIT_AND, std::move($1), std::move($4)); $$ = std::make_unique<AstNode>(@$, AST_BIT_AND, std::move($1), std::move($4));
SET_AST_NODE_LOC($$.get(), @1, @4); SET_AST_NODE_LOC($$.get(), @1, @4);
append_attr($$.get(), $3); append_attr($$.get(), std::move($3));
} | } |
basic_expr OP_NAND attr basic_expr { basic_expr OP_NAND attr basic_expr {
$$ = std::make_unique<AstNode>(@$, AST_BIT_NOT, std::make_unique<AstNode>(@$, AST_BIT_AND, std::move($1), std::move($4))); $$ = std::make_unique<AstNode>(@$, AST_BIT_NOT, std::make_unique<AstNode>(@$, AST_BIT_AND, std::move($1), std::move($4)));
SET_AST_NODE_LOC($$.get(), @1, @4); SET_AST_NODE_LOC($$.get(), @1, @4);
append_attr($$.get(), $3); append_attr($$.get(), std::move($3));
} | } |
basic_expr TOK_PIPE attr basic_expr { basic_expr TOK_PIPE attr basic_expr {
$$ = std::make_unique<AstNode>(@$, AST_BIT_OR, std::move($1), std::move($4)); $$ = std::make_unique<AstNode>(@$, AST_BIT_OR, std::move($1), std::move($4));
SET_AST_NODE_LOC($$.get(), @1, @4); SET_AST_NODE_LOC($$.get(), @1, @4);
append_attr($$.get(), $3); append_attr($$.get(), std::move($3));
} | } |
basic_expr OP_NOR attr basic_expr { basic_expr OP_NOR attr basic_expr {
$$ = std::make_unique<AstNode>(@$, AST_BIT_NOT, std::make_unique<AstNode>(@$, AST_BIT_OR, std::move($1), std::move($4))); $$ = std::make_unique<AstNode>(@$, AST_BIT_NOT, std::make_unique<AstNode>(@$, AST_BIT_OR, std::move($1), std::move($4)));
SET_AST_NODE_LOC($$.get(), @1, @4); SET_AST_NODE_LOC($$.get(), @1, @4);
append_attr($$.get(), $3); append_attr($$.get(), std::move($3));
} | } |
basic_expr TOK_CARET attr basic_expr { basic_expr TOK_CARET attr basic_expr {
$$ = std::make_unique<AstNode>(@$, AST_BIT_XOR, std::move($1), std::move($4)); $$ = std::make_unique<AstNode>(@$, AST_BIT_XOR, std::move($1), std::move($4));
SET_AST_NODE_LOC($$.get(), @1, @4); SET_AST_NODE_LOC($$.get(), @1, @4);
append_attr($$.get(), $3); append_attr($$.get(), std::move($3));
} | } |
basic_expr OP_XNOR attr basic_expr { basic_expr OP_XNOR attr basic_expr {
$$ = std::make_unique<AstNode>(@$, AST_BIT_XNOR, std::move($1), std::move($4)); $$ = std::make_unique<AstNode>(@$, AST_BIT_XNOR, std::move($1), std::move($4));
SET_AST_NODE_LOC($$.get(), @1, @4); SET_AST_NODE_LOC($$.get(), @1, @4);
append_attr($$.get(), $3); append_attr($$.get(), std::move($3));
} | } |
TOK_AMP attr basic_expr %prec UNARY_OPS { TOK_AMP attr basic_expr %prec UNARY_OPS {
$$ = std::make_unique<AstNode>(@$, AST_REDUCE_AND, std::move($3)); $$ = std::make_unique<AstNode>(@$, AST_REDUCE_AND, std::move($3));
SET_AST_NODE_LOC($$.get(), @1, @3); SET_AST_NODE_LOC($$.get(), @1, @3);
append_attr($$.get(), $2); append_attr($$.get(), std::move($2));
} | } |
OP_NAND attr basic_expr %prec UNARY_OPS { OP_NAND attr basic_expr %prec UNARY_OPS {
$$ = std::make_unique<AstNode>(@$, AST_REDUCE_AND, std::move($3)); $$ = std::make_unique<AstNode>(@$, AST_REDUCE_AND, std::move($3));
SET_AST_NODE_LOC($$.get(), @1, @3); SET_AST_NODE_LOC($$.get(), @1, @3);
append_attr($$.get(), $2); append_attr($$.get(), std::move($2));
$$ = std::make_unique<AstNode>(@$, AST_LOGIC_NOT, std::move($$)); $$ = std::make_unique<AstNode>(@$, AST_LOGIC_NOT, std::move($$));
} | } |
TOK_PIPE attr basic_expr %prec UNARY_OPS { TOK_PIPE attr basic_expr %prec UNARY_OPS {
@ -3384,134 +3374,134 @@ basic_expr:
OP_NOR attr basic_expr %prec UNARY_OPS { OP_NOR attr basic_expr %prec UNARY_OPS {
$$ = std::make_unique<AstNode>(@$, AST_REDUCE_OR, std::move($3)); $$ = std::make_unique<AstNode>(@$, AST_REDUCE_OR, std::move($3));
SET_AST_NODE_LOC($$.get(), @1, @3); SET_AST_NODE_LOC($$.get(), @1, @3);
append_attr($$.get(), $2); append_attr($$.get(), std::move($2));
$$ = std::make_unique<AstNode>(@$, AST_LOGIC_NOT, std::move($$)); $$ = std::make_unique<AstNode>(@$, AST_LOGIC_NOT, std::move($$));
SET_AST_NODE_LOC($$.get(), @1, @3); SET_AST_NODE_LOC($$.get(), @1, @3);
} | } |
TOK_CARET attr basic_expr %prec UNARY_OPS { TOK_CARET attr basic_expr %prec UNARY_OPS {
$$ = std::make_unique<AstNode>(@$, AST_REDUCE_XOR, std::move($3)); $$ = std::make_unique<AstNode>(@$, AST_REDUCE_XOR, std::move($3));
SET_AST_NODE_LOC($$.get(), @1, @3); SET_AST_NODE_LOC($$.get(), @1, @3);
append_attr($$.get(), $2); append_attr($$.get(), std::move($2));
} | } |
OP_XNOR attr basic_expr %prec UNARY_OPS { OP_XNOR attr basic_expr %prec UNARY_OPS {
$$ = std::make_unique<AstNode>(@$, AST_REDUCE_XNOR, std::move($3)); $$ = std::make_unique<AstNode>(@$, AST_REDUCE_XNOR, std::move($3));
SET_AST_NODE_LOC($$.get(), @1, @3); SET_AST_NODE_LOC($$.get(), @1, @3);
append_attr($$.get(), $2); append_attr($$.get(), std::move($2));
} | } |
basic_expr OP_SHL attr basic_expr { basic_expr OP_SHL attr basic_expr {
$$ = std::make_unique<AstNode>(@$, AST_SHIFT_LEFT, std::move($1), std::make_unique<AstNode>(@$, AST_TO_UNSIGNED, std::move($4))); $$ = std::make_unique<AstNode>(@$, AST_SHIFT_LEFT, std::move($1), std::make_unique<AstNode>(@$, AST_TO_UNSIGNED, std::move($4)));
SET_AST_NODE_LOC($$.get(), @1, @4); SET_AST_NODE_LOC($$.get(), @1, @4);
append_attr($$.get(), $3); append_attr($$.get(), std::move($3));
} | } |
basic_expr OP_SHR attr basic_expr { basic_expr OP_SHR attr basic_expr {
$$ = std::make_unique<AstNode>(@$, AST_SHIFT_RIGHT, std::move($1), std::make_unique<AstNode>(@$, AST_TO_UNSIGNED, std::move($4))); $$ = std::make_unique<AstNode>(@$, AST_SHIFT_RIGHT, std::move($1), std::make_unique<AstNode>(@$, AST_TO_UNSIGNED, std::move($4)));
SET_AST_NODE_LOC($$.get(), @1, @4); SET_AST_NODE_LOC($$.get(), @1, @4);
append_attr($$.get(), $3); append_attr($$.get(), std::move($3));
} | } |
basic_expr OP_SSHL attr basic_expr { basic_expr OP_SSHL attr basic_expr {
$$ = std::make_unique<AstNode>(@$, AST_SHIFT_SLEFT, std::move($1), std::make_unique<AstNode>(@$, AST_TO_UNSIGNED, std::move($4))); $$ = std::make_unique<AstNode>(@$, AST_SHIFT_SLEFT, std::move($1), std::make_unique<AstNode>(@$, AST_TO_UNSIGNED, std::move($4)));
SET_AST_NODE_LOC($$.get(), @1, @4); SET_AST_NODE_LOC($$.get(), @1, @4);
append_attr($$.get(), $3); append_attr($$.get(), std::move($3));
} | } |
basic_expr OP_SSHR attr basic_expr { basic_expr OP_SSHR attr basic_expr {
$$ = std::make_unique<AstNode>(@$, AST_SHIFT_SRIGHT, std::move($1), std::make_unique<AstNode>(@$, AST_TO_UNSIGNED, std::move($4))); $$ = std::make_unique<AstNode>(@$, AST_SHIFT_SRIGHT, std::move($1), std::make_unique<AstNode>(@$, AST_TO_UNSIGNED, std::move($4)));
SET_AST_NODE_LOC($$.get(), @1, @4); SET_AST_NODE_LOC($$.get(), @1, @4);
append_attr($$.get(), $3); append_attr($$.get(), std::move($3));
} | } |
basic_expr TOK_LT attr basic_expr { basic_expr TOK_LT attr basic_expr {
$$ = std::make_unique<AstNode>(@$, AST_LT, std::move($1), std::move($4)); $$ = std::make_unique<AstNode>(@$, AST_LT, std::move($1), std::move($4));
SET_AST_NODE_LOC($$.get(), @1, @4); SET_AST_NODE_LOC($$.get(), @1, @4);
append_attr($$.get(), $3); append_attr($$.get(), std::move($3));
} | } |
basic_expr OP_LE attr basic_expr { basic_expr OP_LE attr basic_expr {
$$ = std::make_unique<AstNode>(@$, AST_LE, std::move($1), std::move($4)); $$ = std::make_unique<AstNode>(@$, AST_LE, std::move($1), std::move($4));
SET_AST_NODE_LOC($$.get(), @1, @4); SET_AST_NODE_LOC($$.get(), @1, @4);
append_attr($$.get(), $3); append_attr($$.get(), std::move($3));
} | } |
basic_expr OP_EQ attr basic_expr { basic_expr OP_EQ attr basic_expr {
$$ = std::make_unique<AstNode>(@$, AST_EQ, std::move($1), std::move($4)); $$ = std::make_unique<AstNode>(@$, AST_EQ, std::move($1), std::move($4));
SET_AST_NODE_LOC($$.get(), @1, @4); SET_AST_NODE_LOC($$.get(), @1, @4);
append_attr($$.get(), $3); append_attr($$.get(), std::move($3));
} | } |
basic_expr OP_NE attr basic_expr { basic_expr OP_NE attr basic_expr {
$$ = std::make_unique<AstNode>(@$, AST_NE, std::move($1), std::move($4)); $$ = std::make_unique<AstNode>(@$, AST_NE, std::move($1), std::move($4));
SET_AST_NODE_LOC($$.get(), @1, @4); SET_AST_NODE_LOC($$.get(), @1, @4);
append_attr($$.get(), $3); append_attr($$.get(), std::move($3));
} | } |
basic_expr OP_EQX attr basic_expr { basic_expr OP_EQX attr basic_expr {
$$ = std::make_unique<AstNode>(@$, AST_EQX, std::move($1), std::move($4)); $$ = std::make_unique<AstNode>(@$, AST_EQX, std::move($1), std::move($4));
SET_AST_NODE_LOC($$.get(), @1, @4); SET_AST_NODE_LOC($$.get(), @1, @4);
append_attr($$.get(), $3); append_attr($$.get(), std::move($3));
} | } |
basic_expr OP_NEX attr basic_expr { basic_expr OP_NEX attr basic_expr {
$$ = std::make_unique<AstNode>(@$, AST_NEX, std::move($1), std::move($4)); $$ = std::make_unique<AstNode>(@$, AST_NEX, std::move($1), std::move($4));
SET_AST_NODE_LOC($$.get(), @1, @4); SET_AST_NODE_LOC($$.get(), @1, @4);
append_attr($$.get(), $3); append_attr($$.get(), std::move($3));
} | } |
basic_expr OP_GE attr basic_expr { basic_expr OP_GE attr basic_expr {
$$ = std::make_unique<AstNode>(@$, AST_GE, std::move($1), std::move($4)); $$ = std::make_unique<AstNode>(@$, AST_GE, std::move($1), std::move($4));
SET_AST_NODE_LOC($$.get(), @1, @4); SET_AST_NODE_LOC($$.get(), @1, @4);
append_attr($$.get(), $3); append_attr($$.get(), std::move($3));
} | } |
basic_expr TOK_GT attr basic_expr { basic_expr TOK_GT attr basic_expr {
$$ = std::make_unique<AstNode>(@$, AST_GT, std::move($1), std::move($4)); $$ = std::make_unique<AstNode>(@$, AST_GT, std::move($1), std::move($4));
SET_AST_NODE_LOC($$.get(), @1, @4); SET_AST_NODE_LOC($$.get(), @1, @4);
append_attr($$.get(), $3); append_attr($$.get(), std::move($3));
} | } |
basic_expr TOK_PLUS attr basic_expr { basic_expr TOK_PLUS attr basic_expr {
$$ = std::make_unique<AstNode>(@$, AST_ADD, std::move($1), std::move($4)); $$ = std::make_unique<AstNode>(@$, AST_ADD, std::move($1), std::move($4));
SET_AST_NODE_LOC($$.get(), @1, @4); SET_AST_NODE_LOC($$.get(), @1, @4);
append_attr($$.get(), $3); append_attr($$.get(), std::move($3));
} | } |
basic_expr TOK_MINUS attr basic_expr { basic_expr TOK_MINUS attr basic_expr {
$$ = std::make_unique<AstNode>(@$, AST_SUB, std::move($1), std::move($4)); $$ = std::make_unique<AstNode>(@$, AST_SUB, std::move($1), std::move($4));
SET_AST_NODE_LOC($$.get(), @1, @4); SET_AST_NODE_LOC($$.get(), @1, @4);
append_attr($$.get(), $3); append_attr($$.get(), std::move($3));
} | } |
basic_expr TOK_ASTER attr basic_expr { basic_expr TOK_ASTER attr basic_expr {
$$ = std::make_unique<AstNode>(@$, AST_MUL, std::move($1), std::move($4)); $$ = std::make_unique<AstNode>(@$, AST_MUL, std::move($1), std::move($4));
SET_AST_NODE_LOC($$.get(), @1, @4); SET_AST_NODE_LOC($$.get(), @1, @4);
append_attr($$.get(), $3); append_attr($$.get(), std::move($3));
} | } |
basic_expr TOK_SLASH attr basic_expr { basic_expr TOK_SLASH attr basic_expr {
$$ = std::make_unique<AstNode>(@$, AST_DIV, std::move($1), std::move($4)); $$ = std::make_unique<AstNode>(@$, AST_DIV, std::move($1), std::move($4));
SET_AST_NODE_LOC($$.get(), @1, @4); SET_AST_NODE_LOC($$.get(), @1, @4);
append_attr($$.get(), $3); append_attr($$.get(), std::move($3));
} | } |
basic_expr TOK_PERC attr basic_expr { basic_expr TOK_PERC attr basic_expr {
$$ = std::make_unique<AstNode>(@$, AST_MOD, std::move($1), std::move($4)); $$ = std::make_unique<AstNode>(@$, AST_MOD, std::move($1), std::move($4));
SET_AST_NODE_LOC($$.get(), @1, @4); SET_AST_NODE_LOC($$.get(), @1, @4);
append_attr($$.get(), $3); append_attr($$.get(), std::move($3));
} | } |
basic_expr OP_POW attr basic_expr { basic_expr OP_POW attr basic_expr {
$$ = std::make_unique<AstNode>(@$, AST_POW, std::move($1), std::move($4)); $$ = std::make_unique<AstNode>(@$, AST_POW, std::move($1), std::move($4));
SET_AST_NODE_LOC($$.get(), @1, @4); SET_AST_NODE_LOC($$.get(), @1, @4);
append_attr($$.get(), $3); append_attr($$.get(), std::move($3));
} | } |
TOK_PLUS attr basic_expr %prec UNARY_OPS { TOK_PLUS attr basic_expr %prec UNARY_OPS {
$$ = std::make_unique<AstNode>(@$, AST_POS, std::move($3)); $$ = std::make_unique<AstNode>(@$, AST_POS, std::move($3));
SET_AST_NODE_LOC($$.get(), @1, @3); SET_AST_NODE_LOC($$.get(), @1, @3);
append_attr($$.get(), $2); append_attr($$.get(), std::move($2));
} | } |
TOK_MINUS attr basic_expr %prec UNARY_OPS { TOK_MINUS attr basic_expr %prec UNARY_OPS {
$$ = std::make_unique<AstNode>(@$, AST_NEG, std::move($3)); $$ = std::make_unique<AstNode>(@$, AST_NEG, std::move($3));
SET_AST_NODE_LOC($$.get(), @1, @3); SET_AST_NODE_LOC($$.get(), @1, @3);
append_attr($$.get(), $2); append_attr($$.get(), std::move($2));
} | } |
basic_expr OP_LAND attr basic_expr { basic_expr OP_LAND attr basic_expr {
$$ = std::make_unique<AstNode>(@$, AST_LOGIC_AND, std::move($1), std::move($4)); $$ = std::make_unique<AstNode>(@$, AST_LOGIC_AND, std::move($1), std::move($4));
SET_AST_NODE_LOC($$.get(), @1, @4); SET_AST_NODE_LOC($$.get(), @1, @4);
append_attr($$.get(), $3); append_attr($$.get(), std::move($3));
} | } |
basic_expr OP_LOR attr basic_expr { basic_expr OP_LOR attr basic_expr {
$$ = std::make_unique<AstNode>(@$, AST_LOGIC_OR, std::move($1), std::move($4)); $$ = std::make_unique<AstNode>(@$, AST_LOGIC_OR, std::move($1), std::move($4));
SET_AST_NODE_LOC($$.get(), @1, @4); SET_AST_NODE_LOC($$.get(), @1, @4);
append_attr($$.get(), $3); append_attr($$.get(), std::move($3));
} | } |
TOK_EXCL attr basic_expr %prec UNARY_OPS { TOK_EXCL attr basic_expr %prec UNARY_OPS {
$$ = std::make_unique<AstNode>(@$, AST_LOGIC_NOT, std::move($3)); $$ = std::make_unique<AstNode>(@$, AST_LOGIC_NOT, std::move($3));
SET_AST_NODE_LOC($$.get(), @1, @3); SET_AST_NODE_LOC($$.get(), @1, @3);
append_attr($$.get(), $2); append_attr($$.get(), std::move($2));
} | } |
TOK_SIGNED OP_CAST TOK_LPAREN expr TOK_RPAREN { TOK_SIGNED OP_CAST TOK_LPAREN expr TOK_RPAREN {
if (!mode->sv) if (!mode->sv)