diff --git a/preprocessor/macro/MacroBison.yy b/preprocessor/macro/MacroBison.yy index 64848d141..d3c379543 100644 --- a/preprocessor/macro/MacroBison.yy +++ b/preprocessor/macro/MacroBison.yy @@ -65,8 +65,8 @@ class MacroDriver; #define yylex driver.lexer->lex %} -%token DEFINE -%token LPAREN RPAREN LBRACKET RBRACKET COLON EQUAL EOL +%token DEFINE LINE +%token LPAREN RPAREN LBRACKET RBRACKET EQUAL EOL %token INTEGER %token NAME STRING @@ -80,6 +80,8 @@ class MacroDriver; %left UMINUS UPLUS EXCLAMATION %left LBRACKET +%nonassoc COLON + %type expr array_expr %% @@ -95,6 +97,8 @@ statement : expr { *driver.out_stream << $1->toString(); delete $1; } | DEFINE NAME EQUAL expr { driver.env[*$2] = $4; delete $2; } + | LINE STRING INTEGER + /* Ignore @line declarations */ expr : INTEGER { $$ = new IntMV($1); } @@ -138,6 +142,8 @@ expr : INTEGER { $$ = (*$1)[*$3]; delete $1; delete $3; } | LBRACKET array_expr RBRACKET { $$ = $2; } + | expr COLON expr + { $$ = IntMV::new_range(*$1, *$3); delete $1; delete $3; } ; array_expr : expr diff --git a/preprocessor/macro/MacroFlex.ll b/preprocessor/macro/MacroFlex.ll index a1ba2ca97..01fe1f55c 100644 --- a/preprocessor/macro/MacroFlex.ll +++ b/preprocessor/macro/MacroFlex.ll @@ -62,9 +62,6 @@ typedef Macro::parser::token token; yylloc->step(); %} - /* Ignore @line declarations, replace them by a blank line */ -^@line[^\r\n]*(\r)?\n { yylloc->lines(1); yylloc->step(); *yyout << endl; } - ^@include[ \t]+\" BEGIN(INCLUDE); [^\"\r\n]* { @@ -102,7 +99,7 @@ typedef Macro::parser::token token; [ \t\r\f]+ { yylloc->step(); } @ { BEGIN(INITIAL); return token::EOL; } -\n { BEGIN(INITIAL); return token::EOL; } +\n { BEGIN(INITIAL); yylloc->lines(1); yylloc->step(); *yyout << endl; return token::EOL; } [0-9]+ { yylval->int_val = atoi(yytext); @@ -129,12 +126,13 @@ typedef Macro::parser::token token; [*] { 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; } +line { return token::LINE; } define { return token::DEFINE; } [A-Za-z_][A-Za-z0-9_]* { diff --git a/preprocessor/macro/MacroValue.cc b/preprocessor/macro/MacroValue.cc index b8e0d0753..fbb3e449c 100644 --- a/preprocessor/macro/MacroValue.cc +++ b/preprocessor/macro/MacroValue.cc @@ -95,6 +95,12 @@ MacroValue::operator[](const MacroValue &mv) const throw (TypeError) throw TypeError("Operator [] does not exist for this type"); } +MacroValue * +MacroValue::append(const MacroValue &mv) const +{ + throw TypeError("Cannot append an array at the end of another one. Should use concatenation."); +} + IntMV::IntMV(int value_arg) : value(value_arg) { } @@ -109,8 +115,7 @@ 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); + return new IntMV(value + mv2->value); } MacroValue * @@ -119,8 +124,7 @@ 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); + return new IntMV(value - mv2->value); } MacroValue * @@ -135,8 +139,7 @@ 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); + return new IntMV(value * mv2->value); } MacroValue * @@ -145,8 +148,7 @@ 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); + return new IntMV(value / mv2->value); } MacroValue * @@ -155,8 +157,7 @@ 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); + return new IntMV(value < mv2->value); } MacroValue * @@ -165,8 +166,7 @@ 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); + return new IntMV(value > mv2->value); } MacroValue * @@ -175,8 +175,7 @@ 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); + return new IntMV(value <= mv2->value); } MacroValue * @@ -185,8 +184,7 @@ 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); + return new IntMV(value >= mv2->value); } MacroValue * @@ -194,7 +192,7 @@ IntMV::operator==(const MacroValue &mv) const throw (TypeError) { const IntMV *mv2 = dynamic_cast(&mv); if (mv2 == NULL) - throw new IntMV(0); + return new IntMV(0); else return new IntMV(value == mv2->value); } @@ -204,7 +202,7 @@ IntMV::operator!=(const MacroValue &mv) const throw (TypeError) { const IntMV *mv2 = dynamic_cast(&mv); if (mv2 == NULL) - throw new IntMV(1); + return new IntMV(1); else return new IntMV(value != mv2->value); } @@ -215,8 +213,7 @@ 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); + return new IntMV(value && mv2->value); } MacroValue * @@ -225,8 +222,7 @@ 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); + return new IntMV(value || mv2->value); } MacroValue * @@ -263,12 +259,33 @@ IntMV::append(const MacroValue &array) const const ArrayMV *array2 = dynamic_cast *>(&array); if (array2 == NULL) throw TypeError("Type mismatch for append operation"); - else + + vector v(array2->values); + v.push_back(value); + return new ArrayMV(v); +} + +MacroValue * +IntMV::new_range(const MacroValue &mv1, const MacroValue &mv2) throw (TypeError) +{ + const IntMV *mv1i = dynamic_cast(&mv1); + const IntMV *mv2i = dynamic_cast(&mv2); + if (mv1i == NULL || mv2i == NULL) + throw TypeError("Arguments of range operator (:) must be integers"); + + int v1 = mv1i->value; + int v2 = mv2i->value; + + vector result; + if (v2 < v1) { - vector v(array2->values); - v.push_back(value); - return new ArrayMV(v); + int x = v2; + v2 = v1; + v1 = x; } + for(; v1 <= v2; v1++) + result.push_back(v1); + return new ArrayMV(result); } StringMV::StringMV(const string &value_arg) : value(value_arg) @@ -285,8 +302,7 @@ 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); + return new StringMV(value + mv2->value); } MacroValue * @@ -294,7 +310,7 @@ StringMV::operator==(const MacroValue &mv) const throw (TypeError) { const StringMV *mv2 = dynamic_cast(&mv); if (mv2 == NULL) - throw new IntMV(0); + return new IntMV(0); else return new IntMV(value == mv2->value); } @@ -304,7 +320,7 @@ StringMV::operator!=(const MacroValue &mv) const throw (TypeError) { const StringMV *mv2 = dynamic_cast(&mv); if (mv2 == NULL) - throw new IntMV(1); + return new IntMV(1); else return new IntMV(value != mv2->value); } @@ -351,10 +367,8 @@ StringMV::append(const MacroValue &array) const const ArrayMV *array2 = dynamic_cast *>(&array); if (array2 == NULL) throw TypeError("Type mismatch for append operation"); - else - { - vector v(array2->values); - v.push_back(value); - return new ArrayMV(v); - } + + vector v(array2->values); + v.push_back(value); + return new ArrayMV(v); } diff --git a/preprocessor/macro/MacroValue.hh b/preprocessor/macro/MacroValue.hh index cdac2db5e..c029ce3ed 100644 --- a/preprocessor/macro/MacroValue.hh +++ b/preprocessor/macro/MacroValue.hh @@ -26,9 +26,11 @@ using namespace std; #include #include +//! Base class for representing values in macro language class MacroValue { public: + //! Exception thrown when type error occurs in macro language class TypeError { public: @@ -36,39 +38,88 @@ public: TypeError(const string &message_arg) : message(message_arg) {}; }; virtual ~MacroValue(); + //! Applies + operator + /*! Returns a newly allocated value */ virtual MacroValue *operator+(const MacroValue &mv) const throw (TypeError) = 0; + //! Applies - operator + /*! Returns a newly allocated value */ virtual MacroValue *operator-(const MacroValue &mv) const throw (TypeError); + //! Applies unary - operator + /*! Returns a newly allocated value */ virtual MacroValue *operator-() const throw (TypeError); + //! Applies * operator + /*! Returns a newly allocated value */ virtual MacroValue *operator*(const MacroValue &mv) const throw (TypeError); + //! Applies / operator + /*! Returns a newly allocated value */ virtual MacroValue *operator/(const MacroValue &mv) const throw (TypeError); + //! Less comparison + /*! Returns a newly allocated IntMV, equal to 0 or 1 */ virtual MacroValue *operator<(const MacroValue &mv) const throw (TypeError); + //! Greater comparision + /*! Returns a newly allocated IntMV, equal to 0 or 1 */ virtual MacroValue *operator>(const MacroValue &mv) const throw (TypeError); + //! Less or equal comparison + /*! Returns a newly allocated IntMV, equal to 0 or 1 */ virtual MacroValue *operator<=(const MacroValue &mv) const throw (TypeError); + //! Greater or equal comparison + /*! Returns a newly allocated IntMV, equal to 0 or 1 */ virtual MacroValue *operator>=(const MacroValue &mv) const throw (TypeError); + //! Equal comparison + /*! Returns a newly allocated IntMV, equal to 0 or 1 */ virtual MacroValue *operator==(const MacroValue &mv) const throw (TypeError) = 0; + //! Not equal comparison + /*! Returns a newly allocated IntMV, equal to 0 or 1 */ virtual MacroValue *operator!=(const MacroValue &mv) const throw (TypeError) = 0; + //! Applies && operator + /*! Returns a newly allocated value */ virtual MacroValue *operator&&(const MacroValue &mv) const throw (TypeError); + //! Applies || operator + /*! Returns a newly allocated value */ virtual MacroValue *operator||(const MacroValue &mv) const throw (TypeError); + //! Applies unary ! operator + /*! Returns a newly allocated value */ virtual MacroValue *operator!() const throw (TypeError); + //! Applies [] operator + /*! Returns a newly allocated value */ virtual MacroValue *operator[](const MacroValue &mv) const throw (TypeError); + //! Converts value to string virtual string toString() const = 0; + //! Clones value + /*! Returns a newly allocated value */ virtual MacroValue *clone() const = 0; + //! Converts value to array form + /*! Returns a newly allocated array value */ virtual MacroValue *toArray() const = 0; - virtual MacroValue *append(const MacroValue &array) const = 0; + //! Appends value at the end of an array + /*! The first argument must be an array. Returns a newly allocated array. */ + virtual MacroValue *append(const MacroValue &array) const; }; +//! Represents an integer value in macro language class IntMV : public MacroValue { friend class StringMV; private: + //! Underlying integer value int value; public: IntMV(int value_arg); virtual ~IntMV(); + //! Computes arithmetic addition + /*! Returns a newly allocated value */ virtual MacroValue *operator+(const MacroValue &mv) const throw (TypeError); + //! Computes arithmetic substraction + /*! Returns a newly allocated value */ virtual MacroValue *operator-(const MacroValue &mv) const throw (TypeError); + //! Computes opposite + /*! Returns a newly allocated value */ virtual MacroValue *operator-() const throw (TypeError); + //! Computes arithmetic multiplication + /*! Returns a newly allocated value */ virtual MacroValue *operator*(const MacroValue &mv) const throw (TypeError); + //! Computes arithmetic division + /*! Returns a newly allocated value */ 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); @@ -76,41 +127,63 @@ public: 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); + //! Computes logical and + /*! Returns a newly allocated value */ virtual MacroValue *operator&&(const MacroValue &mv) const throw (TypeError); + //! Computes logical or + /*! Returns a newly allocated value */ virtual MacroValue *operator||(const MacroValue &mv) const throw (TypeError); + //! Computes logical negation + /*! Returns a newly allocated value */ virtual MacroValue *operator!() const throw (TypeError); virtual string toString() const; virtual MacroValue *clone() const; + //! Converts value to array form + /*! Returns a newly allocated integer array containing a single value */ virtual MacroValue *toArray() const; + //! Appends value at the end of an array + /*! The first argument must be an integer array. Returns a newly allocated integer array. */ virtual MacroValue *append(const MacroValue &array) const; + //! Creates a integer range + /*! Arguments must be of type IntMV. + Returns a newly allocated integer array containing all integers between mv1 and mv2. + If mv2 < mv1, constructs the range in decreasing order. + */ + static MacroValue *new_range(const MacroValue &mv1, const MacroValue &mv2) throw (TypeError); }; +//! Represents a string value in macro language class StringMV : public MacroValue { private: + //! Underlying string value string value; public: StringMV(const string &value_arg); virtual ~StringMV(); + //! Computes string concatenation + /*! Returns a newly allocated value */ 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); //! Subscripting operator - /*! - Argument must be an ArrayMV. Indexes begin at 1. - \todo Add bound error checking + /*! Argument must be an ArrayMV. Indexes begin at 1. + Returns a newly allocated string. + \todo Add bound error checking */ virtual MacroValue *operator[](const MacroValue &mv) const throw (TypeError); + //! Returns underlying string value virtual string toString() const; virtual MacroValue *clone() const; + //! Converts value to array form + /*! Returns a newly allocated string array containing a single value */ virtual MacroValue *toArray() const; + //! Appends value at the end of an array + /*! The first argument must be a string array. Returns a newly allocated string array. */ virtual MacroValue *append(const MacroValue &array) const; }; +//! Represents an array in macro language template class ArrayMV : public MacroValue { @@ -118,23 +191,28 @@ class ArrayMV : public MacroValue friend class StringMV; friend class ArrayMV; // Necessary for operator[] to access values of integer array when subscripting a string array private: + //! Underlying vector vector values; public: ArrayMV(const vector &values_arg); virtual ~ArrayMV(); + //! Computes array concatenation + /*! Both array must be of same type + Returns a newly allocated array */ 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); //! Subscripting operator - /*! - Argument must be an ArrayMV. Indexes begin at 1. - \todo Add bound error checking + /*! Argument must be an ArrayMV. Indexes begin at 1. + Returns a newly allocated array. + \todo Add bound error checking */ virtual MacroValue *operator[](const MacroValue &mv) const throw (TypeError); + //! Returns a string containing the concatenation of string representations of elements virtual string toString() const; virtual MacroValue *clone() const; + //! Returns itself virtual MacroValue *toArray() const; - virtual MacroValue *append(const MacroValue &array) const; }; template @@ -154,14 +232,10 @@ ArrayMV::operator+(const MacroValue &mv) const throw (TypeError) const ArrayMV *mv2 = dynamic_cast *>(&mv); if (mv2 == NULL) throw TypeError("Type mismatch for operands of + operator"); - else - { - vector values_copy(values); - values_copy.insert(values_copy.end(), - mv2->values.begin(), - mv2->values.end()); - return new ArrayMV(values_copy); - } + + vector values_copy(values); + values_copy.insert(values_copy.end(), mv2->values.begin(), mv2->values.end()); + return new ArrayMV(values_copy); } template @@ -170,7 +244,7 @@ ArrayMV::operator==(const MacroValue &mv) const throw (TypeError) { const ArrayMV *mv2 = dynamic_cast *>(&mv); if (mv2 == NULL) - throw new IntMV(0); + return new IntMV(0); else return new IntMV(values == mv2->values); } @@ -181,7 +255,7 @@ ArrayMV::operator!=(const MacroValue &mv) const throw (TypeError) { const ArrayMV *mv2 = dynamic_cast *>(&mv); if (mv2 == NULL) - throw new IntMV(1); + return new IntMV(1); else return new IntMV(values != mv2->values); } @@ -225,11 +299,4 @@ ArrayMV::toArray() const return clone(); } -template -MacroValue * -ArrayMV::append(const MacroValue &mv) const -{ - throw TypeError("Cannot append an array at the end of another one. Should use concatenation."); -} - #endif