diff --git a/macro/MacroBison.yy b/macro/MacroBison.yy
index 0addc52cb48781dfa0e0a9addb9261a62fb91cd6..64848d141fbf3d36feea76f031b5c2fbfcdf2d7f 100644
--- a/macro/MacroBison.yy
+++ b/macro/MacroBison.yy
@@ -55,7 +55,7 @@ class MacroDriver;
 };
 
 %{
-#include <stdlib.h>  // Pour atoi()
+#include <cstdlib>  // Pour atoi()
 #include "MacroDriver.hh"
 
 /* this "connects" the bison parser in the driver to the flex scanner class
@@ -71,6 +71,7 @@ class MacroDriver;
 %token <int_val> INTEGER
 %token <string_val> NAME STRING
 
+%left COMMA
 %left LOGICAL_OR
 %left LOGICAL_AND
 %left LESS GREATER LESS_EQUAL GREATER_EQUAL EQUAL_EQUAL EXCLAMATION_EQUAL
@@ -79,7 +80,7 @@ class MacroDriver;
 %left UMINUS UPLUS EXCLAMATION
 %left LBRACKET
 
-%type <mv> expr
+%type <mv> expr array_expr
 %%
 
 %start statement_list_or_nothing;
@@ -133,10 +134,18 @@ expr : INTEGER
        { $$ = $2; }
      | EXCLAMATION expr
        { $$ = !*$2; delete $2; }
-     | expr LBRACKET expr RBRACKET
+     | expr LBRACKET array_expr RBRACKET
        { $$ = (*$1)[*$3]; delete $1; delete $3; }
+     | LBRACKET array_expr RBRACKET
+       { $$ = $2; }
      ;
 
+array_expr : expr
+             { $$ = $1->toArray(); delete $1; }
+           | array_expr COMMA expr
+             { $$ = $3->append(*$1); delete $1; delete $3; }
+           ;
+
 %%
 
 void
diff --git a/macro/MacroFlex.ll b/macro/MacroFlex.ll
index 8bdc68ccb24c4f984f08a8f5ac8d7378c4314d03..a1ba2ca97ae0204d01d1109cdb3e4e540ec2ca82 100644
--- a/macro/MacroFlex.ll
+++ b/macro/MacroFlex.ll
@@ -113,6 +113,7 @@ typedef Macro::parser::token token;
 <MACRO>\[                   { return token::LBRACKET; }
 <MACRO>\]                   { return token::RBRACKET; }
 <MACRO>:                    { return token::COLON; }
+<MACRO>,                    { return token::COMMA; }
 <MACRO>=                    { return token::EQUAL; }
 <MACRO>[!]                  { return token::EXCLAMATION; }
 <MACRO>"||"                 { return token::LOGICAL_OR; }
@@ -162,6 +163,9 @@ typedef Macro::parser::token token;
                               BEGIN(END_INCLUDE);
                             }
 
+ /* Ignore \r, because under Cygwin, outputting \n automatically adds another \r */
+<INITIAL>[\r]+              { yylloc->step(); }
+
  /* Copy everything else to output */
 <INITIAL>[\n]+              { yylloc->lines(yyleng); yylloc->step(); ECHO; }
 <INITIAL>.                  { yylloc->step(); ECHO; }
diff --git a/macro/MacroValue.cc b/macro/MacroValue.cc
index aa137dfab50bcb72c4f4f00eb6deb60354c32bd4..b8e0d0753270974362a4daf0c7e4e35404792ab3 100644
--- a/macro/MacroValue.cc
+++ b/macro/MacroValue.cc
@@ -17,10 +17,12 @@
  * along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <sstream>
-
 #include "MacroValue.hh"
 
+MacroValue::~MacroValue()
+{
+}
+
 MacroValue *
 MacroValue::operator-(const MacroValue &mv) const throw (TypeError)
 {
@@ -97,6 +99,10 @@ IntMV::IntMV(int value_arg) : value(value_arg)
 {
 }
 
+IntMV::~IntMV()
+{
+}
+
 MacroValue *
 IntMV::operator+(const MacroValue &mv) const throw (TypeError)
 {
@@ -243,10 +249,36 @@ IntMV::clone() const
   return new IntMV(value);
 }
 
+MacroValue *
+IntMV::toArray() const
+{
+  vector<int> v;
+  v.push_back(value);
+  return new ArrayMV<int>(v);
+}
+
+MacroValue *
+IntMV::append(const MacroValue &array) const
+{
+  const ArrayMV<int> *array2 = dynamic_cast<const ArrayMV<int> *>(&array);
+  if (array2 == NULL)
+    throw TypeError("Type mismatch for append operation");
+  else
+    {
+      vector<int> v(array2->values);
+      v.push_back(value);
+      return new ArrayMV<int>(v);
+    }
+}
+
 StringMV::StringMV(const string &value_arg) : value(value_arg)
 {
 }
 
+StringMV::~StringMV()
+{
+}
+
 MacroValue *
 StringMV::operator+(const MacroValue &mv) const throw (TypeError)
 {
@@ -277,6 +309,22 @@ StringMV::operator!=(const MacroValue &mv) const throw (TypeError)
     return new IntMV(value != mv2->value);
 }
 
+MacroValue *
+StringMV::operator[](const MacroValue &mv) const throw (TypeError)
+{
+  const ArrayMV<int> *mv2 = dynamic_cast<const ArrayMV<int> *>(&mv);
+  if (mv2 == NULL)
+    throw TypeError("Expression inside [] must be an integer array");
+  string result;
+  for(vector<int>::const_iterator it = mv2->values.begin();
+      it != mv2->values.end(); it++)
+    {
+      char c = value.at(*it - 1);
+      result.append(&c);
+    }
+  return new StringMV(result);
+}
+
 string
 StringMV::toString() const
 {
@@ -288,3 +336,25 @@ StringMV::clone() const
 {
   return new StringMV(value);
 }
+
+MacroValue *
+StringMV::toArray() const
+{
+  vector<string> v;
+  v.push_back(value);
+  return new ArrayMV<string>(v);
+}
+
+MacroValue *
+StringMV::append(const MacroValue &array) const
+{
+  const ArrayMV<string> *array2 = dynamic_cast<const ArrayMV<string> *>(&array);
+  if (array2 == NULL)
+    throw TypeError("Type mismatch for append operation");
+  else
+    {
+      vector<string> v(array2->values);
+      v.push_back(value);
+      return new ArrayMV<string>(v);
+    }
+}
diff --git a/macro/MacroValue.hh b/macro/MacroValue.hh
index 31e7687c49b8466bcadd42ac991f4bebb358698b..cdac2db5e0991b9350897f1bad8965d4b4602897 100644
--- a/macro/MacroValue.hh
+++ b/macro/MacroValue.hh
@@ -24,6 +24,7 @@ using namespace std;
 
 #include <string>
 #include <vector>
+#include <sstream>
 
 class MacroValue
 {
@@ -34,6 +35,7 @@ public:
     const string message;
     TypeError(const string &message_arg) : message(message_arg) {};
   };
+  virtual ~MacroValue();
   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);
@@ -51,14 +53,18 @@ public:
   virtual MacroValue *operator[](const MacroValue &mv) const throw (TypeError);
   virtual string toString() const = 0;
   virtual MacroValue *clone() const = 0;
+  virtual MacroValue *toArray() const = 0;
+  virtual MacroValue *append(const MacroValue &array) const = 0;
 };
 
 class IntMV : public MacroValue
 {
+  friend class StringMV;
 private:
   int value;
 public:
   IntMV(int value_arg);
+  virtual ~IntMV();
   virtual MacroValue *operator+(const MacroValue &mv) const throw (TypeError);
   virtual MacroValue *operator-(const MacroValue &mv) const throw (TypeError);
   virtual MacroValue *operator-() const throw (TypeError);
@@ -75,6 +81,8 @@ public:
   virtual MacroValue *operator!() const throw (TypeError);
   virtual string toString() const;
   virtual MacroValue *clone() const;
+  virtual MacroValue *toArray() const;
+  virtual MacroValue *append(const MacroValue &array) const;
 };
 
 class StringMV : public MacroValue
@@ -83,6 +91,7 @@ private:
   string value;
 public:
   StringMV(const string &value_arg);
+  virtual ~StringMV();
   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);
