Parse function calls, and detect type case expressions.

Type cast expressions and some function calls are syntactically
identical to array element select, so we can only tell the difference
by looking up the name of the identifier being selected. If it is a
type name, then create an ExpCast instead of an ExpName object.

Also, parse and emit vector part selects.
This commit is contained in:
Stephen Williams 2011-08-21 16:52:18 -07:00
parent e6a9b5532a
commit 7556a37859
7 changed files with 149 additions and 9 deletions

View File

@ -219,6 +219,13 @@ void ExpBitstring::dump(ostream&out, int indent) const
out << "\"" << endl;
}
void ExpCast::dump(ostream&out, int indent) const
{
out << setw(indent) << "" << "Cast to " << *res_type_
<< " at " << get_fileline() << endl;
arg_->dump(out, indent+4);
}
void ExpCharacter::dump(ostream&out, int indent) const
{
out << setw(indent) << "" << "Character '" << value_ << "'"
@ -302,6 +309,8 @@ void ExpName::dump(ostream&out, int indent) const
<< " at " << get_fileline() << endl;
if (index_)
index_->dump(out, indent+6);
if (lsb_)
lsb_->dump(out, indent+6);
}
void ExpNameALL::dump(ostream&out, int indent) const

View File

@ -184,6 +184,15 @@ ExpBitstring::~ExpBitstring()
{
}
ExpCast::ExpCast(const VType*typ, Expression*arg)
: res_type_(typ), arg_(arg)
{
}
ExpCast::~ExpCast()
{
}
ExpCharacter::ExpCharacter(char val)
: value_(val)
{
@ -249,12 +258,17 @@ ExpLogical::~ExpLogical()
}
ExpName::ExpName(perm_string nn)
: name_(nn), index_(0)
: name_(nn), index_(0), lsb_(0)
{
}
ExpName::ExpName(perm_string nn, Expression*ix)
: name_(nn), index_(ix)
: name_(nn), index_(ix), lsb_(0)
{
}
ExpName::ExpName(perm_string nn, Expression*msb, Expression*lsb)
: name_(nn), index_(msb), lsb_(lsb)
{
}

View File

