diff --git a/vhdlpp/Makefile.in b/vhdlpp/Makefile.in index d52a703fc..c5abc4d69 100644 --- a/vhdlpp/Makefile.in +++ b/vhdlpp/Makefile.in @@ -60,7 +60,7 @@ LIBS = @LIBS@ @EXTRALIBS@ M = StringHeap.o LineInfo.o O = main.o architec.o compiler.o entity.o entity_elaborate.o \ - lexor.o lexor_keyword.o parse.o vhdlreal.o vhdlint.o $M + expression.o lexor.o lexor_keyword.o parse.o vhdlreal.o vhdlint.o debug.o $M all: dep vhdlpp@EXEEXT@ diff --git a/vhdlpp/architec.cc b/vhdlpp/architec.cc index 76491cb2f..d27bcb229 100644 --- a/vhdlpp/architec.cc +++ b/vhdlpp/architec.cc @@ -18,8 +18,11 @@ */ # include "architec.h" +# include "expression.h" -Architecture::Architecture(perm_string name, std::list&s) +using namespace std; + +Architecture::Architecture(perm_string name, list&s) : name_(name) { statements_.splice(statements_.end(), s); @@ -37,11 +40,16 @@ Architecture::Statement::~Statement() { } -SignalAssignment::SignalAssignment(perm_string targ_name) +SignalAssignment::SignalAssignment(perm_string targ_name, list&rv) : target_name_(targ_name) { + rval_.splice(rval_.end(), rv); } SignalAssignment::~SignalAssignment() { + for (list::iterator cur = rval_.begin() + ; cur != rval_.end() ; ++cur) { + delete *cur; + } } diff --git a/vhdlpp/architec.h b/vhdlpp/architec.h index 55eb02931..90659d04f 100644 --- a/vhdlpp/architec.h +++ b/vhdlpp/architec.h @@ -23,6 +23,8 @@ # include "LineInfo.h" # include +class Expression; + /* * The Architecture class carries the contents (name, statements, * etc.) of a parsed VHDL architecture. These objects are ultimately @@ -71,13 +73,14 @@ class Architecture : public LineInfo { class SignalAssignment : public Architecture::Statement { public: - SignalAssignment(perm_string target_name); + SignalAssignment(perm_string target_name, std::list&rval); ~SignalAssignment(); virtual void dump(ostream&out) const; private: perm_string target_name_; + std::list rval_; }; #endif diff --git a/vhdlpp/debug.cc b/vhdlpp/debug.cc index aa8eb2fe2..3cba11096 100644 --- a/vhdlpp/debug.cc +++ b/vhdlpp/debug.cc @@ -20,8 +20,10 @@ # include "entity.h" # include "architec.h" +# include "expression.h" # include # include +# include static ostream& operator << (ostream&out, port_mode_t that) { @@ -95,5 +97,52 @@ void Architecture::Statement::dump(ostream&out) const void SignalAssignment::dump(ostream&out) const { out << " SignalAssignment file=" << get_fileline() << endl; - out << " " << target_name_ << " <= " << endl; + out << " " << target_name_ << " <= ..." << endl; + + for (list::const_iterator cur = rval_.begin() + ; cur != rval_.end() ; ++cur) { + (*cur)->dump(out, 5); + } +} + +void Expression::dump(ostream&out, int indent) const +{ + out << setw(indent) << "" << "Expression [" << typeid(*this).name() << "]" + << " at " << get_fileline()<< endl; +} + +void ExpLogical::dump(ostream&out, int indent) const +{ + const char*fun_name = "?"; + switch (fun_) { + case AND: + fun_name = "AND"; + break; + case OR: + fun_name = "OR"; + break; + case NAND: + fun_name = "NAND"; + break; + case NOR: + fun_name = "NOR"; + break; + case XOR: + fun_name = "XOR"; + break; + case XNOR: + fun_name = "XNOR"; + break; + } + + out << setw(indent) << "" << "Logical " << fun_name + << " at " << get_fileline() << endl; + operand1_->dump(out, indent+4); + operand2_->dump(out, indent+4); +} + +void ExpName::dump(ostream&out, int indent) const +{ + out << setw(indent) << "" << "ExpName(\"" << name_ << "\")" + << " at " << get_fileline() << endl; } diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc new file mode 100644 index 000000000..3a08b33b9 --- /dev/null +++ b/vhdlpp/expression.cc @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2011 Stephen Williams (steve@icarus.com) + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form under the terms of the GNU + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +# include "expression.h" + +Expression::Expression() +{ +} + +Expression::~Expression() +{ +} + +ExpLogical::ExpLogical(ExpLogical::fun_t ty, Expression*op1, Expression*op2) +: fun_(ty), operand1_(op1), operand2_(op2) +{ +} + +ExpLogical::~ExpLogical() +{ + delete operand1_; + delete operand2_; +} + +ExpName::ExpName(perm_string nn) +: name_(nn) +{ +} + +ExpName::~ExpName() +{ +} diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h new file mode 100644 index 000000000..8ef663826 --- /dev/null +++ b/vhdlpp/expression.h @@ -0,0 +1,78 @@ +#ifndef __expression_H +#define __expression_H +/* + * Copyright (c) 2011 Stephen Williams (steve@icarus.com) + * + * This source code is free software; you can redistribute it + * and/or modify it in source code form under the terms of the GNU + * General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +# include "StringHeap.h" +# include "LineInfo.h" + +/* + * The Expression class represents parsed expressions from the parsed + * VHDL input. The Expression class is a virtual class that holds more + * specific derived expression types. + */ +class Expression : public LineInfo { + + public: + Expression(); + virtual ~Expression() =0; + + virtual void dump(ostream&out, int indent) const; + + private: + + private: // Not implemented + Expression(const Expression&); + Expression& operator = (const Expression&); +}; + +class ExpLogical : public Expression { + + public: + enum fun_t { AND, OR, NAND, NOR, XOR, XNOR }; + + public: + ExpLogical(ExpLogical::fun_t ty, Expression*op1, Expression*op2); + ~ExpLogical(); + + void dump(ostream&out, int indent) const; + + private: + fun_t fun_; + Expression*operand1_; + Expression*operand2_; +}; + +/* + * The ExpName class represents an expression that is an identifier or + * other sort of name. + */ +class ExpName : public Expression { + + public: + ExpName(perm_string nn); + ~ExpName(); + + void dump(ostream&out, int indent) const; + + private: + perm_string name_; +}; + +#endif diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 7f31cb917..ebec95bbf 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -26,6 +26,7 @@ # include "parse_api.h" # include "parse_misc.h" # include "architec.h" +# include "expression.h" # include # include @@ -46,9 +47,13 @@ int parse_errors = 0; %union { port_mode_t port_mode; char*text; + vhdlint* integer; vhdlreal* real; + Expression*expr; + std::list* expr_list; + InterfacePort*interface_element; std::list* interface_list; @@ -98,6 +103,10 @@ int parse_errors = 0; %type concurrent_statement concurrent_signal_assignment_statement %type architecture_statement_part +%type expression expression_logical factor primary relation +%type shift_expression simple_expression term waveform_element + +%type waveform waveform_elements %% /* The design_file is the root for the VHDL parse. */ @@ -142,11 +151,12 @@ architecture_statement_part concurrent_signal_assignment_statement : IDENTIFIER LEQ waveform ';' { perm_string targ_name = lex_strings.make($1); - SignalAssignment*tmp = new SignalAssignment(targ_name); + SignalAssignment*tmp = new SignalAssignment(targ_name, *$3); FILE_NAME(tmp, @1); $$ = tmp; delete[]$1; + delete $3; } ; @@ -221,14 +231,43 @@ entity_header expression : expression_logical + { $$ = $1; } ; expression_logical : relation K_and relation + { ExpLogical*tmp = new ExpLogical(ExpLogical::AND, $1, $3); + FILE_NAME(tmp, @2); + $$ = tmp; + } | relation K_or relation + { ExpLogical*tmp = new ExpLogical(ExpLogical::OR, $1, $3); + FILE_NAME(tmp, @2); + $$ = tmp; + } + | relation K_xor relation + { ExpLogical*tmp = new ExpLogical(ExpLogical::XOR, $1, $3); + FILE_NAME(tmp, @2); + $$ = tmp; + } + | relation K_nand relation + { ExpLogical*tmp = new ExpLogical(ExpLogical::NAND, $1, $3); + FILE_NAME(tmp, @2); + $$ = tmp; + } + | relation K_nor relation + { ExpLogical*tmp = new ExpLogical(ExpLogical::NOR, $1, $3); + FILE_NAME(tmp, @2); + $$ = tmp; + } + | relation K_xnor relation + { ExpLogical*tmp = new ExpLogical(ExpLogical::XNOR, $1, $3); + FILE_NAME(tmp, @2); + $$ = tmp; + } ; -factor : primary ; +factor : primary { $$ = $1; } ; /* The interface_element is also an interface_declaration */ interface_element @@ -289,9 +328,14 @@ port_clause primary : IDENTIFIER + { ExpName*tmp = new ExpName(lex_strings.make($1)); + FILE_NAME(tmp, @1); + delete[]$1; + $$ = tmp; + } ; -relation : shift_expression ; +relation : shift_expression { $$ = $1; } ; selected_name : IDENTIFIER '.' K_all @@ -303,11 +347,11 @@ selected_names | selected_name ; -shift_expression : simple_expression ; +shift_expression : simple_expression { $$ = $1; } ; -simple_expression : term ; +simple_expression : term { $$ = $1; } ; -term : factor ; +term : factor { $$ = $1; } ; use_clause : K_use selected_names ';' @@ -317,17 +361,29 @@ use_clause waveform : waveform_elements + { $$ = $1; } | K_unaffected + { $$ = 0; } ; waveform_elements : waveform_elements ',' waveform_element + { std::list*tmp = $1; + tmp->push_back($3); + $$ = tmp; + } | waveform_element + { std::list*tmp = new std::list; + tmp->push_back($1); + $$ = tmp; + } ; waveform_element : expression + { $$ = $1; } | K_null + { $$ = 0; } ; /* Some keywords are optional in some contexts. In all such cases, a diff --git a/vhdlpp/parse_wrap.h b/vhdlpp/parse_wrap.h index 2a91204bb..08315d467 100644 --- a/vhdlpp/parse_wrap.h +++ b/vhdlpp/parse_wrap.h @@ -29,6 +29,7 @@ # include "vhdlint.h" # include "vhdlreal.h" # include "architec.h" +# include "expression.h" # include "parse.h" #endif