diff --git a/macro/MacroBison.yy b/macro/MacroBison.yy index d1aa75dd..0addc52c 100644 --- a/macro/MacroBison.yy +++ b/macro/MacroBison.yy @@ -24,6 +24,8 @@ %{ using namespace std; +#include "MacroValue.hh" + class MacroDriver; %} @@ -49,9 +51,11 @@ class MacroDriver; { string *string_val; int int_val; + MacroValue *mv; }; %{ +#include // Pour atoi() #include "MacroDriver.hh" /* this "connects" the bison parser in the driver to the flex scanner class @@ -61,13 +65,77 @@ class MacroDriver; #define yylex driver.lexer->lex %} -%token INT_NUMBER -%token NAME +%token DEFINE +%token LPAREN RPAREN LBRACKET RBRACKET COLON EQUAL EOL + +%token INTEGER +%token NAME STRING + +%left LOGICAL_OR +%left LOGICAL_AND +%left LESS GREATER LESS_EQUAL GREATER_EQUAL EQUAL_EQUAL EXCLAMATION_EQUAL +%left TIMES DIVIDE +%left PLUS MINUS +%left UMINUS UPLUS EXCLAMATION +%left LBRACKET + +%type expr %% %start statement_list_or_nothing; -statement_list_or_nothing : /* empty */; +statement_list_or_nothing : /* empty */ + | statement_list; + +statement_list : statement EOL + | statement_list statement EOL; + +statement : expr + { *driver.out_stream << $1->toString(); delete $1; } + | DEFINE NAME EQUAL expr + { driver.env[*$2] = $4; delete $2; } + +expr : INTEGER + { $$ = new IntMV($1); } + | STRING + { $$ = new StringMV(*$1); delete $1; } + | NAME + { $$ = driver.env[*$1]->clone(); delete $1; } + | LPAREN expr RPAREN + { $$ = $2; } + | expr PLUS expr + { $$ = *$1 + *$3; delete $1; delete $3; } + | expr MINUS expr + { $$ = *$1 - *$3; delete $1; delete $3; } + | expr TIMES expr + { $$ = *$1 * *$3; delete $1; delete $3; } + | expr DIVIDE expr + { $$ = *$1 / *$3; delete $1; delete $3; } + | expr LESS expr + { $$ = *$1 < *$3; delete $1; delete $3; } + | expr GREATER expr + { $$ = *$1 > *$3; delete $1; delete $3; } + | expr LESS_EQUAL expr + { $$ = *$1 <= *$3; delete $1; delete $3; } + | expr GREATER_EQUAL expr + { $$ = *$1 >= *$3; delete $1; delete $3; } + | expr EQUAL_EQUAL expr + { $$ = *$1 == *$3; delete $1; delete $3; } + | expr EXCLAMATION_EQUAL expr + { $$ = *$1 != *$3; delete $1; delete $3; } + | expr LOGICAL_OR expr + { $$ = *$1 || *$3; delete $1; delete $3; } + | expr LOGICAL_AND expr + { $$ = *$1 && *$3; delete $1; delete $3; } + | MINUS expr %prec UMINUS + { $$ = -*$2; delete $2;} + | PLUS expr %prec UPLUS + { $$ = $2; } + | EXCLAMATION expr + { $$ = !*$2; delete $2; } + | expr LBRACKET expr RBRACKET + { $$ = (*$1)[*$3]; delete $1; delete $3; } + ; %% diff --git a/macro/MacroDriver.cc b/macro/MacroDriver.cc index 926d027a..56c0efcd 100644 --- a/macro/MacroDriver.cc +++ b/macro/MacroDriver.cc @@ -34,6 +34,7 @@ void MacroDriver::parse(const string &f, ostream &out) { file = f; + out_stream = &out; ifstream in(f.c_str(), ios::binary); diff --git a/macro/MacroDriver.hh b/macro/MacroDriver.hh index e53e0cbc..e70e758a 100644 --- a/macro/MacroDriver.hh +++ b/macro/MacroDriver.hh @@ -27,8 +27,10 @@ #include #include #include +#include #include "MacroBison.hh" +#include "MacroValue.hh" using namespace std; @@ -78,12 +80,18 @@ public: //! Stack of locations used for (possibly nested) includes stack loc_stack; + //! Environment (maps macro variables to their values) + map env; + //! Name of main file being parsed string file; //! Reference to the lexer class MacroFlex *lexer; + //! Copy of output stream + ostream *out_stream; + //! Trace scanning ? /*! If set to true before calling parse(), the flex scanner will dump a lot of debugging information. Defaults to false. */ diff --git a/macro/MacroFlex.ll b/macro/MacroFlex.ll index 6f6b7ade..8bdc68cc 100644 --- a/macro/MacroFlex.ll +++ b/macro/MacroFlex.ll @@ -49,6 +49,7 @@ typedef Macro::parser::token token; %x INCLUDE %x END_INCLUDE +%x MACRO %{ // Increments location counter for every token read @@ -96,6 +97,51 @@ typedef Macro::parser::token token; BEGIN(INITIAL); } +@ { BEGIN(MACRO); } + + +[ \t\r\f]+ { yylloc->step(); } +@ { BEGIN(INITIAL); return token::EOL; } +\n { BEGIN(INITIAL); return token::EOL; } + +[0-9]+ { + yylval->int_val = atoi(yytext); + return token::INTEGER; + } +\( { return token::LPAREN; } +\) { return token::RPAREN; } +\[ { return token::LBRACKET; } +\] { return token::RBRACKET; } +: { return token::COLON; } += { return token::EQUAL; } +[!] { return token::EXCLAMATION; } +"||" { return token::LOGICAL_OR; } +&& { return token::LOGICAL_AND; } +"<=" { return token::LESS_EQUAL; } +">=" { return token::GREATER_EQUAL; } +"<" { return token::LESS; } +">" { return token::GREATER; } +"==" { return token::EQUAL_EQUAL; } +"!=" { return token::EXCLAMATION_EQUAL; } +[+] { return token::PLUS; } +[-] { return token::MINUS; } +[*] { return token::TIMES; } +[/] { return token::DIVIDE; } + +\'[^\']*\' { + yylval->string_val = new string(yytext + 1); + yylval->string_val->resize(yylval->string_val->length() - 1); + return token::STRING; + } + +define { return token::DEFINE; } + +[A-Za-z_][A-Za-z0-9_]* { + yylval->string_val = new string(yytext); + return token::NAME; + } + + <> { /* We don't use yypop_buffer_state(), since it doesn't exist in Flex 2.5.4 (see Flex 2.5.33 info file - section 11 - for code @@ -116,9 +162,6 @@ typedef Macro::parser::token token; BEGIN(END_INCLUDE); } - /* Ignore Ctrl-M */ -(\r)+ { yylloc->step(); } - /* Copy everything else to output */ [\n]+ { yylloc->lines(yyleng); yylloc->step(); ECHO; } . { yylloc->step(); ECHO; } diff --git a/macro/MacroValue.cc b/macro/MacroValue.cc new file mode 100644 index 00000000..aa137dfa --- /dev/null +++ b/macro/MacroValue.cc @@ -0,0 +1,290 @@ +/* + * Copyright (C) 2008 Dynare Team + * + * This file is part of Dynare. + * + * Dynare is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Dynare 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 Dynare. If not, see . + */ + +#include + +#include "MacroValue.hh" + +MacroValue * +MacroValue::operator-(const MacroValue &mv) const throw (TypeError) +{ + throw TypeError("Operator - does not exist for this type"); +} + +MacroValue * +MacroValue::operator-() const throw (TypeError) +{ + throw TypeError("Operator - does not exist for this type"); +} + +MacroValue * +MacroValue::operator*(const MacroValue &mv) const throw (TypeError) +{ + throw TypeError("Operator * does not exist for this type"); +} + +MacroValue * +MacroValue::operator/(const MacroValue &mv) const throw (TypeError) +{ + throw TypeError("Operator / does not exist for this type"); +} + +MacroValue * +MacroValue::operator<(const MacroValue &mv) const throw (TypeError) +{ + throw TypeError("Operator < does not exist for this type"); +} + +MacroValue * +MacroValue::operator>(const MacroValue &mv) const throw (TypeError) +{ + throw TypeError("Operator > does not exist for this type"); +} + +MacroValue * +MacroValue::operator<=(const MacroValue &mv) const throw (TypeError) +{ + throw TypeError("Operator <= does not exist for this type"); +} + +MacroValue * +MacroValue::operator>=(const MacroValue &mv) const throw (TypeError) +{ + throw TypeError("Operator >= does not exist for this type"); +} + +MacroValue * +MacroValue::operator&&(const MacroValue &mv) const throw (TypeError) +{ + throw TypeError("Operator && does not exist for this type"); +} + +MacroValue * +MacroValue::operator||(const MacroValue &mv) const throw (TypeError) +{ + throw TypeError("Operator || does not exist for this type"); +} + +MacroValue * +MacroValue::operator!() const throw (TypeError) +{ + throw TypeError("Operator ! does not exist for this type"); +} + +MacroValue * +MacroValue::operator[](const MacroValue &mv) const throw (TypeError) +{ + throw TypeError("Operator [] does not exist for this type"); +} + +IntMV::IntMV(int value_arg) : value(value_arg) +{ +} + +MacroValue * +IntMV::operator+(const MacroValue &mv) const throw (TypeError) +{ + const IntMV *mv2 = dynamic_cast(&mv); + if (mv2 == NULL) + throw TypeError("Type mismatch for operands of + operator"); + else + return new IntMV(value + mv2->value); +} + +MacroValue * +IntMV::operator-(const MacroValue &mv) const throw (TypeError) +{ + const IntMV *mv2 = dynamic_cast(&mv); + if (mv2 == NULL) + throw TypeError("Type mismatch for operands of - operator"); + else + return new IntMV(value - mv2->value); +} + +MacroValue * +IntMV::operator-() const throw (TypeError) +{ + return new IntMV(-value); +} + +MacroValue * +IntMV::operator*(const MacroValue &mv) const throw (TypeError) +{ + const IntMV *mv2 = dynamic_cast(&mv); + if (mv2 == NULL) + throw TypeError("Type mismatch for operands of * operator"); + else + return new IntMV(value * mv2->value); +} + +MacroValue * +IntMV::operator/(const MacroValue &mv) const throw (TypeError) +{ + const IntMV *mv2 = dynamic_cast(&mv); + if (mv2 == NULL) + throw TypeError("Type mismatch for operands of / operator"); + else + return new IntMV(value / mv2->value); +} + +MacroValue * +IntMV::operator<(const MacroValue &mv) const throw (TypeError) +{ + const IntMV *mv2 = dynamic_cast(&mv); + if (mv2 == NULL) + throw TypeError("Type mismatch for operands of < operator"); + else + return new IntMV(value < mv2->value); +} + +MacroValue * +IntMV::operator>(const MacroValue &mv) const throw (TypeError) +{ + const IntMV *mv2 = dynamic_cast(&mv); + if (mv2 == NULL) + throw TypeError("Type mismatch for operands of > operator"); + else + return new IntMV(value > mv2->value); +} + +MacroValue * +IntMV::operator<=(const MacroValue &mv) const throw (TypeError) +{ + const IntMV *mv2 = dynamic_cast(&mv); + if (mv2 == NULL) + throw TypeError("Type mismatch for operands of <= operator"); + else + return new IntMV(value <= mv2->value); +} + +MacroValue * +IntMV::operator>=(const MacroValue &mv) const throw (TypeError) +{ + const IntMV *mv2 = dynamic_cast(&mv); + if (mv2 == NULL) + throw TypeError("Type mismatch for operands of >= operator"); + else + return new IntMV(value >= mv2->value); +} + +MacroValue * +IntMV::operator==(const MacroValue &mv) const throw (TypeError) +{ + const IntMV *mv2 = dynamic_cast(&mv); + if (mv2 == NULL) + throw new IntMV(0); + else + return new IntMV(value == mv2->value); +} + +MacroValue * +IntMV::operator!=(const MacroValue &mv) const throw (TypeError) +{ + const IntMV *mv2 = dynamic_cast(&mv); + if (mv2 == NULL) + throw new IntMV(1); + else + return new IntMV(value != mv2->value); +} + +MacroValue * +IntMV::operator&&(const MacroValue &mv) const throw (TypeError) +{ + const IntMV *mv2 = dynamic_cast(&mv); + if (mv2 == NULL) + throw TypeError("Type mismatch for operands of && operator"); + else + return new IntMV(value && mv2->value); +} + +MacroValue * +IntMV::operator||(const MacroValue &mv) const throw (TypeError) +{ + const IntMV *mv2 = dynamic_cast(&mv); + if (mv2 == NULL) + throw TypeError("Type mismatch for operands of || operator"); + else + return new IntMV(value || mv2->value); +} + +MacroValue * +IntMV::operator!() const throw (TypeError) +{ + return new IntMV(!value); +} + +string +IntMV::toString() const +{ + ostringstream ss; + ss << value; + return ss.str(); +} + +MacroValue * +IntMV::clone() const +{ + return new IntMV(value); +} + +StringMV::StringMV(const string &value_arg) : value(value_arg) +{ +} + +MacroValue * +StringMV::operator+(const MacroValue &mv) const throw (TypeError) +{ + const StringMV *mv2 = dynamic_cast(&mv); + if (mv2 == NULL) + throw TypeError("Type mismatch for operands of + operator"); + else + return new StringMV(value + mv2->value); +} + +MacroValue * +StringMV::operator==(const MacroValue &mv) const throw (TypeError) +{ + const StringMV *mv2 = dynamic_cast(&mv); + if (mv2 == NULL) + throw new IntMV(0); + else + return new IntMV(value == mv2->value); +} + +MacroValue * +StringMV::operator!=(const MacroValue &mv) const throw (TypeError) +{ + const StringMV *mv2 = dynamic_cast(&mv); + if (mv2 == NULL) + throw new IntMV(1); + else + return new IntMV(value != mv2->value); +} + +string +StringMV::toString() const +{ + return value; +} + +MacroValue * +StringMV::clone() const +{ + return new StringMV(value); +} diff --git a/macro/MacroValue.hh b/macro/MacroValue.hh new file mode 100644 index 00000000..31e7687c --- /dev/null +++ b/macro/MacroValue.hh @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2008 Dynare Team + * + * This file is part of Dynare. + * + * Dynare is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Dynare 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 Dynare. If not, see . + */ + +#ifndef _MACRO_VALUE_HH +#define _MACRO_VALUE_HH + +using namespace std; + +#include +#include + +class MacroValue +{ +public: + class TypeError + { + public: + const string message; + TypeError(const string &message_arg) : message(message_arg) {}; + }; + virtual MacroValue *operator+(const MacroValue &mv) const throw (TypeError) = 0; + virtual MacroValue *operator-(const MacroValue &mv) const throw (TypeError); + virtual MacroValue *operator-() const throw (TypeError); + virtual MacroValue *operator*(const MacroValue &mv) const throw (TypeError); + virtual MacroValue *operator/(const MacroValue &mv) const throw (TypeError); + virtual MacroValue *operator<(const MacroValue &mv) const throw (TypeError); + virtual MacroValue *operator>(const MacroValue &mv) const throw (TypeError); + virtual MacroValue *operator<=(const MacroValue &mv) const throw (TypeError); + virtual MacroValue *operator>=(const MacroValue &mv) const throw (TypeError); + virtual MacroValue *operator==(const MacroValue &mv) const throw (TypeError) = 0; + virtual MacroValue *operator!=(const MacroValue &mv) const throw (TypeError) = 0; + virtual MacroValue *operator&&(const MacroValue &mv) const throw (TypeError); + virtual MacroValue *operator||(const MacroValue &mv) const throw (TypeError); + virtual MacroValue *operator!() const throw (TypeError); + virtual MacroValue *operator[](const MacroValue &mv) const throw (TypeError); + virtual string toString() const = 0; + virtual MacroValue *clone() const = 0; +}; + +class IntMV : public MacroValue +{ +private: + int value; +public: + IntMV(int value_arg); + virtual MacroValue *operator+(const MacroValue &mv) const throw (TypeError); + virtual MacroValue *operator-(const MacroValue &mv) const throw (TypeError); + virtual MacroValue *operator-() const throw (TypeError); + virtual MacroValue *operator*(const MacroValue &mv) const throw (TypeError); + virtual MacroValue *operator/(const MacroValue &mv) const throw (TypeError); + virtual MacroValue *operator<(const MacroValue &mv) const throw (TypeError); + virtual MacroValue *operator>(const MacroValue &mv) const throw (TypeError); + virtual MacroValue *operator<=(const MacroValue &mv) const throw (TypeError); + virtual MacroValue *operator>=(const MacroValue &mv) const throw (TypeError); + virtual MacroValue *operator==(const MacroValue &mv) const throw (TypeError); + virtual MacroValue *operator!=(const MacroValue &mv) const throw (TypeError); + virtual MacroValue *operator&&(const MacroValue &mv) const throw (TypeError); + virtual MacroValue *operator||(const MacroValue &mv) const throw (TypeError); + virtual MacroValue *operator!() const throw (TypeError); + virtual string toString() const; + virtual MacroValue *clone() const; +}; + +class StringMV : public MacroValue +{ +private: + string value; +public: + StringMV(const string &value_arg); + virtual MacroValue *operator+(const MacroValue &mv) const throw (TypeError); +// virtual MacroValue *operator<(const MacroValue &mv) const throw (TypeError); +// virtual MacroValue *operator>(const MacroValue &mv) const throw (TypeError); +// virtual MacroValue *operator<=(const MacroValue &mv) const throw (TypeError); +// virtual MacroValue *operator>=(const MacroValue &mv) const throw (TypeError); + virtual MacroValue *operator==(const MacroValue &mv) const throw (TypeError); + virtual MacroValue *operator!=(const MacroValue &mv) const throw (TypeError); +// virtual MacroValue *operator[](const MacroValue &mv) const throw (TypeError); + virtual string toString() const; + virtual MacroValue *clone() const; +}; + +/* +class IntArrayMV : public MacroValue +{ +private: + vector values; +public: + IntArrayMV(const vector &values_arg); + virtual MacroValue *operator+(const MacroValue &mv) const throw (TypeError); + virtual MacroValue *operator==(const MacroValue &mv) const throw (TypeError); + virtual MacroValue *operator!=(const MacroValue &mv) const throw (TypeError); + virtual MacroValue *operator[](const MacroValue &mv) const throw (TypeError); + virtual string toString() const; + virtual MacroValue *clone() const; +}; + +class StringArrayMV : public MacroValue +{ +private: + vector values; +public: + StringArrayMV(const vector &values_arg); + virtual MacroValue *operator+(const MacroValue &mv) const throw (TypeError); + virtual MacroValue *operator==(const MacroValue &mv) const throw (TypeError); + virtual MacroValue *operator!=(const MacroValue &mv) const throw (TypeError); + virtual MacroValue *operator[](const MacroValue &mv) const throw (TypeError); + virtual string toString() const; + virtual MacroValue *clone() const; +}; +*/ + +#endif diff --git a/macro/Makefile b/macro/Makefile index fbf27271..8ce93aa9 100644 --- a/macro/Makefile +++ b/macro/Makefile @@ -1,6 +1,6 @@ include ../Makefile.include -OBJ = MacroFlex.o MacroBison.o MacroDriver.o +OBJ = MacroFlex.o MacroBison.o MacroDriver.o MacroValue.o libmacro.a: $(OBJ) $(AR) crs libmacro.a $(OBJ)