Skip to content

Commit 2a72a1c

Browse files
committed
Verilog: introduce scope stack
This adds a scope stack to the Verilog parser, to enable entering named scopes using the :: and member operators while parsing.
1 parent c02f2b9 commit 2a72a1c

File tree

5 files changed

+114
-52
lines changed

5 files changed

+114
-52
lines changed

src/verilog/parser.y

Lines changed: 40 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -536,8 +536,9 @@ int yyverilogerror(const char *error)
536536

537537
/* Others */
538538
%token TOK_ENDOFFILE
539-
%token TOK_NON_TYPE_IDENTIFIER
540-
%token TOK_TYPE_IDENTIFIER
539+
%token TOK_IDENTIFIER
540+
%token TOK_IDENTIFIER_PACKAGE
541+
%token TOK_IDENTIFIER_TYPE
541542
%token TOK_NUMBER // number, any base
542543
%token TOK_TIME_LITERAL // number followed by time unit
543544
%token TOK_QSTRING // quoted string
@@ -1447,8 +1448,7 @@ type_declaration:
14471448
data_type any_identifier ';'
14481449
{ $$ = $2;
14491450
// add to the scope as a type name
1450-
auto &name = PARSER.scopes.add_name(stack_expr($4).get(ID_identifier), "", verilog_scopet::TYPEDEF);
1451-
name.is_type = true;
1451+
PARSER.scopes.add_name(stack_expr($4).get(ID_identifier), "", verilog_scopet::TYPEDEF);
14521452
addswap($$, ID_type, $3);
14531453
stack_expr($4).id(ID_declarator);
14541454
mto($$, $4);
@@ -1537,7 +1537,7 @@ data_type:
15371537

15381538
// We attach a dummy id to distinguish two syntactically
15391539
// identical enum types.
1540-
auto id = PARSER.scopes.current_scope->prefix + "enum-" + PARSER.get_next_id();
1540+
auto id = PARSER.scopes.current_scope().prefix + "enum-" + PARSER.get_next_id();
15411541
stack_expr($$).set(ID_identifier, id);
15421542
}
15431543
| TOK_STRING
@@ -1568,7 +1568,7 @@ enum_name_value_opt:
15681568
;
15691569

