From 7556a37859ec32f3d472c4bcfe08bfe938124f3c Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 21 Aug 2011 16:52:18 -0700 Subject: [PATCH] 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. --- vhdlpp/debug.cc | 9 ++++ vhdlpp/expression.cc | 18 +++++++- vhdlpp/expression.h | 20 +++++++++ vhdlpp/expression_elaborate.cc | 16 +++++++ vhdlpp/expression_emit.cc | 16 +++++++ vhdlpp/parse.y | 76 ++++++++++++++++++++++++++++++---- vhdlpp/parse_types.h | 3 ++ 7 files changed, 149 insertions(+), 9 deletions(-) diff --git a/vhdlpp/debug.cc b/vhdlpp/debug.cc index 89714035c..d13acae1e 100644 --- a/vhdlpp/debug.cc +++ b/vhdlpp/debug.cc @@ -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 diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc index 8f5e0ff69..c4567e106 100644 --- a/vhdlpp/expression.cc +++ b/vhdlpp/expression.cc @@ -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) { } diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index 5ea908d03..a5385371e 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -209,6 +209,24 @@ class ExpBitstring : public Expression { std::vectorvalue_; }; +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 { diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index 828bbfc7f..30cd63f97 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -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)) diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index e0662b2db..ffc6a4461 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -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 << "]"; } diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index faf8a8fce..826b952c0 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -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 diff --git a/vhdlpp/parse_types.h b/vhdlpp/parse_types.h index 2110c6ed5..7f08c9971 100644 --- a/vhdlpp/parse_types.h +++ b/vhdlpp/parse_types.h @@ -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_;