diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index 2c42aa44e..fdc218652 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -215,6 +215,8 @@ class ExpAggregate : public Expression { size_t count_choices() const { return fields_.size(); } void map_choices(choice_element*dst); + inline Expression* extract_expression() { return val_; } + void dump(ostream&out, int indent) const; private: diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 8b519537e..844a7c307 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -139,6 +139,47 @@ const VType*parse_type_by_name(perm_string name) return active_scope->find_type(name); } +// This funciton is called when an aggregate expression is detected by +// the parser. It makes the ExpAggregate. It also tries to detect the +// special case that the aggregate is really a primary. The problem is +// that this: +// ( ) +// also matches the pattern: +// ( [ choices => ] ... ) +// so try to assume that a single expression in parentheses is a +// primary and fix the parse by returning an Expression instead of an +// ExpAggregate. +static Expression*aggregate_or_primary(const YYLTYPE&loc, std::list*el) +{ + if (el->size() != 1) { + ExpAggregate*tmp = new ExpAggregate(el); + FILE_NAME(tmp,loc); + return tmp; + } + + ExpAggregate::element_t*el1 = el->front(); + if (el1->count_choices() > 0) { + ExpAggregate*tmp = new ExpAggregate(el); + FILE_NAME(tmp,loc); + return tmp; + } + + return el1->extract_expression(); +} + +static list* record_elements(list*names, + const VType*type) +{ + list*res = new list; + + for (list::iterator cur = names->begin() + ; cur != names->end() ; ++cur) { + res->push_back(new VTypeRecord::element_t(*cur, type)); + } + + return res; +} + %} @@ -185,6 +226,8 @@ const VType*parse_type_by_name(perm_string name) ExpAggregate::element_t*element; std::list*element_list; + std::list*record_elements; + std::list* interface_list; Architecture::Statement* arch_statement; @@ -264,8 +307,11 @@ const VType*parse_type_by_name(perm_string name) %type association_list port_map_aspect port_map_aspect_opt %type generic_map_aspect generic_map_aspect_opt +%type composite_type_definition record_type_definition %type subtype_indication type_definition +%type element_declaration element_declaration_list + %type architecture_body_start package_declaration_start %type identifier_opt identifier_colon_opt logical_name suffix %type logical_name_list identifier_list @@ -595,6 +641,17 @@ component_specification } ; +composite_type_definition + /* constrained_array_definition */ + : K_array index_constraint K_of subtype_indication + { VTypeArray*tmp = new VTypeArray($4, $2); + delete $2; + $$ = tmp; + } + | record_type_definition + { $$ = $1; } + ; + concurrent_signal_assignment_statement : name LEQ waveform ';' { ExpName*name = dynamic_cast ($1); @@ -699,6 +756,19 @@ constant_declaration { sorrymsg(@1, "Deferred constant declarations not supported\n"); delete $2; } + + /* Some error handling... */ + + | K_constant identifier_list ':' subtype_indication VASSIGN error ';' + { // The syntax allows mutliple names to have the same type/value. + errormsg(@6, "Error in value expression for constants.\n"); + yyerrok; + for (std::list::iterator cur = $2->begin() + ; cur != $2->end() ; ++cur) { + active_scope->bind_name(*cur, $4, 0); + } + delete $2; + } ; context_clause : context_items | ; @@ -732,6 +802,10 @@ element_association { ExpAggregate::element_t*tmp = new ExpAggregate::element_t($1, $3); $$ = tmp; } + | expression + { ExpAggregate::element_t*tmp = new ExpAggregate::element_t(0, $1); + $$ = tmp; + } ; element_association_list @@ -747,6 +821,21 @@ element_association_list } ; +element_declaration + : identifier_list ':' subtype_indication ';' + { $$ = record_elements($1, $3); } + ; + +element_declaration_list + : element_declaration_list element_declaration + { $$ = $1; + $$->splice($$->end(), *$2); + delete $2; + } + | element_declaration + { $$ = $1; } + ; + /* As an entity is declared, add it to the map of design entities. */ entity_aspect : K_entity name @@ -1372,7 +1461,12 @@ package_declarative_item : component_declaration | constant_declaration | subtype_declaration + | type_declaration | use_clause + | error ';' + { errormsg(@1, "Syntax error in package declarative item.\n"); + yyerrok; + } ; package_declarative_items @@ -1479,7 +1573,10 @@ primary delete[]$1; $$ = tmp; } - +/*XXXX Caught up in element_association_list? + | '(' expression ')' + { $$ = $2; } +*/ /* 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 @@ -1489,11 +1586,10 @@ primary $$ = 0; } - | '(' expression ')' - { $$ = $2; } + /* Aggregates */ + | '(' element_association_list ')' - { ExpAggregate*tmp = new ExpAggregate($2); - FILE_NAME(tmp,@1); + { Expression*tmp = aggregate_or_primary(@1, $2); $$ = tmp; } ; @@ -1638,6 +1734,13 @@ range_list } ; +record_type_definition + : K_record element_declaration_list K_end K_record + { VTypeRecord*tmp = new VTypeRecord($2); + $$ = tmp; + } + ; + relation : shift_expression { $$ = $1; } @@ -1911,12 +2014,9 @@ type_definition delete $2; $$ = tmp; } - /* constrained_array_definition */ - | K_array index_constraint K_of subtype_indication - { VTypeArray*tmp = new VTypeArray($4, $2); - delete $2; - $$ = tmp; - } + | composite_type_definition + { $$ = $1; } + ; use_clause diff --git a/vhdlpp/vtype.cc b/vhdlpp/vtype.cc index 4a8e4ced7..25f669813 100644 --- a/vhdlpp/vtype.cc +++ b/vhdlpp/vtype.cc @@ -162,6 +162,43 @@ void VTypeEnum::show(ostream&out) const out << ")"; } +VTypeRecord::VTypeRecord(std::list*elements) +: elements_(elements->size()) +{ + for (size_t idx = 0 ; idx < elements_.size() ; idx += 1) { + elements_[idx] = elements->front(); + elements->pop_front(); + } + delete elements; +} + +VTypeRecord::~VTypeRecord() +{ + for (size_t idx = 0 ; idx < elements_.size() ; idx += 1) + delete elements_[idx]; +} + +void VTypeRecord::show(ostream&out) const +{ + out << "record "; + for (size_t idx = 0 ; idx < elements_.size() ; idx += 1) { + elements_[idx]->show(out); + out << "; "; + } + out << "endrecord"; +} + +VTypeRecord::element_t::element_t(perm_string name, const VType*typ) +: name_(name), type_(typ) +{ +} + +void VTypeRecord::element_t::show(ostream&out) const +{ + out << name_ << ":"; + type_->show(out); +} + VTypeDef::VTypeDef(perm_string nam, const VType*typ) : name_(nam), type_(typ) { diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index 2e0f96d2a..bdda995ed 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -198,6 +198,38 @@ class VTypeEnum : public VType { std::vectornames_; }; +class VTypeRecord : public VType { + + public: + class element_t { + public: + element_t(perm_string name, const VType*type); + + void show(std::ostream&) const; + + private: + perm_string name_; + const VType*type_; + + private:// Not implement + element_t(const element_t&); + element_t& operator= (const element_t); + }; + + public: + explicit VTypeRecord(std::list*elements); + ~VTypeRecord(); + + void show(std::ostream&) const; + + int emit_def(std::ostream&out, perm_string name) const; + private: + int emit_decl(std::ostream&out, perm_string name, bool reg_flag) const; + + private: + std::vector elements_; +}; + class VTypeDef : public VType { public: diff --git a/vhdlpp/vtype_emit.cc b/vhdlpp/vtype_emit.cc index e9a59c3b0..e6042f0e7 100644 --- a/vhdlpp/vtype_emit.cc +++ b/vhdlpp/vtype_emit.cc @@ -159,6 +159,20 @@ int VTypeRange::emit_decl(ostream&out, perm_string name, bool reg_flag) const return errors; } +int VTypeRecord::emit_def(ostream&out, perm_string name) const +{ + int errors = 0; + assert(0); + return errors; +} + +int VTypeRecord::emit_decl(ostream&out, perm_string name, bool reg_flag) const +{ + int errors = 0; + assert(0); + return errors; +} + int VTypeDef::emit_def(ostream&out, perm_string name) const { int errors = 0;