From 56c42dcf370a51cf83e9afe9a35a6d7fa4fa3ba3 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 4 Jul 2026 12:09:47 -0700 Subject: [PATCH] Support UDP names shadowing type identifiers SystemVerilog allows a UDP primitive or UDP port declaration to use the same name as a visible type identifier from another namespace or outer scope. The lexer reports such names as `TYPE_IDENTIFIER` before the UDP name has been installed, which made constructs such as: typedef int T; primitive T (Q, A); output Q; input A; table 0 : 0; endtable endprimitive fail in the UDP grammar. UDP primitive and port names do not have the local type/name ambiguity that exists for variable, net, or parameter declarations. Use `identifier_name` for the primitive name, the UDP port list, UDP port declarations, and the UDP initial target so a `TYPE_IDENTIFIER` token can be accepted as the UDP name. Signed-off-by: Lars-Peter Clausen --- parse.y | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/parse.y b/parse.y index 4736ce90f..1a67658d2 100644 --- a/parse.y +++ b/parse.y @@ -7650,7 +7650,7 @@ udp_sequ_entry ; udp_initial - : K_initial IDENTIFIER '=' number ';' + : K_initial identifier_name '=' number ';' { PExpr*etmp = new PENumber($4); PEIdent*itmp = new PEIdent(lex_strings.make($2), @2.lexical_pos); PAssign*atmp = new PAssign(itmp, etmp); @@ -7728,9 +7728,9 @@ udp_output_sym makes for these ports are scoped within the UDP, so there is no hierarchy involved. */ udp_port_decl - : K_input list_of_identifiers ';' + : K_input udp_port_list ';' { $$ = pform_make_udp_input_ports($2); } - | K_output IDENTIFIER ';' + | K_output identifier_name ';' { perm_string pname = lex_strings.make($2); PWire*pp = new PWire(pname, @2.lexical_pos, NetNet::IMPLICIT, NetNet::POUTPUT); vector*tmp = new std::vector(1); @@ -7738,7 +7738,7 @@ udp_port_decl $$ = tmp; delete[]$2; } - | K_reg IDENTIFIER ';' + | K_reg identifier_name ';' { perm_string pname = lex_strings.make($2); PWire*pp = new PWire(pname, @2.lexical_pos, NetNet::REG, NetNet::PIMPLICIT); vector*tmp = new std::vector(1); @@ -7746,7 +7746,7 @@ udp_port_decl $$ = tmp; delete[]$2; } - | K_output K_reg IDENTIFIER ';' + | K_output K_reg identifier_name ';' { perm_string pname = lex_strings.make($3); PWire*pp = new PWire(pname, @3.lexical_pos, NetNet::REG, NetNet::POUTPUT); vector*tmp = new std::vector(1); @@ -7771,9 +7771,9 @@ udp_port_decls ; udp_port_list - : IDENTIFIER + : identifier_name { $$ = list_from_identifier($1, @1.lexical_pos); } - | udp_port_list ',' IDENTIFIER + | udp_port_list ',' identifier_name { $$ = list_from_identifier($1, $3, @3.lexical_pos); } ; @@ -7782,9 +7782,9 @@ udp_reg_opt | { $$ = false; }; udp_input_declaration_list - : K_input IDENTIFIER + : K_input identifier_name { $$ = list_from_identifier($2, @2.lexical_pos); } - | udp_input_declaration_list ',' K_input IDENTIFIER + | udp_input_declaration_list ',' K_input identifier_name { $$ = list_from_identifier($1, $4, @4.lexical_pos); } ; @@ -7793,7 +7793,7 @@ udp_primitive format. The ports are simply names in the port list, and the declarations are in the body. */ - : K_primitive IDENTIFIER '(' udp_port_list ')' ';' + : K_primitive identifier_name '(' udp_port_list ')' ';' udp_port_decls udp_init_opt udp_body @@ -7807,8 +7807,8 @@ udp_primitive /* This is the syntax for IEEE1364-2001 format definitions. The port names and declarations are all in the parameter list. */ - | K_primitive IDENTIFIER - '(' K_output udp_reg_opt IDENTIFIER initializer_opt ',' + | K_primitive identifier_name + '(' K_output udp_reg_opt identifier_name initializer_opt ',' udp_input_declaration_list ')' ';' udp_body K_endprimitive label_opt