From 045e20e284691aa1eb67ece2dd0ecb214f209f51 Mon Sep 17 00:00:00 2001
From: sebastien <sebastien@ac1d8469-bf42-47a9-8791-bf33cf982152>
Date: Mon, 8 Dec 2008 15:13:08 +0000
Subject: [PATCH] trunk preprocessor/macro: added new 'in' operator for testing
 membership of an array

git-svn-id: https://www.dynare.org/svn/dynare/dynare_v4@2300 ac1d8469-bf42-47a9-8791-bf33cf982152
---
 macro/MacroBison.yy |  3 +++
 macro/MacroFlex.ll  |  2 +-
 macro/MacroValue.cc | 44 ++++++++++++++++++++++++++++++++++++++++++++
 macro/MacroValue.hh |  7 ++++++-
 4 files changed, 54 insertions(+), 2 deletions(-)

diff --git a/macro/MacroBison.yy b/macro/MacroBison.yy
index e44f5bfc..8caa736c 100644
--- a/macro/MacroBison.yy
+++ b/macro/MacroBison.yy
@@ -85,6 +85,7 @@ class MacroDriver;
 %left LOGICAL_OR
 %left LOGICAL_AND
 %left LESS GREATER LESS_EQUAL GREATER_EQUAL EQUAL_EQUAL EXCLAMATION_EQUAL
+%nonassoc IN
 %nonassoc COLON
 %left PLUS MINUS
 %left TIMES DIVIDE
@@ -180,6 +181,8 @@ expr : INTEGER
        { $$ = $2; }
      | expr COLON expr
        { TYPERR_CATCH($$ = IntMV::new_range(driver, $1, $3), @$); }
+     | expr IN expr
+       { TYPERR_CATCH($$ = $1->in($3), @$); }
      ;
 
 array_expr : expr
diff --git a/macro/MacroFlex.ll b/macro/MacroFlex.ll
index d74ab064..557b9733 100644
--- a/macro/MacroFlex.ll
+++ b/macro/MacroFlex.ll
@@ -144,6 +144,7 @@ CONT \\\\
 <STMT,EXPR>[-]              { return token::MINUS; }
 <STMT,EXPR>[*]              { return token::TIMES; }
 <STMT,EXPR>[/]              { return token::DIVIDE; }
+<STMT,EXPR>in               { return token::IN; }
 
 <STMT,EXPR>\"[^\"]*\"       {
                               yylval->string_val = new string(yytext + 1);
@@ -155,7 +156,6 @@ CONT \\\\
 <STMT>define                { return token::DEFINE; }
 
 <STMT>for                   { reading_for_statement = true; return token::FOR; }
-<STMT>in                    { return token::IN; }
 <STMT>endfor                { driver.error(*yylloc, "@#endfor is not matched by a @#for statement"); }
 
 <STMT>if                    { reading_if_statement = true; return token::IF; }
diff --git a/macro/MacroValue.cc b/macro/MacroValue.cc
index d3dcce6a..be509f67 100644
--- a/macro/MacroValue.cc
+++ b/macro/MacroValue.cc
@@ -112,6 +112,12 @@ MacroValue::append(const MacroValue *mv) const throw (TypeError)
   throw TypeError("Cannot append an array at the end of another one. Should use concatenation.");
 }
 
+const MacroValue *
+MacroValue::in(const MacroValue *array) const throw (TypeError)
+{
+  throw TypeError("First argument of 'in' operator cannot be an array");
+}
+
 const MacroValue *
 MacroValue::new_base_value(MacroDriver &driver, int i)
 {
@@ -288,6 +294,25 @@ IntMV::append(const MacroValue *array) const throw (TypeError)
   return new ArrayMV<int>(driver, v);
 }
 
+const MacroValue *
+IntMV::in(const MacroValue *array) const throw (TypeError)
+{
+  const ArrayMV<int> *array2 = dynamic_cast<const ArrayMV<int> *>(array);
+  if (array2 == NULL)
+    throw TypeError("Type mismatch for 'in' operator");
+
+  int result = 0;
+  for(vector<int>::const_iterator it = array2->values.begin();
+      it != array2->values.end(); it++)
+    if (*it == value)
+      {
+        result = 1;
+        break;
+      }
+
+  return new IntMV(driver, result);
+}
+
 const MacroValue *
 IntMV::new_range(MacroDriver &driver, const MacroValue *mv1, const MacroValue *mv2) throw (TypeError)
 {
@@ -392,3 +417,22 @@ StringMV::append(const MacroValue *array) const throw (TypeError)
   v.push_back(value);
   return new ArrayMV<string>(driver, v);
 }
+
+const MacroValue *
+StringMV::in(const MacroValue *array) const throw (TypeError)
+{
+  const ArrayMV<string> *array2 = dynamic_cast<const ArrayMV<string> *>(array);
+  if (array2 == NULL)
+    throw TypeError("Type mismatch for 'in' operator");
+
+  int result = 0;
+  for(vector<string>::const_iterator it = array2->values.begin();
+      it != array2->values.end(); it++)
+    if (*it == value)
+      {
+        result = 1;
+        break;
+      }
+
+  return new IntMV(driver, result);
+}
diff --git a/macro/MacroValue.hh b/macro/MacroValue.hh
index 77b6bb22..da2df145 100644
--- a/macro/MacroValue.hh
+++ b/macro/MacroValue.hh
@@ -91,8 +91,11 @@ public:
   //! Converts value to array form
   virtual const MacroValue *toArray() const = 0;
   //! Appends value at the end of an array
-  /*! The first argument must be an array. */
+  /*! The argument must be an array. */
   virtual const MacroValue *append(const MacroValue *array) const throw (TypeError);
+  //! Applies "in" operator
+  /*! The argument must be an array. Returns an IntMV, equal to 0 or 1 */
+  virtual const MacroValue *in(const MacroValue *array) const throw (TypeError);
   //! Returns a new IntMV
   /*! Necessary for ArrayMV::operator[] (template issue) */
   static const MacroValue *new_base_value(MacroDriver &driver, int i);
@@ -144,6 +147,7 @@ public:
   //! Appends value at the end of an array
   /*! The first argument must be an integer array. */
   virtual const MacroValue *append(const MacroValue *array) const throw (TypeError);
+  virtual const MacroValue *in(const MacroValue *array) const throw (TypeError);
   //! Creates a integer range
   /*! Arguments must be of type IntMV.
       Returns an integer array containing all integers between mv1 and mv2.
@@ -177,6 +181,7 @@ public:
   //! Appends value at the end of an array
   /*! The first argument must be a string array. Returns a string array. */
   virtual const MacroValue *append(const MacroValue *array) const throw (TypeError);
+  virtual const MacroValue *in(const MacroValue *array) const throw (TypeError);
 };
 
 //! Represents an array in macro language
-- 
GitLab