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
|
//! Saves current scanning context and create a new context based on the "else" body
|
||||||
void create_else_context(Macro::parser::location_type *yylloc);
|
void create_else_context(Macro::parser::location_type *yylloc);
|
||||||
|
|
||||||
//! Iterates over the loop body
|
//! Initialise a new flex buffer with the loop body
|
||||||
/*! If loop is terminated, return false and do nothing.
|
void new_loop_body_buffer(Macro::parser::location_type *yylloc);
|
||||||
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);
|
|
||||||
public:
|
public:
|
||||||
MacroFlex(istream* in, ostream* out, bool no_line_macro_arg);
|
MacroFlex(istream* in, ostream* out, bool no_line_macro_arg);
|
||||||
|
|
||||||
|
|
|
@ -199,6 +199,9 @@ CONT \\\\
|
||||||
for_body_tmp.append(yytext);
|
for_body_tmp.append(yytext);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
// Switch to loop body context, except if iterating over an empty array
|
||||||
|
if (driver.iter_loop())
|
||||||
{
|
{
|
||||||
// Save old buffer state and location
|
// Save old buffer state and location
|
||||||
save_context(yylloc);
|
save_context(yylloc);
|
||||||
|
@ -207,7 +210,8 @@ CONT \\\\
|
||||||
for_body = for_body_tmp;
|
for_body = for_body_tmp;
|
||||||
for_body_loc = for_body_loc_tmp;
|
for_body_loc = for_body_loc_tmp;
|
||||||
|
|
||||||
iter_loop(driver, yylloc);
|
new_loop_body_buffer(yylloc);
|
||||||
|
}
|
||||||
|
|
||||||
BEGIN(INITIAL);
|
BEGIN(INITIAL);
|
||||||
}
|
}
|
||||||
|
@ -299,7 +303,9 @@ CONT \\\\
|
||||||
|
|
||||||
/* If we are not in a loop body, or if the loop has terminated,
|
/* If we are not in a loop body, or if the loop has terminated,
|
||||||
pop a context */
|
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);
|
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));
|
yy_switch_to_buffer(yy_create_buffer(input, YY_BUF_SIZE));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
MacroFlex::iter_loop(MacroDriver &driver, Macro::parser::location_type *yylloc)
|
MacroFlex::new_loop_body_buffer(Macro::parser::location_type *yylloc)
|
||||||
{
|
{
|
||||||
if (!driver.iter_loop())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
input = new stringstream(for_body);
|
input = new stringstream(for_body);
|
||||||
*yylloc = for_body_loc;
|
*yylloc = for_body_loc;
|
||||||
yylloc->begin.filename = yylloc->end.filename = new string(*for_body_loc.begin.filename);
|
yylloc->begin.filename = yylloc->end.filename = new string(*for_body_loc.begin.filename);
|
||||||
output_line(yylloc);
|
output_line(yylloc);
|
||||||
yy_switch_to_buffer(yy_create_buffer(input, YY_BUF_SIZE));
|
yy_switch_to_buffer(yy_create_buffer(input, YY_BUF_SIZE));
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This implementation of MacroFlexLexer::yylex() is required to fill the
|
/* This implementation of MacroFlexLexer::yylex() is required to fill the
|
||||||
|
|
|
@ -185,7 +185,6 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Represents an array in macro language
|
//! Represents an array in macro language
|
||||||
/*! Empty arrays are forbidden */
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class ArrayMV : public MacroValue
|
class ArrayMV : public MacroValue
|
||||||
{
|
{
|
||||||
|
@ -221,8 +220,6 @@ public:
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ArrayMV<T>::ArrayMV(MacroDriver &driver, const vector<T> &values_arg) : MacroValue(driver), values(values_arg)
|
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>
|
template<typename T>
|
||||||
|
@ -306,7 +303,7 @@ ArrayMV<T>::operator[](const MacroValue &mv) const throw (TypeError, OutOfBounds
|
||||||
result.push_back(values[*it - 1]);
|
result.push_back(values[*it - 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.size() > 1)
|
if (result.size() > 1 || result.size() == 0)
|
||||||
return new ArrayMV<T>(driver, result);
|
return new ArrayMV<T>(driver, result);
|
||||||
else
|
else
|
||||||
return MacroValue::new_base_value(driver, result[0]);
|
return MacroValue::new_base_value(driver, result[0]);
|
||||||
|
|
Loading…
Reference in New Issue