@@ -90,39 +99,137 @@ 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);
-// virtual MacroValue *operator[](const MacroValue &mv) const throw (TypeError);
+  //! Subscripting operator
+  /*!
+    Argument must be an ArrayMV<int>. Indexes begin at 1.
+    \todo Add bound error checking
+  */
+  virtual MacroValue *operator[](const MacroValue &mv) const throw (TypeError);
   virtual string toString() const;
   virtual MacroValue *clone() const;
+  virtual MacroValue *toArray() const;
+  virtual MacroValue *append(const MacroValue &array) const;
 };
 
-/*
-class IntArrayMV : public MacroValue
+template<typename T>
+class ArrayMV : public MacroValue
 {
+  friend class IntMV;
+  friend class StringMV;
+  friend class ArrayMV<string>; // Necessary for operator[] to access values of integer array when subscripting a string array
 private:
-  vector<int> values;
+  vector<T> values;
 public:
-  IntArrayMV(const vector<int> &values_arg);
+  ArrayMV(const vector<T> &values_arg);
+  virtual ~ArrayMV();
   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<int>. Indexes begin at 1.
+    \todo Add bound error checking
+  */
   virtual MacroValue *operator[](const MacroValue &mv) const throw (TypeError);
   virtual string toString() const;
   virtual MacroValue *clone() const;
