trunk preprocessor/macro: allow empty arrays, and iteration over them in @#for loops (empty array can only be constructed through set difference for the moment)

git-svn-id: https://www.dynare.org/svn/dynare/trunk@2401 ac1d8469-bf42-47a9-8791-bf33cf982152
issue#70
sebastien 2009-02-06 15:47:26 +00:00
parent 1883643772
commit 2de828a643
3 changed files with 19 additions and 23 deletions

View File

@ -130,11 +130,9 @@ private:
//! Saves current scanning context and create a new context based on the "else" body
void create_else_context(Macro::parser::location_type *yylloc);
//! Iterates over the loop body
/*! If loop is terminated, return false and do nothing.
Otherwise, set loop variable to its new value (through driver.iter_loop()),
and initialise a new scanning context with the loop body */
bool iter_loop(MacroDriver &driver, Macro::parser::location_type *yylloc);
//! Initialise a new flex buffer with the loop body
void new_loop_body_buffer(Macro::parser::location_type *yylloc);
public:
MacroFlex(istream* in, ostream* out, bool no_line_macro_arg);

View File

@ -200,14 +200,18 @@ CONT \\\\
}
else
{
// Save old buffer state and location
save_context(yylloc);
// Switch to loop body context, except if iterating over an empty array
if (driver.iter_loop())
{
// Save old buffer state and location
save_context(yylloc);
is_for_context = true;
for_body = for_body_tmp;
for_body_loc = for_body_loc_tmp;
is_for_context = true;
for_body = for_body_tmp;
for_body_loc = for_body_loc_tmp;
iter_loop(driver, yylloc);
new_loop_body_buffer(yylloc);
}
BEGIN(INITIAL);
}
@ -299,7 +303,9 @@ CONT \\\\
/* If we are not in a loop body, or if the loop has terminated,
pop a context */
if (!is_for_context || !iter_loop(driver, yylloc))
if (is_for_context && driver.iter_loop())
new_loop_body_buffer(yylloc);
else
restore_context(yylloc);
}
@ -396,19 +402,14 @@ MacroFlex::create_else_context(Macro::parser::location_type *yylloc)
yy_switch_to_buffer(yy_create_buffer(input, YY_BUF_SIZE));
}
bool
MacroFlex::iter_loop(MacroDriver &driver, Macro::parser::location_type *yylloc)
void
MacroFlex::new_loop_body_buffer(Macro::parser::location_type *yylloc)
{
if (!driver.iter_loop())
return false;
input = new stringstream(for_body);
*yylloc = for_body_loc;
yylloc->begin.filename = yylloc->end.filename = new string(*for_body_loc.begin.filename);
output_line(yylloc);
yy_switch_to_buffer(yy_create_buffer(input, YY_BUF_SIZE));
return true;
}
/* This implementation of MacroFlexLexer::yylex() is required to fill the

View File

@ -185,7 +185,6 @@ public:
};
//! Represents an array in macro language
/*! Empty arrays are forbidden */
template<typename T>
class ArrayMV : public MacroValue
{
@ -221,8 +220,6 @@ public:
template<typename T>
ArrayMV<T>::ArrayMV(MacroDriver &driver, const vector<T> &values_arg) : MacroValue(driver), values(values_arg)
{
if (values.size() == 0)
throw "Empty arrays forbidden";
}
template<typename T>
@ -306,7 +303,7 @@ ArrayMV<T>::operator[](const MacroValue &mv) const throw (TypeError, OutOfBounds
result.push_back(values[*it - 1]);
}
if (result.size() > 1)
if (result.size() > 1 || result.size() == 0)
return new ArrayMV<T>(driver, result);
else
return MacroValue::new_base_value(driver, result[0]);