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:
parent
e6a9b5532a
commit
7556a37859
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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 << "]";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
|
|
|||
Loading…
Reference in New Issue