15701570
enum_name_declaration:
1571-
TOK_NON_TYPE_IDENTIFIER enum_name_value_opt
1571+
TOK_IDENTIFIER enum_name_value_opt
15721572
{
15731573
init($$);
15741574
auto &scope = PARSER.scopes.add_name(stack_expr($1).id(), "", verilog_scopet::ENUM_NAME);
@@ -2315,8 +2315,8 @@ smv_assertion_statement:
23152315
;
23162316

23172317
smv_property_identifier_list:
2318-
TOK_NON_TYPE_IDENTIFIER
2319-
| smv_property_identifier_list ',' TOK_NON_TYPE_IDENTIFIER
2318+
TOK_IDENTIFIER
2319+
| smv_property_identifier_list ',' TOK_IDENTIFIER
23202320
;
23212321

23222322
smv_using:
@@ -2901,7 +2901,7 @@ name_of_gate_instance_opt:
29012901
| name_of_gate_instance
29022902
;
29032903

2904-
name_of_gate_instance: TOK_NON_TYPE_IDENTIFIER;
2904+
name_of_gate_instance: TOK_IDENTIFIER;
29052905

29062906
// System Verilog standard 1800-2017
29072907
// A.4.1.1 Module instantiation
@@ -2971,7 +2971,7 @@ module_instance:
29712971

29722972
name_of_instance:
29732973
{ init($$, "$_&#ANON" + PARSER.get_next_id());}
2974-
| TOK_NON_TYPE_IDENTIFIER
2974+
| TOK_IDENTIFIER
29752975
;
29762976

29772977
list_of_module_connections_opt:
@@ -4224,10 +4224,19 @@ part_select_range:
42244224

42254225
primary: primary_literal
42264226
| hierarchical_identifier_select
4227-
| package_scope hierarchical_identifier_select
4228-
{ init($$, ID_verilog_package_scope);
4227+
| package_scope
4228+
{
4229+
init($$, ID_verilog_package_scope);
4230+
// enter that scope
4231+
PARSER.scopes.enter_package_scope(stack_expr($1).id());
42294232
mto($$, $1);
4230-
mto($$, $2); }
4233+
}
4234+
hierarchical_identifier_select
4235+
{ $$ = $2;
4236+
mto($$, $3);
4237+
// exit the scope
4238+
pop_scope();
4239+
}
42314240
| concatenation
42324241
| multiple_concatenation
42334242
| function_subroutine_call
@@ -4372,15 +4381,15 @@ any_identifier:
43724381
| non_type_identifier
43734382
;
43744383

4375-
non_type_identifier: TOK_NON_TYPE_IDENTIFIER
4384+
non_type_identifier: TOK_IDENTIFIER
43764385
{ new_symbol($$, $1); }
43774386
;
43784387

4379-
block_identifier: TOK_NON_TYPE_IDENTIFIER;
4388+
block_identifier: TOK_IDENTIFIER;
43804389

4381-
class_identifier: TOK_NON_TYPE_IDENTIFIER;
4390+
class_identifier: TOK_IDENTIFIER;
43824391

4383-
constraint_identifier: TOK_NON_TYPE_IDENTIFIER;
4392+
constraint_identifier: TOK_IDENTIFIER;
43844393

43854394
edge_identifier: identifier;
43864395

@@ -4391,27 +4400,27 @@ genvar_identifier: identifier;
43914400
hierarchical_parameter_identifier: hierarchical_identifier
43924401
;
43934402

4394-
interface_identifier: TOK_NON_TYPE_IDENTIFIER;
4403+
interface_identifier: TOK_IDENTIFIER;
43954404

4396-
module_identifier: TOK_NON_TYPE_IDENTIFIER;
4405+
module_identifier: TOK_IDENTIFIER;
43974406

43984407
endmodule_identifier_opt:
43994408
/* Optional */
44004409
| TOK_COLON module_identifier
44014410
;
44024411

4403-
clocking_identifier: TOK_NON_TYPE_IDENTIFIER;
4412+
clocking_identifier: TOK_IDENTIFIER;
44044413

4405-
checker_identifier: TOK_NON_TYPE_IDENTIFIER;
4414+
checker_identifier: TOK_IDENTIFIER;
44064415

44074416
net_identifier: identifier;
44084417

4409-
package_identifier: TOK_NON_TYPE_IDENTIFIER;
4418+
package_identifier: TOK_IDENTIFIER;
44104419

44114420
package_scope: package_identifier "::"
44124421
;
44134422

4414-
param_identifier: TOK_NON_TYPE_IDENTIFIER;
4423+
param_identifier: TOK_IDENTIFIER;
44154424

44164425
port_identifier: identifier;
44174426

@@ -4424,22 +4433,22 @@ method_identifier: identifier;
44244433

44254434
signal_identifier: identifier;
44264435

4427-
type_identifier: TOK_TYPE_IDENTIFIER
4436+
type_identifier: TOK_IDENTIFIER_TYPE
44284437
{
44294438
init($$, ID_typedef_type);
44304439
auto base_name = stack_expr($1).id();
44314440
stack_expr($$).set(ID_base_name, base_name);
4432-
stack_expr($$).set(ID_identifier, PARSER.scopes.current_scope->prefix+id2string(base_name));
4441+
stack_expr($$).set(ID_identifier, PARSER.scopes.current_scope().prefix+id2string(base_name));
44334442
}
44344443
;
44354444

44364445
ps_type_identifier: type_identifier;
44374446

4438-
parameter_identifier: TOK_NON_TYPE_IDENTIFIER;
4447+
parameter_identifier: TOK_IDENTIFIER;
44394448

4440-
generate_block_identifier: TOK_NON_TYPE_IDENTIFIER;
4449+
generate_block_identifier: TOK_IDENTIFIER;
44414450

4442-
udp_identifier: TOK_NON_TYPE_IDENTIFIER;
4451+
udp_identifier: TOK_IDENTIFIER;
44434452

44444453
task_identifier: hierarchical_identifier
44454454
;
@@ -4450,7 +4459,7 @@ hierarchical_task_or_block_identifier: task_identifier;
44504459

44514460
hierarchical_tf_identifier: hierarchical_identifier;
44524461

4453-
specparam_identifier: TOK_NON_TYPE_IDENTIFIER;
4462+
specparam_identifier: TOK_IDENTIFIER;
44544463

44554464
function_identifier: hierarchical_identifier
44564465
;
@@ -4473,9 +4482,9 @@ hierarchical_variable_identifier: hierarchical_identifier;
44734482

44744483
identifier: non_type_identifier;
44754484

4476-
property_identifier: TOK_NON_TYPE_IDENTIFIER;
4485+
property_identifier: TOK_IDENTIFIER;
44774486

4478-
sequence_identifier: TOK_NON_TYPE_IDENTIFIER;
4487+
sequence_identifier: TOK_IDENTIFIER;
44794488

44804489
variable_identifier: identifier;
44814490

src/verilog/scanner.l

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,7 @@ static void preprocessor()
6565
{ newstack(yyveriloglval); \
6666
irep_idt irep_id = text; \
6767
stack_expr(yyveriloglval).id(irep_id); \
68-
auto name = PARSER.scopes.lookup(irep_id); \
69-
return name == nullptr ? TOK_NON_TYPE_IDENTIFIER : \
70-
name->is_type ? TOK_TYPE_IDENTIFIER : \
71-
TOK_NON_TYPE_IDENTIFIER; \
68+
return PARSER.scopes.identifier_token(irep_id); \
7269
}
7370
#define KEYWORD(s, x) \
7471
{ if(PARSER.parse_tree.standard >= verilog_standardt::s) \

src/verilog/verilog_scope.cpp

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@ Author: Daniel Kroening, [email protected]
88

99
#include "verilog_scope.h"
1010

11-
const verilog_scopet *verilog_scopest::lookup(irep_idt name) const
11+
#include "verilog_y.tab.h"
12+
13+
const verilog_scopet *verilog_scopest::lookup(irep_idt base_name) const
1214
{
1315
// we start from the current scope, and walk upwards to the root
14-
auto scope = current_scope;
16+
auto scope = &current_scope();
1517
while(scope != nullptr)
1618
{
17-
auto name_it = scope->scope_map.find(name);
19+
auto name_it = scope->scope_map.find(base_name);
1820
if(name_it == scope->scope_map.end())
1921
scope = scope->parent;
2022
else
@@ -24,3 +26,41 @@ const verilog_scopet *verilog_scopest::lookup(irep_idt name) const
2426
// not found, give up
2527
return nullptr;
2628
}
29+
30+
void verilog_scopest::enter_package_scope(irep_idt base_name)
31+
{
32+
// look in the global scope
33+
auto name_it = top_scope.scope_map.find(base_name);
34+
if(name_it == top_scope.scope_map.end())
35+
enter_scope(current_scope());
36+
else
37+
enter_scope(name_it->second); // found it
38+
}
39+
40+
unsigned verilog_scopest::identifier_token(irep_idt base_name) const
41+
{
42+
auto scope = lookup(base_name);
43+
if(scope == nullptr)
44+
return TOK_IDENTIFIER;
45+
else
46+
{
47+
switch(scope->kind)
48+
{
49+
// clang-format off
50+
case verilog_scopet::GLOBAL: return TOK_IDENTIFIER;
51+
case verilog_scopet::FILE: return TOK_IDENTIFIER;
52+
case verilog_scopet::PACKAGE: return TOK_IDENTIFIER_PACKAGE;
53+
case verilog_scopet::MODULE: return TOK_IDENTIFIER;
54+
case verilog_scopet::CLASS: return TOK_IDENTIFIER;
55+
case verilog_scopet::BLOCK: return TOK_IDENTIFIER;
56+
case verilog_scopet::ENUM_NAME: return TOK_IDENTIFIER;
57+
case verilog_scopet::TASK: return TOK_IDENTIFIER;
58+
case verilog_scopet::FUNCTION: return TOK_IDENTIFIER;
59+
case verilog_scopet::TYPEDEF: return TOK_IDENTIFIER_TYPE;
60+
case verilog_scopet::OTHER: return TOK_IDENTIFIER;
61+
// clang-format on
62+
}
63+
64+
UNREACHABLE;
65+
}
66+
}

src/verilog/verilog_scope.h

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ struct verilog_scopet
4747
}
4848

4949
verilog_scopet *parent = nullptr;
50-
bool is_type = false;
5150
irep_idt __base_name;
5251
std::string prefix;
5352
kindt kind;
@@ -73,42 +72,59 @@ class verilog_scopest
7372
public:
7473
using scopet = verilog_scopet;
7574

76-
scopet top_scope, *current_scope = &top_scope;
75+
scopet top_scope;
7776

7877
scopet &add_name(
7978
irep_idt _base_name,
8079
const std::string &separator,
8180
scopet::kindt kind)
8281
{
83-
auto result = current_scope->scope_map.emplace(
84-
_base_name, scopet{_base_name, separator, current_scope, kind});
82+
auto result = current_scope().scope_map.emplace(
83+
_base_name, scopet{_base_name, separator, &current_scope(), kind});
8584
return result.first->second;
8685
}
8786

88-
// Create the given sub-scope of the current scope.
87+
// Scope stack
88+
std::vector<scopet *> scope_stack = {&top_scope};
89+
90+
scopet &current_scope() const
91+
{
92+
// We never pop the top scope
93+
PRECONDITION(!scope_stack.empty());
94+
return *scope_stack.back();
95+
}
96+
97+
// find the package scope with given base name, and enter it
98+
void enter_package_scope(irep_idt base_name);
99+
100+
void enter_scope(scopet &scope)
101+
{
102+
scope_stack.push_back(&scope);
103+
}
104+
105+
// Create the given sub-scope of the current scope, and enter it.
89106
void push_scope(
90107
irep_idt _base_name,
91108
const std::string &separator,
92109
scopet::kindt kind)
93110
{
94-
current_scope = &add_name(_base_name, separator, kind);
111+
enter_scope(add_name(_base_name, separator, kind));
95112
}
96113

97114
void pop_scope()
98115
{
99-
PRECONDITION(current_scope->parent != nullptr);
100-
current_scope = current_scope->parent;
116+
// We never pop the top scope
117+
PRECONDITION(scope_stack.size() >= 2);
118+
scope_stack.pop_back();
101119
}
102120

103121
// Look up an identifier, starting from the current scope,
104122
// going upwards until found. Returns nullptr when not found.
105123
const scopet *lookup(irep_idt base_name) const;
106124

107-
bool is_type(irep_idt base_name) const
108-
{
109-
auto scope_ptr = lookup(base_name);
110-
return scope_ptr == nullptr ? false : scope_ptr->is_type;
111-
}
125+
// token to be returned by the scanner for the given identifier
126+
// in the current scope
127+
unsigned identifier_token(irep_idt base_name) const;
112128
};
113129

114130
#endif

src/vlindex/vlindex_parser.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class verilog_indexer_parsert
4848
}
4949
bool is_identifier() const
5050
{
51-
return kind == TOK_NON_TYPE_IDENTIFIER || kind == TOK_TYPE_IDENTIFIER;
51+
return kind == TOK_IDENTIFIER || kind == TOK_IDENTIFIER_TYPE;
5252
}
5353
bool is_system_identifier() const
5454
{

0 commit comments

Comments
 (0)