@ -209,6 +209,24 @@ class ExpBitstring : public Expression {
std::vector<char>value_;
};
class ExpCast : public Expression {
public:
ExpCast(const VType*typ, Expression*arg);
~ExpCast();
const VType*probe_type(Entity*ent, Architecture*arc) const;
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
int emit(ostream&out, Entity*ent, Architecture*arc);
void dump(ostream&out, int indent = 0) const;
private:
// This is the target, result type to cast to.
const VType*res_type_;
// This is the expression being cast.
Expression*arg_;
};
class ExpCharacter : public Expression {
public:
@ -320,6 +338,7 @@ class ExpName : public Expression {
public:
explicit ExpName(perm_string nn);
ExpName(perm_string nn, Expression*index);
ExpName(perm_string nn, Expression*msb, Expression*lsb);
~ExpName();
public: // Base methods
@ -337,6 +356,7 @@ class ExpName : public Expression {
private:
perm_string name_;
Expression*index_;
Expression*lsb_;
};
class ExpNameALL : public ExpName {

View File

@ -180,6 +180,19 @@ int ExpBitstring::elaborate_expr(Entity*, Architecture*, const VType*)
return errors;
}
const VType* ExpCast::probe_type(Entity*, Architecture*) const
{
return res_type_;
}
int ExpCast::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
{
int errors = 0;
const VType*sub_type = arg_->probe_type(ent, arc);
errors += arg_->elaborate_expr(ent, arc, sub_type);
return errors;
}
int ExpCharacter::elaborate_expr(Entity*, Architecture*, const VType*ltype)
{
assert(ltype != 0);
@ -254,6 +267,9 @@ const VType* ExpName::probe_type(Entity*ent, Architecture*arc) const
if (Signal*sig = arc->find_signal(name_))
return sig->peek_type();
if (Variable*var = arc->find_variable(name_))
return var->peek_type();
const VType*ctype = 0;
Expression*cval = 0;
if (arc->find_constant(name_, ctype, cval))

View File

@ -145,6 +145,17 @@ int ExpBitstring::emit(ostream&out, Entity*, Architecture*)
return errors;
}
int ExpCast::emit(ostream&out, Entity*ent, Architecture*arc)
{
int errors = 0;
cerr << get_fileline() << ": sorry: I do not know how to emit cast expressions yet." << endl;
errors += 1;
out << "/* Cast to type=" << *res_type_ << " */ ";
errors += arg_->emit(out, ent, arc);
return errors;
}
int ExpCharacter::emit_primitive_bit_(ostream&out, Entity*, Architecture*,
const VTypePrimitive*etype)
{
@ -298,6 +309,11 @@ int ExpName::emit(ostream&out, Entity*ent, Architecture*arc)
if (index_) {
out << "[";
errors += index_->emit(out, ent, arc);
if (lsb_) {
out << ":";
errors += lsb_->emit(out, ent, arc);
}
out << "]";
}

View File

@ -471,6 +471,11 @@ choice
{ $$ = 0; }
;
choices
: choices '|' choice
| choice
;
component_configuration
: K_for component_specification
binding_indication_semicolon_opt
@ -573,6 +578,12 @@ concurrent_signal_assignment_statement
$$ = 0;
yyerrok;
}
| error LEQ waveform ';'
{ errormsg(@1, "Syntax error in l-value of signal assignment.\n");
yyerrok;
delete $3;
$$ = 0;
}
;
concurrent_statement
@ -669,6 +680,15 @@ design_units
/* Indicate the direction as a flag, with "downto" being TRUE. */
direction : K_to { $$ = false; } | K_downto { $$ = true; } ;
element_association
: choices ARROW expression
;
element_association_list
: element_association_list ',' element_association
| element_association
;
/* As an entity is declared, add it to the map of design entities. */
entity_aspect
: K_entity name
@ -1104,8 +1124,24 @@ name
delete[]$1;
$$ = tmp;
}
/* Note that this rule can match array element selects and various
function calls. The only way we can tell the difference is from
left context, namely whether the name is a type name or function
name. If none of the above, treat it as a array element select. */
| IDENTIFIER '(' expression ')'
{ ExpName*tmp = new ExpName(lex_strings.make($1), $3);
{ perm_string name = lex_strings.make($1);
delete[]$1;
if (const VType*type = active_scope->find_type(name)) {
ExpCast*tmp = new ExpCast(type, $3);
$$ = tmp;
} else {
ExpName*tmp = new ExpName(name, $3);
$$ = tmp;
}
FILE_NAME($$, @1);
}
| IDENTIFIER '(' range ')'
{ ExpName*tmp = new ExpName(lex_strings.make($1), $3->msb(), $3->lsb());
FILE_NAME(tmp, @1);
delete[]$1;
$$ = tmp;
@ -1275,9 +1311,9 @@ primary
}
| STRING_LITERAL
{ ExpString*tmp = new ExpString($1);
FILE_NAME(tmp,@1);
delete[]$1;
$$ = tmp;
FILE_NAME(tmp,@1);
delete[]$1;
$$ = tmp;
}
| BITSTRING_LITERAL
{ ExpBitstring*tmp = new ExpBitstring($1);
@ -1285,8 +1321,22 @@ primary
delete[]$1;
$$ = tmp;
}
/* This catches function calls that use association lists for the
argument list. The position argument list is discovered elsewhere
and must be discovered by elaboration (thanks to the ambiguity of
VHDL syntax). */
| IDENTIFIER '(' association_list ')'
{ sorrymsg(@1, "Function calls not supported\n");
$$ = 0;
}
| '(' expression ')'
{ $$ = $2; }
| '(' element_association_list ')'
{ sorrymsg(@1, "Aggregate expressions not supported\n");
$$ = 0;
}
;
primary_unit
@ -1404,11 +1454,11 @@ process_sensitivity_list
| name_list
{ $$ = $1; }
;
range
: simple_expression direction simple_expression
{
range_t* tmp = new range_t($1, $3, $2);
$$ = tmp;
{ range_t* tmp = new range_t($1, $3, $2);
$$ = tmp;
}
;
@ -1683,6 +1733,18 @@ variable_assignment_statement
FILE_NAME(tmp, @1);
$$ = tmp;
}
| name VASSIGN error ';'
{ errormsg(@3, "Syntax error in r-value expression of assignment.\n");
yyerrok;
delete $1;
$$ = 0;
}
| error VASSIGN expression ';'
{ errormsg(@1, "Syntax error in l-value expression of assignment.\n");
yyerrok;
delete $3;
$$ = 0;
}
;
waveform

View File

@ -74,6 +74,9 @@ class range_t {
~range_t() { delete left_; delete right_; }
void dump(ostream&out, int indent) const;
Expression*msb() { return direction_? left_ : right_; }
Expression*lsb() { return direction_? right_: left_; }
private:
Expression *left_, *right_;
bool direction_;