+  virtual MacroValue *toArray() const;
+  virtual MacroValue *append(const MacroValue &array) const;
 };
 
-class StringArrayMV : public MacroValue
+template<typename T>
+ArrayMV<T>::ArrayMV(const vector<T> &values_arg) : values(values_arg)
 {
-private:
-  vector<string> values;
-public:
-  StringArrayMV(const vector<string> &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;
-};
-*/
+}
+
+template<typename T>
+ArrayMV<T>::~ArrayMV()
+{
+}
+
+template<typename T>
+MacroValue *
+ArrayMV<T>::operator+(const MacroValue &mv) const throw (TypeError)
+{
+  const ArrayMV<T> *mv2 = dynamic_cast<const ArrayMV<T> *>(&mv);
+  if (mv2 == NULL)
+    throw TypeError("Type mismatch for operands of + operator");
+  else
+    {
+      vector<T> values_copy(values);
+      values_copy.insert(values_copy.end(),
+                         mv2->values.begin(),
+                         mv2->values.end());
+      return new ArrayMV<T>(values_copy);
+    }
+}
+
+template<typename T>
+MacroValue *
+ArrayMV<T>::operator==(const MacroValue &mv) const throw (TypeError)
+{
+  const ArrayMV<T> *mv2 = dynamic_cast<const ArrayMV<T> *>(&mv);
+  if (mv2 == NULL)
+    throw new IntMV(0);
+  else
+    return new IntMV(values == mv2->values);
+}
+
+template<typename T>
+MacroValue *
+ArrayMV<T>::operator!=(const MacroValue &mv) const throw (TypeError)
+{
+  const ArrayMV<T> *mv2 = dynamic_cast<const ArrayMV<T> *>(&mv);
+  if (mv2 == NULL)
+    throw new IntMV(1);
+  else
+    return new IntMV(values != mv2->values);
+}
+
+template<typename T>
+MacroValue *
+ArrayMV<T>::operator[](const MacroValue &mv) const throw (TypeError)
+{
+  const ArrayMV<int> *mv2 = dynamic_cast<const ArrayMV<int> *>(&mv);
+  if (mv2 == NULL)
+    throw TypeError("Expression inside [] must be an integer array");
+  vector<T> result;
+  for(vector<int>::const_iterator it = mv2->values.begin();
+      it != mv2->values.end(); it++)
+    result.push_back(values[*it - 1]);
+  return new ArrayMV<T>(result);
+}
+
+template<typename T>
+string
+ArrayMV<T>::toString() const
+{
+  ostringstream ss;
+  for(typename vector<T>::const_iterator it = values.begin();
+      it != values.end(); it++)
+    ss << *it;
+  return ss.str();
+}
+
+template<typename T>
+MacroValue *
+ArrayMV<T>::clone() const
+{
+  return new ArrayMV<T>(values);
+}
+
+template<typename T>
+MacroValue *
+ArrayMV<T>::toArray() const
+{
+  return clone();
+}
+
+template<typename T>
+MacroValue *
+ArrayMV<T>::append(const MacroValue &mv) const
+{
+  throw TypeError("Cannot append an array at the end of another one. Should use concatenation.");
+}
 
 #endif