From 039b27bbafa66ca8251691dd8107412f7ec59eed Mon Sep 17 00:00:00 2001 From: Houtan Bastani <houtan@dynare.org> Date: Tue, 7 Aug 2018 12:40:59 +0200 Subject: [PATCH] macroprocessor: union operator. #5 --- src/macro/MacroBison.yy | 4 +++- src/macro/MacroFlex.ll | 1 + src/macro/MacroValue.cc | 30 ++++++++++++++++++++++++++++++ src/macro/MacroValue.hh | 3 +++ 4 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/macro/MacroBison.yy b/src/macro/MacroBison.yy index 41359488..5b9bac62 100644 --- a/src/macro/MacroBison.yy +++ b/src/macro/MacroBison.yy @@ -78,7 +78,7 @@ class MacroDriver; %nonassoc IN %nonassoc COLON %left PLUS MINUS -%left TIMES DIVIDE +%left TIMES DIVIDE UNION %precedence UMINUS UPLUS EXCLAMATION %precedence LBRACKET @@ -205,6 +205,8 @@ expr : INTEGER { TYPERR_CATCH($$ = ArrayMV::range($1, $3), @$); } | expr IN expr { TYPERR_CATCH($$ = $3->in($1), @$); } + | expr UNION expr + { TYPERR_CATCH($$ = $1->set_union($3), @$); } ; comma_expr : %empty diff --git a/src/macro/MacroFlex.ll b/src/macro/MacroFlex.ll index 1db33cb6..8dae3b4a 100644 --- a/src/macro/MacroFlex.ll +++ b/src/macro/MacroFlex.ll @@ -218,6 +218,7 @@ CONT \\\\ <STMT,EXPR>[!] { return token::EXCLAMATION; } <STMT,EXPR>"||" { return token::LOGICAL_OR; } <STMT,EXPR>&& { return token::LOGICAL_AND; } +<STMT,EXPR>"|" { return token::UNION; } <STMT,EXPR>"<=" { return token::LESS_EQUAL; } <STMT,EXPR>">=" { return token::GREATER_EQUAL; } <STMT,EXPR>"<" { return token::LESS; } diff --git a/src/macro/MacroValue.cc b/src/macro/MacroValue.cc index 739ca795..e64ae065 100644 --- a/src/macro/MacroValue.cc +++ b/src/macro/MacroValue.cc @@ -126,6 +126,12 @@ MacroValue::in(const MacroValuePtr &mv) noexcept(false) throw TypeError("Second argument of 'in' operator must be an array"); } +shared_ptr<ArrayMV> +MacroValue::set_union(const MacroValuePtr &mv) noexcept(false) +{ + throw TypeError("Operator | does not exist for this type"); +} + IntMV::IntMV(int value_arg) : value{value_arg} { } @@ -532,6 +538,30 @@ ArrayMV::range(const MacroValuePtr &mv1, const MacroValuePtr &mv2) noexcept(fals return make_shared<ArrayMV>(result); } +shared_ptr<ArrayMV> +ArrayMV::set_union(const MacroValuePtr &mv) noexcept(false) +{ + auto mv2 = dynamic_pointer_cast<ArrayMV>(mv); + if (!mv2) + throw TypeError("Arguments of the union operator (|) must be sets"); + + vector<MacroValuePtr> new_values = values; + for (auto &it : mv2->values) + { + bool found = false; + for (auto &nvit : new_values) + if (nvit->is_equal(it)->value) + { + found = true; + break; + } + if (!found) + new_values.push_back(it); + } + + return make_shared<ArrayMV>(new_values); +} + TupleMV::TupleMV(vector<MacroValuePtr> values_arg) : values{move(values_arg)} { } diff --git a/src/macro/MacroValue.hh b/src/macro/MacroValue.hh index 051ec614..a26b466b 100644 --- a/src/macro/MacroValue.hh +++ b/src/macro/MacroValue.hh @@ -105,6 +105,8 @@ public: //! Applies "in" operator /*! The argument is the element to be tested for inclusion. Returns an IntMV, equal to 0 or 1 */ virtual shared_ptr<IntMV> in(const MacroValuePtr &mv) noexcept(false); + //! Creates the union of two sets + virtual shared_ptr<ArrayMV> set_union(const MacroValuePtr &mv) noexcept(false); }; //! Represents an integer value in macro language @@ -210,6 +212,7 @@ public: If mv2 < mv1, returns an empty range (for consistency with MATLAB). */ static shared_ptr<ArrayMV> range(const MacroValuePtr &mv1, const MacroValuePtr &mv2) noexcept(false); + shared_ptr<ArrayMV> set_union(const MacroValuePtr &mvp) noexcept(false) override; }; //! Represents a tuple value in macro language -- GitLab