Improve parsing of package scoped identifiers

In order to avoid conflicts in the grammar the lexer distinguishes between
identifiers and type identifiers. To correctly classify an identifier the
lexer needs to know in which scope a token is parsed. E.g. when the parser
encounters a package scope operator it calls `lex_in_package_scope()` to tell
the lexer which scope the following identifier should be classified in.

Currently the `lex_in_package_scope()` is only used when a type identifiers
is parsed, but on for normal identifiers. As a result it is not possible to
reference variables or function from a package scope that have the same
name as a type identifier in the current scope. E.g.

```
package P;
  int T;
endpackage

module test;
  typedef int T;
  initial $display(P::T);
endmodule
```

Another problem is that in expressions both type identifiers and signal
identifiers can be referenced. As a result there are two rules in an
expression that can be reduced

  * <PACKAGE_TYPE> :: <TYPE_IDENTIFIER>
  * <PACKAGE_TYPE> :: <IDENTIFIER>

The way the rules are formulated at the moment the parser has to use token
lookahead to decide which rule to follow before it can reduce the package
scope operator. As a result the lexer detects the token before
lex_in_package_scope() is called and the identifier does not get evaluated
in the package scope, but in the current scope. Which can cause the
identifier to be misclassified. E.g.

```
package P;
  typedef int T;
  shortint X;
endpackage

module test;
   typedef byte X;
   initial $display($bits(P::T));
   initial $display($bits(P::X));
endmodule
```

Here `P::T` gets classified as a signal identifier and `P::X` gets
classified as a type identifier.

To solve this introduce a common rule for the package scope operator. Using
the same rule everywhere allows the parser to reduce it unconditionally
without using lookahead.

Note that there are additional problems with resolving the type of a scoped
type identifiers in expressions, but this is a prerequisite to solve that.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
This commit is contained in:
Lars-Peter Clausen 2022-09-19 22:58:38 +02:00
parent 3b711ed785
commit 8d7e7b6283
1 changed files with 37 additions and 20 deletions

57
parse.y
View File

@ -700,6 +700,8 @@ static void current_function_set_statement(const YYLTYPE&loc, std::vector<Statem
%type <genvar_iter> genvar_iteration %type <genvar_iter> genvar_iteration
%type <package> package_scope
%token K_TAND %token K_TAND
%nonassoc K_PLUS_EQ K_MINUS_EQ K_MUL_EQ K_DIV_EQ K_MOD_EQ K_AND_EQ K_OR_EQ %nonassoc K_PLUS_EQ K_MINUS_EQ K_MUL_EQ K_DIV_EQ K_MOD_EQ K_AND_EQ K_OR_EQ
%nonassoc K_XOR_EQ K_LS_EQ K_RS_EQ K_RSS_EQ K_NB_TRIGGER %nonassoc K_XOR_EQ K_LS_EQ K_RS_EQ K_RSS_EQ K_NB_TRIGGER
@ -1165,19 +1167,25 @@ data_declaration /* IEEE1800-2005: A.2.1.3 */
| attribute_list_opt package_import_declaration | attribute_list_opt package_import_declaration
; ;
package_scope
: PACKAGE_IDENTIFIER K_SCOPE_RES
{ lex_in_package_scope($1);
$$ = $1;
}
;
ps_type_identifier /* IEEE1800-2017: A.9.3 */ ps_type_identifier /* IEEE1800-2017: A.9.3 */
: TYPE_IDENTIFIER : TYPE_IDENTIFIER
{ pform_set_type_referenced(@1, $1.text); { pform_set_type_referenced(@1, $1.text);
delete[]$1.text; delete[]$1.text;
$$ = $1.type; $$ = $1.type;
} }
| PACKAGE_IDENTIFIER K_SCOPE_RES | package_scope TYPE_IDENTIFIER
{ lex_in_package_scope($1); }
TYPE_IDENTIFIER
{ lex_in_package_scope(0); { lex_in_package_scope(0);
$$ = $4.type; $$ = $2.type;
delete[]$4.text; delete[]$2.text;
} }
;
/* Data types that can have packed dimensions directly attached to it */ /* Data types that can have packed dimensions directly attached to it */
packed_array_data_type /* IEEE1800-2005: A.2.2.1 */ packed_array_data_type /* IEEE1800-2005: A.2.2.1 */
@ -1977,12 +1985,19 @@ package_import_declaration /* IEEE1800-2005 A.2.1.3 */
; ;
package_import_item package_import_item
: PACKAGE_IDENTIFIER K_SCOPE_RES IDENTIFIER : package_scope IDENTIFIER
{ pform_package_import(@2, $1, $3); { lex_in_package_scope(0);
delete[]$3; pform_package_import(@1, $1, $2);
delete[]$2;
} }
| PACKAGE_IDENTIFIER K_SCOPE_RES '*' | package_scope TYPE_IDENTIFIER
{ pform_package_import(@2, $1, 0); { lex_in_package_scope(0);
pform_package_import(@1, $1, $2.text);
delete[]$2.text;
}
| package_scope '*'
{ lex_in_package_scope(0);
pform_package_import(@1, $1, 0);
} }
; ;
@ -3689,9 +3704,10 @@ expr_primary
delete nm; delete nm;
} }
| PACKAGE_IDENTIFIER K_SCOPE_RES hierarchy_identifier | package_scope hierarchy_identifier
{ $$ = pform_package_ident(@2, $1, $3); { lex_in_package_scope(0);
delete $3; $$ = pform_package_ident(@2, $1, $2);
delete $2;
} }
/* An identifier followed by an expression list in parentheses is a /* An identifier followed by an expression list in parentheses is a
@ -3723,11 +3739,11 @@ expr_primary
delete $3; delete $3;
$$ = tmp; $$ = tmp;
} }
| PACKAGE_IDENTIFIER K_SCOPE_RES IDENTIFIER '(' expression_list_with_nuls ')' | package_scope IDENTIFIER { lex_in_package_scope(0); } '(' expression_list_with_nuls ')'
{ perm_string use_name = lex_strings.make($3); { perm_string use_name = lex_strings.make($2);
PECallFunction*tmp = new PECallFunction($1, use_name, *$5); PECallFunction*tmp = new PECallFunction($1, use_name, *$5);
FILE_NAME(tmp, @3); FILE_NAME(tmp, @2);
delete[]$3; delete[]$2;
delete $5; delete $5;
$$ = tmp; $$ = tmp;
} }
@ -6342,9 +6358,10 @@ statement_item /* This is roughly statement_item in the LRM */
delete $2; delete $2;
$$ = tmp; $$ = tmp;
} }
| K_TRIGGER PACKAGE_IDENTIFIER K_SCOPE_RES hierarchy_identifier | K_TRIGGER package_scope hierarchy_identifier
{ PTrigger*tmp = pform_new_trigger(@4, $2, *$4); { lex_in_package_scope(0);
delete $4; PTrigger*tmp = pform_new_trigger(@3, $2, *$3);
delete $3;
$$ = tmp; $$ = tmp;
} }
/* FIXME: Does this need support for package resolution like above? */ /* FIXME: Does this need support for package resolution like above? */