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:
parent
3b711ed785
commit
8d7e7b6283
57
parse.y
57
parse.y
|
|
@ -700,6 +700,8 @@ static void current_function_set_statement(const YYLTYPE&loc, std::vector<Statem
|
|||
|
||||
%type <genvar_iter> genvar_iteration
|
||||
|
||||
%type <package> package_scope
|
||||
|
||||
%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_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
|
||||
;
|
||||
|
||||
package_scope
|
||||
: PACKAGE_IDENTIFIER K_SCOPE_RES
|
||||
{ lex_in_package_scope($1);
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
|
||||
ps_type_identifier /* IEEE1800-2017: A.9.3 */
|
||||
: TYPE_IDENTIFIER
|
||||
{ pform_set_type_referenced(@1, $1.text);
|
||||
delete[]$1.text;
|
||||
$$ = $1.type;
|
||||
}
|
||||
| PACKAGE_IDENTIFIER K_SCOPE_RES
|
||||
{ lex_in_package_scope($1); }
|
||||
TYPE_IDENTIFIER
|
||||
| package_scope TYPE_IDENTIFIER
|
||||
{ lex_in_package_scope(0);
|
||||
$$ = $4.type;
|
||||
delete[]$4.text;
|
||||
$$ = $2.type;
|
||||
delete[]$2.text;
|
||||
}
|
||||
;
|
||||
|
||||
/* Data types that can have packed dimensions directly attached to it */
|
||||
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_IDENTIFIER K_SCOPE_RES IDENTIFIER
|
||||
{ pform_package_import(@2, $1, $3);
|
||||
delete[]$3;
|
||||
: package_scope IDENTIFIER
|
||||
{ lex_in_package_scope(0);
|
||||
pform_package_import(@1, $1, $2);
|
||||
delete[]$2;
|
||||
}
|
||||
| PACKAGE_IDENTIFIER K_SCOPE_RES '*'
|
||||
{ pform_package_import(@2, $1, 0);
|
||||
| package_scope TYPE_IDENTIFIER
|
||||
{ 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;
|
||||
}
|
||||
|
||||
| PACKAGE_IDENTIFIER K_SCOPE_RES hierarchy_identifier
|
||||
{ $$ = pform_package_ident(@2, $1, $3);
|
||||
delete $3;
|
||||
| package_scope hierarchy_identifier
|
||||
{ lex_in_package_scope(0);
|
||||
$$ = pform_package_ident(@2, $1, $2);
|
||||
delete $2;
|
||||
}
|
||||
|
||||
/* An identifier followed by an expression list in parentheses is a
|
||||
|
|
@ -3723,11 +3739,11 @@ expr_primary
|
|||
delete $3;
|
||||
$$ = tmp;
|
||||
}
|
||||
| PACKAGE_IDENTIFIER K_SCOPE_RES IDENTIFIER '(' expression_list_with_nuls ')'
|
||||
{ perm_string use_name = lex_strings.make($3);
|
||||
| package_scope IDENTIFIER { lex_in_package_scope(0); } '(' expression_list_with_nuls ')'
|
||||
{ perm_string use_name = lex_strings.make($2);
|
||||
PECallFunction*tmp = new PECallFunction($1, use_name, *$5);
|
||||
FILE_NAME(tmp, @3);
|
||||
delete[]$3;
|
||||
FILE_NAME(tmp, @2);
|
||||
delete[]$2;
|
||||
delete $5;
|
||||
$$ = tmp;
|
||||
}
|
||||
|
|
@ -6342,9 +6358,10 @@ statement_item /* This is roughly statement_item in the LRM */
|
|||
delete $2;
|
||||
$$ = tmp;
|
||||
}
|
||||
| K_TRIGGER PACKAGE_IDENTIFIER K_SCOPE_RES hierarchy_identifier
|
||||
{ PTrigger*tmp = pform_new_trigger(@4, $2, *$4);
|
||||
delete $4;
|
||||
| K_TRIGGER package_scope hierarchy_identifier
|
||||
{ lex_in_package_scope(0);
|
||||
PTrigger*tmp = pform_new_trigger(@3, $2, *$3);
|
||||
delete $3;
|
||||
$$ = tmp;
|
||||
}
|
||||
/* FIXME: Does this need support for package resolution like above? */
|
||||
|
|
|
|||
Loading…
Reference in New Issue