Tighter parsing of statement lists and expression lists.
This commit is contained in:
parent
bd1b00ca29
commit
37111eb4a8
105
parse.y
105
parse.y
|
|
@ -19,7 +19,7 @@
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||||
*/
|
*/
|
||||||
#ifdef HAVE_CVS_IDENT
|
#ifdef HAVE_CVS_IDENT
|
||||||
#ident "$Id: parse.y,v 1.232 2007/03/22 16:08:17 steve Exp $"
|
#ident "$Id: parse.y,v 1.233 2007/04/01 23:02:03 steve Exp $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
|
|
@ -221,7 +221,7 @@ static list<perm_string>* list_from_identifier(list<perm_string>*tmp, char*id)
|
||||||
%type <expr> lpvalue
|
%type <expr> lpvalue
|
||||||
%type <expr> delay_value delay_value_simple
|
%type <expr> delay_value delay_value_simple
|
||||||
%type <exprs> delay1 delay3 delay3_opt delay_value_list
|
%type <exprs> delay1 delay3 delay3_opt delay_value_list
|
||||||
%type <exprs> expression_list
|
%type <exprs> expression_list_with_nuls expression_list_proper
|
||||||
%type <exprs> assign assign_list
|
%type <exprs> assign assign_list
|
||||||
%type <indexed_identifier> indexed_identifier
|
%type <indexed_identifier> indexed_identifier
|
||||||
|
|
||||||
|
|
@ -236,7 +236,7 @@ static list<perm_string>* list_from_identifier(list<perm_string>*tmp, char*id)
|
||||||
%type <event_expr> event_expression_list
|
%type <event_expr> event_expression_list
|
||||||
%type <event_expr> event_expression
|
%type <event_expr> event_expression
|
||||||
%type <event_statement> event_control
|
%type <event_statement> event_control
|
||||||
%type <statement> statement statement_opt
|
%type <statement> statement statement_or_null
|
||||||
%type <statement_list> statement_list
|
%type <statement_list> statement_list
|
||||||
|
|
||||||
%type <letter> spec_polarity
|
%type <letter> spec_polarity
|
||||||
|
|
@ -443,24 +443,24 @@ block_item_decls_opt
|
||||||
;
|
;
|
||||||
|
|
||||||
case_item
|
case_item
|
||||||
: expression_list ':' statement_opt
|
: expression_list_proper ':' statement_or_null
|
||||||
{ PCase::Item*tmp = new PCase::Item;
|
{ PCase::Item*tmp = new PCase::Item;
|
||||||
tmp->expr = *$1;
|
tmp->expr = *$1;
|
||||||
tmp->stat = $3;
|
tmp->stat = $3;
|
||||||
delete $1;
|
delete $1;
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
| K_default ':' statement_opt
|
| K_default ':' statement_or_null
|
||||||
{ PCase::Item*tmp = new PCase::Item;
|
{ PCase::Item*tmp = new PCase::Item;
|
||||||
tmp->stat = $3;
|
tmp->stat = $3;
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
| K_default statement_opt
|
| K_default statement_or_null
|
||||||
{ PCase::Item*tmp = new PCase::Item;
|
{ PCase::Item*tmp = new PCase::Item;
|
||||||
tmp->stat = $2;
|
tmp->stat = $2;
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
| error ':' statement_opt
|
| error ':' statement_or_null
|
||||||
{ yyerror(@1, "error: Incomprehensible case expression.");
|
{ yyerror(@1, "error: Incomprehensible case expression.");
|
||||||
yyerrok;
|
yyerrok;
|
||||||
}
|
}
|
||||||
|
|
@ -969,9 +969,14 @@ expression
|
||||||
|
|
||||||
/* Many contexts take a comma separated list of expressions. Null
|
/* Many contexts take a comma separated list of expressions. Null
|
||||||
expressions can happen anywhere in the list, so there are two
|
expressions can happen anywhere in the list, so there are two
|
||||||
extra rules for parsing and installing those nulls. */
|
extra rules in expression_list_with_nuls for parsing and
|
||||||
expression_list
|
installing those nulls.
|
||||||
: expression_list ',' expression
|
|
||||||
|
The expression_list_proper rules do not allow null items in the
|
||||||
|
expression list, so can be used where nul expressions are not allowed. */
|
||||||
|
|
||||||
|
expression_list_with_nuls
|
||||||
|
: expression_list_with_nuls ',' expression
|
||||||
{ svector<PExpr*>*tmp = new svector<PExpr*>(*$1, $3);
|
{ svector<PExpr*>*tmp = new svector<PExpr*>(*$1, $3);
|
||||||
delete $1;
|
delete $1;
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
|
|
@ -987,13 +992,25 @@ expression_list
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
| expression_list ','
|
| expression_list_with_nuls ','
|
||||||
{ svector<PExpr*>*tmp = new svector<PExpr*>(*$1, 0);
|
{ svector<PExpr*>*tmp = new svector<PExpr*>(*$1, 0);
|
||||||
delete $1;
|
delete $1;
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
expression_list_proper
|
||||||
|
: expression_list_proper ',' expression
|
||||||
|
{ svector<PExpr*>*tmp = new svector<PExpr*>(*$1, $3);
|
||||||
|
delete $1;
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
|
| expression
|
||||||
|
{ svector<PExpr*>*tmp = new svector<PExpr*>(1);
|
||||||
|
(*tmp)[0] = $1;
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
expr_primary
|
expr_primary
|
||||||
: number
|
: number
|
||||||
|
|
@ -1062,14 +1079,14 @@ expr_primary
|
||||||
function call. If a system identifier, then a system function
|
function call. If a system identifier, then a system function
|
||||||
call. */
|
call. */
|
||||||
|
|
||||||
| identifier '(' expression_list ')'
|
| identifier '(' expression_list_proper ')'
|
||||||
{ PECallFunction*tmp = new PECallFunction(*$1, *$3);
|
{ PECallFunction*tmp = new PECallFunction(*$1, *$3);
|
||||||
tmp->set_file(@1.text);
|
tmp->set_file(@1.text);
|
||||||
tmp->set_lineno(@1.first_line);
|
tmp->set_lineno(@1.first_line);
|
||||||
delete $1;
|
delete $1;
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
| SYSTEM_IDENTIFIER '(' expression_list ')'
|
| SYSTEM_IDENTIFIER '(' expression_list_proper ')'
|
||||||
{ PECallFunction*tmp = new PECallFunction(hname_t($1), *$3);
|
{ PECallFunction*tmp = new PECallFunction(hname_t($1), *$3);
|
||||||
tmp->set_file(@1.text);
|
tmp->set_file(@1.text);
|
||||||
tmp->set_lineno(@1.first_line);
|
tmp->set_lineno(@1.first_line);
|
||||||
|
|
@ -1083,14 +1100,14 @@ expr_primary
|
||||||
|
|
||||||
/* Various kinds of concatenation expressions. */
|
/* Various kinds of concatenation expressions. */
|
||||||
|
|
||||||
| '{' expression_list '}'
|
| '{' expression_list_proper '}'
|
||||||
{ PEConcat*tmp = new PEConcat(*$2);
|
{ PEConcat*tmp = new PEConcat(*$2);
|
||||||
tmp->set_file(@1.text);
|
tmp->set_file(@1.text);
|
||||||
tmp->set_lineno(@1.first_line);
|
tmp->set_lineno(@1.first_line);
|
||||||
delete $2;
|
delete $2;
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
| '{' expression '{' expression_list '}' '}'
|
| '{' expression '{' expression_list_proper '}' '}'
|
||||||
{ PExpr*rep = $2;
|
{ PExpr*rep = $2;
|
||||||
PEConcat*tmp = new PEConcat(*$4, rep);
|
PEConcat*tmp = new PEConcat(*$4, rep);
|
||||||
tmp->set_file(@1.text);
|
tmp->set_file(@1.text);
|
||||||
|
|
@ -1098,7 +1115,7 @@ expr_primary
|
||||||
delete $4;
|
delete $4;
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
| '{' expression '{' expression_list '}' error '}'
|
| '{' expression '{' expression_list_proper '}' error '}'
|
||||||
{ PExpr*rep = $2;
|
{ PExpr*rep = $2;
|
||||||
PEConcat*tmp = new PEConcat(*$4, rep);
|
PEConcat*tmp = new PEConcat(*$4, rep);
|
||||||
tmp->set_file(@1.text);
|
tmp->set_file(@1.text);
|
||||||
|
|
@ -1201,7 +1218,7 @@ function_item_list
|
||||||
/* A gate_instance is a module instantiation or a built in part
|
/* A gate_instance is a module instantiation or a built in part
|
||||||
type. In any case, the gate has a set of connections to ports. */
|
type. In any case, the gate has a set of connections to ports. */
|
||||||
gate_instance
|
gate_instance
|
||||||
: IDENTIFIER '(' expression_list ')'
|
: IDENTIFIER '(' expression_list_with_nuls ')'
|
||||||
{ lgate*tmp = new lgate;
|
{ lgate*tmp = new lgate;
|
||||||
tmp->name = $1;
|
tmp->name = $1;
|
||||||
tmp->parms = $3;
|
tmp->parms = $3;
|
||||||
|
|
@ -1211,7 +1228,7 @@ gate_instance
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
| IDENTIFIER range '(' expression_list ')'
|
| IDENTIFIER range '(' expression_list_with_nuls ')'
|
||||||
{ lgate*tmp = new lgate;
|
{ lgate*tmp = new lgate;
|
||||||
svector<PExpr*>*rng = $2;
|
svector<PExpr*>*rng = $2;
|
||||||
tmp->name = $1;
|
tmp->name = $1;
|
||||||
|
|
@ -1224,7 +1241,7 @@ gate_instance
|
||||||
delete rng;
|
delete rng;
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
| '(' expression_list ')'
|
| '(' expression_list_with_nuls ')'
|
||||||
{ lgate*tmp = new lgate;
|
{ lgate*tmp = new lgate;
|
||||||
tmp->name = "";
|
tmp->name = "";
|
||||||
tmp->parms = $2;
|
tmp->parms = $2;
|
||||||
|
|
@ -1557,7 +1574,7 @@ lpvalue
|
||||||
tmp->sel_ = PEIdent::SEL_IDX_DO;
|
tmp->sel_ = PEIdent::SEL_IDX_DO;
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
| '{' expression_list '}'
|
| '{' expression_list_proper '}'
|
||||||
{ PEConcat*tmp = new PEConcat(*$2);
|
{ PEConcat*tmp = new PEConcat(*$2);
|
||||||
tmp->set_file(@1.text);
|
tmp->set_file(@1.text);
|
||||||
tmp->set_lineno(@1.first_line);
|
tmp->set_lineno(@1.first_line);
|
||||||
|
|
@ -1831,12 +1848,15 @@ module_item
|
||||||
/* The task declaration rule matches the task declaration
|
/* The task declaration rule matches the task declaration
|
||||||
header, then pushes the function scope. This causes the
|
header, then pushes the function scope. This causes the
|
||||||
definitions in the task_body to take on the scope of the task
|
definitions in the task_body to take on the scope of the task
|
||||||
instead of the module. */
|
instead of the module. Note that these runs accept for the task
|
||||||
|
body statement_or_null, although the standard does not allow null
|
||||||
|
statements in the task body. But we continue to accept it as an
|
||||||
|
extension. */
|
||||||
|
|
||||||
| K_task IDENTIFIER ';'
|
| K_task IDENTIFIER ';'
|
||||||
{ pform_push_scope($2); }
|
{ pform_push_scope($2); }
|
||||||
task_item_list_opt
|
task_item_list_opt
|
||||||
statement_opt
|
statement_or_null
|
||||||
K_endtask
|
K_endtask
|
||||||
{ PTask*tmp = new PTask;
|
{ PTask*tmp = new PTask;
|
||||||
perm_string tmp2 = lex_strings.make($2);
|
perm_string tmp2 = lex_strings.make($2);
|
||||||
|
|
@ -1853,7 +1873,7 @@ module_item
|
||||||
{ pform_push_scope($2); }
|
{ pform_push_scope($2); }
|
||||||
'(' task_port_decl_list ')' ';'
|
'(' task_port_decl_list ')' ';'
|
||||||
task_item_list_opt
|
task_item_list_opt
|
||||||
statement_opt
|
statement_or_null
|
||||||
K_endtask
|
K_endtask
|
||||||
{ PTask*tmp = new PTask;
|
{ PTask*tmp = new PTask;
|
||||||
perm_string tmp2 = lex_strings.make($2);
|
perm_string tmp2 = lex_strings.make($2);
|
||||||
|
|
@ -2147,7 +2167,7 @@ localparam_assign_list
|
||||||
approved by WG1364 on 6/28/1998. */
|
approved by WG1364 on 6/28/1998. */
|
||||||
|
|
||||||
parameter_value_opt
|
parameter_value_opt
|
||||||
: '#' '(' expression_list ')'
|
: '#' '(' expression_list_with_nuls ')'
|
||||||
{ struct parmvalue_t*tmp = new struct parmvalue_t;
|
{ struct parmvalue_t*tmp = new struct parmvalue_t;
|
||||||
tmp->by_order = $3;
|
tmp->by_order = $3;
|
||||||
tmp->by_name = 0;
|
tmp->by_name = 0;
|
||||||
|
|
@ -2944,23 +2964,23 @@ statement
|
||||||
{ yyerrok; }
|
{ yyerrok; }
|
||||||
| K_casez '(' expression ')' error K_endcase
|
| K_casez '(' expression ')' error K_endcase
|
||||||
{ yyerrok; }
|
{ yyerrok; }
|
||||||
| K_if '(' expression ')' statement_opt %prec less_than_K_else
|
| K_if '(' expression ')' statement_or_null %prec less_than_K_else
|
||||||
{ PCondit*tmp = new PCondit($3, $5, 0);
|
{ PCondit*tmp = new PCondit($3, $5, 0);
|
||||||
tmp->set_file(@1.text);
|
tmp->set_file(@1.text);
|
||||||
tmp->set_lineno(@1.first_line);
|
tmp->set_lineno(@1.first_line);
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
| K_if '(' expression ')' statement_opt K_else statement_opt
|
| K_if '(' expression ')' statement_or_null K_else statement_or_null
|
||||||
{ PCondit*tmp = new PCondit($3, $5, $7);
|
{ PCondit*tmp = new PCondit($3, $5, $7);
|
||||||
tmp->set_file(@1.text);
|
tmp->set_file(@1.text);
|
||||||
tmp->set_lineno(@1.first_line);
|
tmp->set_lineno(@1.first_line);
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
| K_if '(' error ')' statement_opt %prec less_than_K_else
|
| K_if '(' error ')' statement_or_null %prec less_than_K_else
|
||||||
{ yyerror(@1, "error: Malformed conditional expression.");
|
{ yyerror(@1, "error: Malformed conditional expression.");
|
||||||
$$ = $5;
|
$$ = $5;
|
||||||
}
|
}
|
||||||
| K_if '(' error ')' statement_opt K_else statement_opt
|
| K_if '(' error ')' statement_or_null K_else statement_or_null
|
||||||
{ yyerror(@1, "error: Malformed conditional expression.");
|
{ yyerror(@1, "error: Malformed conditional expression.");
|
||||||
$$ = $5;
|
$$ = $5;
|
||||||
}
|
}
|
||||||
|
|
@ -2993,7 +3013,7 @@ statement
|
||||||
{ $$ = 0;
|
{ $$ = 0;
|
||||||
yyerror(@3, "error: Error in while loop condition.");
|
yyerror(@3, "error: Error in while loop condition.");
|
||||||
}
|
}
|
||||||
| delay1 statement_opt
|
| delay1 statement_or_null
|
||||||
{ PExpr*del = (*$1)[0];
|
{ PExpr*del = (*$1)[0];
|
||||||
assert($1->count() == 1);
|
assert($1->count() == 1);
|
||||||
PDelayStatement*tmp = new PDelayStatement(del, $2);
|
PDelayStatement*tmp = new PDelayStatement(del, $2);
|
||||||
|
|
@ -3001,7 +3021,7 @@ statement
|
||||||
tmp->set_lineno(@1.first_line);
|
tmp->set_lineno(@1.first_line);
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
| event_control statement_opt
|
| event_control statement_or_null
|
||||||
{ PEventStatement*tmp = $1;
|
{ PEventStatement*tmp = $1;
|
||||||
if (tmp == 0) {
|
if (tmp == 0) {
|
||||||
yyerror(@1, "error: Invalid event control.");
|
yyerror(@1, "error: Invalid event control.");
|
||||||
|
|
@ -3011,14 +3031,14 @@ statement
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| '@' '*' statement_opt
|
| '@' '*' statement_or_null
|
||||||
{ PEventStatement*tmp = new PEventStatement;
|
{ PEventStatement*tmp = new PEventStatement;
|
||||||
tmp->set_file(@1.text);
|
tmp->set_file(@1.text);
|
||||||
tmp->set_lineno(@1.first_line);
|
tmp->set_lineno(@1.first_line);
|
||||||
tmp->set_statement($3);
|
tmp->set_statement($3);
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
| '@' '(' '*' ')' statement_opt
|
| '@' '(' '*' ')' statement_or_null
|
||||||
{ PEventStatement*tmp = new PEventStatement;
|
{ PEventStatement*tmp = new PEventStatement;
|
||||||
tmp->set_file(@1.text);
|
tmp->set_file(@1.text);
|
||||||
tmp->set_lineno(@1.first_line);
|
tmp->set_lineno(@1.first_line);
|
||||||
|
|
@ -3092,7 +3112,7 @@ statement
|
||||||
tmp->set_lineno(@1.first_line);
|
tmp->set_lineno(@1.first_line);
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
| K_wait '(' expression ')' statement_opt
|
| K_wait '(' expression ')' statement_or_null
|
||||||
{ PEventStatement*tmp;
|
{ PEventStatement*tmp;
|
||||||
PEEvent*etmp = new PEEvent(PEEvent::POSITIVE, $3);
|
PEEvent*etmp = new PEEvent(PEEvent::POSITIVE, $3);
|
||||||
tmp = new PEventStatement(etmp);
|
tmp = new PEventStatement(etmp);
|
||||||
|
|
@ -3101,7 +3121,7 @@ statement
|
||||||
tmp->set_statement($5);
|
tmp->set_statement($5);
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
| SYSTEM_IDENTIFIER '(' expression_list ')' ';'
|
| SYSTEM_IDENTIFIER '(' expression_list_with_nuls ')' ';'
|
||||||
{ PCallTask*tmp = new PCallTask(hname_t($1), *$3);
|
{ PCallTask*tmp = new PCallTask(hname_t($1), *$3);
|
||||||
tmp->set_file(@1.text);
|
tmp->set_file(@1.text);
|
||||||
tmp->set_lineno(@1.first_line);
|
tmp->set_lineno(@1.first_line);
|
||||||
|
|
@ -3117,7 +3137,7 @@ statement
|
||||||
delete $1;
|
delete $1;
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
| identifier '(' expression_list ')' ';'
|
| identifier '(' expression_list_proper ')' ';'
|
||||||
{ PCallTask*tmp = new PCallTask(*$1, *$3);
|
{ PCallTask*tmp = new PCallTask(*$1, *$3);
|
||||||
tmp->set_file(@1.text);
|
tmp->set_file(@1.text);
|
||||||
tmp->set_lineno(@1.first_line);
|
tmp->set_lineno(@1.first_line);
|
||||||
|
|
@ -3125,6 +3145,19 @@ statement
|
||||||
delete $3;
|
delete $3;
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* NOTE: The standard doesn't really support an empty argument list
|
||||||
|
between parentheses, but it seems natural, and people commonly
|
||||||
|
want it. So accept it explicitly. */
|
||||||
|
|
||||||
|
| identifier '(' ')' ';'
|
||||||
|
{ svector<PExpr*>pt (0);
|
||||||
|
PCallTask*tmp = new PCallTask(*$1, pt);
|
||||||
|
tmp->set_file(@1.text);
|
||||||
|
tmp->set_lineno(@1.first_line);
|
||||||
|
delete $1;
|
||||||
|
$$ = tmp;
|
||||||
|
}
|
||||||
| identifier ';'
|
| identifier ';'
|
||||||
{ svector<PExpr*>pt (0);
|
{ svector<PExpr*>pt (0);
|
||||||
PCallTask*tmp = new PCallTask(*$1, pt);
|
PCallTask*tmp = new PCallTask(*$1, pt);
|
||||||
|
|
@ -3153,7 +3186,7 @@ statement_list
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
statement_opt
|
statement_or_null
|
||||||
: statement
|
: statement
|
||||||
| ';' { $$ = 0; }
|
| ';' { $$ = 0; }
|
||||||
;
|
;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue