Parse for declarations, implement for_step statements.

for-statement declarations still generate a "sorry" message, but
the for_step statements work in general now.
This commit is contained in:
Stephen Williams 2012-02-25 09:28:20 -08:00
parent cad7c74680
commit d000147392
5 changed files with 98 additions and 79 deletions

View File

@ -276,9 +276,8 @@ PForever::~PForever()
}
PForStatement::PForStatement(PExpr*n1, PExpr*e1, PExpr*cond,
PExpr*n2, PExpr*e2, Statement*st)
: name1_(n1), expr1_(e1), cond_(cond), name2_(n2), expr2_(e2),
statement_(st)
Statement*step, Statement*st)
: name1_(n1), expr1_(e1), cond_(cond), step_(step), statement_(st)
{
}

View File

@ -403,7 +403,7 @@ class PForStatement : public Statement {
public:
PForStatement(PExpr*n1, PExpr*e1, PExpr*cond,
PExpr*n2, PExpr*e2, Statement*st);
Statement*step, Statement*body);
~PForStatement();
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
@ -417,8 +417,7 @@ class PForStatement : public Statement {
PExpr*cond_;
PExpr* name2_;
PExpr* expr2_;
Statement*step_;
Statement*statement_;
};

View File

@ -3780,8 +3780,6 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
const PEIdent*id1 = dynamic_cast<const PEIdent*>(name1_);
assert(id1);
const PEIdent*id2 = dynamic_cast<const PEIdent*>(name2_);
assert(id2);
NetBlock*top = new NetBlock(NetBlock::SEQU, 0);
top->set_line(*this);
@ -3826,32 +3824,15 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
body->append(tmp);
/* Elaborate the increment assignment statement at the end of
the for loop. This is also a very specific assignment
statement. Put this into the "body" block. */
sig = des->find_signal(scope, id2->path());
if (sig == 0) {
cerr << get_fileline() << ": error: Unable to find variable "
<< id2->path() << " in for-loop increment expression." << endl;
des->errors += 1;
return body;
}
assert(sig);
lv = new NetAssign_(sig);
/* Make the r-value of the increment assignment, and size it
properly. Then use it to build the assignment statement. */
etmp = elaborate_rval_expr(des, scope, lv->expr_type(), lv->lwidth(),
expr2_);
/* Now elaborate the for_step statement. I really should do
some error checking here to make sure the step statement
really does step the variable. */
if (debug_elaborate) {
cerr << get_fileline() << ": debug: FOR increment assign: "
cerr << get_fileline() << ": debug: Elaborate for_step statement "
<< sig->name() << " = " << *etmp << endl;
}
NetAssign*step = new NetAssign(lv, etmp);
step->set_line(*this);
NetProc*step = step_->elaborate(des, scope);
body->append(step);

134
parse.y
View File

@ -524,6 +524,7 @@ static void current_task_set_statement(vector<Statement*>*s)
%type <event_expr> event_expression
%type <event_statement> event_control
%type <statement> statement statement_or_null compressed_statement
%type <statement> loop_statement for_step
%type <statement_list> statement_list statement_or_null_list
%type <statement_list> statement_list_or_null
@ -660,6 +661,19 @@ data_type /* IEEE1800-2005: A.2.2.1 */
endnew_opt : ':' K_new | ;
for_step /* IEEE1800-2005: A.6.8 */
: lpvalue '=' expression
{ PAssign*tmp = new PAssign($1,$3);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| inc_or_dec_expression
{ $$ = pform_compressed_assign_from_inc_dec(@1, $1); }
| compressed_statement
{ $$ = $1; }
;
implicit_class_handle /* IEEE1800-2005: A.8.4 */
: K_this
| K_super
@ -694,6 +708,66 @@ inc_or_dec_expression /* IEEE1800-2005: A.4.3 */
}
;
/* Loop statements are kinds of statements. */
loop_statement /* IEEE1800-2005: A.6.8 */
: K_for '(' lpvalue '=' expression ';' expression ';' for_step ')'
statement_or_null
{ PForStatement*tmp = new PForStatement($3, $5, $7, $9, $11);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| K_for '(' data_type IDENTIFIER '=' expression ';' expression ';' for_step ')'
statement_or_null
{ $$ = 0;
yyerror(@3, "sorry: for_variable_declaration not supported");
}
| K_forever statement_or_null
{ PForever*tmp = new PForever($2);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| K_repeat '(' expression ')' statement_or_null
{ PRepeat*tmp = new PRepeat($3, $5);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| K_while '(' expression ')' statement_or_null
{ PWhile*tmp = new PWhile($3, $5);
FILE_NAME(tmp, @1);
$$ = tmp;
}
/* Error forms for loop statements. */
| K_for '(' lpvalue '=' expression ';' expression ';' error ')'
statement_or_null
{ $$ = 0;
yyerror(@1, "error: Error in for loop step assignment.");
}
| K_for '(' lpvalue '=' expression ';' error ';' for_step ')'
statement_or_null
{ $$ = 0;
yyerror(@1, "error: Error in for loop condition expression.");
}
| K_for '(' error ')' statement_or_null
{ $$ = 0;
yyerror(@1, "error: Incomprehensible for loop.");
}
| K_while '(' error ')' statement_or_null
{ $$ = 0;
yyerror(@1, "error: Error in while loop condition.");
}
;
number : BASED_NUMBER
{ $$ = $1; based_size = 0;}
| DEC_NUMBER
@ -710,6 +784,16 @@ real_or_realtime
| K_realtime
;
/* Many places where statements are allowed can actually take a
statement or a null statement marked with a naked semi-colon. */
statement_or_null /* IEEE1800-2005: A.6.4 */
: statement
{ $$ = $1; }
| ';'
{ $$ = 0; }
;
/* The task declaration rule matches the task declaration
header, then pushes the function scope. This causes the
definitions in the task_body to take on the scope of the task
@ -5079,16 +5163,9 @@ statement /* This is roughly statement_item in the LRM */
delete $2;
$$ = tmp;
}
| K_forever statement
{ PForever*tmp = new PForever($2);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| K_repeat '(' expression ')' statement
{ PRepeat*tmp = new PRepeat($3, $5);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| loop_statement { $$ = $1; }
| K_case '(' expression ')' case_items K_endcase
{ PCase*tmp = new PCase(NetCase::EQ, $3, $5);
FILE_NAME(tmp, @1);
@ -5128,36 +5205,6 @@ statement /* This is roughly statement_item in the LRM */
{ yyerror(@1, "error: Malformed conditional expression.");
$$ = $5;
}
| K_for '(' lpvalue '=' expression ';' expression ';'
lpvalue '=' expression ')' statement
{ PForStatement*tmp = new PForStatement($3, $5, $7, $9, $11, $13);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| K_for '(' lpvalue '=' expression ';' expression ';'
error ')' statement
{ $$ = 0;
yyerror(@1, "error: Error in for loop step assignment.");
}
| K_for '(' lpvalue '=' expression ';' error ';'
lpvalue '=' expression ')' statement
{ $$ = 0;
yyerror(@1, "error: Error in for loop condition expression.");
}
| K_for '(' error ')' statement
{ $$ = 0;
yyerror(@1, "error: Incomprehensible for loop.");
}
| K_while '(' expression ')' statement
{ PWhile*tmp = new PWhile($3, $5);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| K_while '(' error ')' statement
{ $$ = 0;
yyerror(@1, "error: Error in while loop condition.");
}
/* SytemVerilog adds the compressed_statement */
| compressed_statement ';'
@ -5406,13 +5453,6 @@ statement_list
}
;
statement_or_null
: statement
{ $$ = $1; }
| ';'
{ $$ = 0; }
;
statement_or_null_list
: statement_or_null_list statement_or_null
{ vector<Statement*>*tmp = $1;

View File

@ -774,8 +774,8 @@ void PForever::dump(ostream&out, unsigned ind) const
void PForStatement::dump(ostream&out, unsigned ind) const
{
out << setw(ind) << "" << "for (" << *name1_ << " = " << *expr1_
<< "; " << *cond_ << "; " << *name2_ << " = " << *expr2_ <<
")" << endl;
<< "; " << *cond_ << "; <for_step>)" << endl;
step_->dump(out, ind+6);
statement_->dump(out, ind+3);
}