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-bf33cf982152issue#70
parent
1883643772
commit
2de828a643
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]);
|
||||
|
|
Loading…
Reference in New Issue