diff --git a/macro/MacroDriver.hh b/macro/MacroDriver.hh index d5669188..6bc3bc0d 100644 --- a/macro/MacroDriver.hh +++ b/macro/MacroDriver.hh @@ -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); diff --git a/macro/MacroFlex.ll b/macro/MacroFlex.ll index 6ea48752..855d740e 100644 --- a/macro/MacroFlex.ll +++ b/macro/MacroFlex.ll @@ -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 diff --git a/macro/MacroValue.hh b/macro/MacroValue.hh index 11eba487..054dd105 100644 --- a/macro/MacroValue.hh +++ b/macro/MacroValue.hh @@ -185,7 +185,6 @@ public: }; //! Represents an array in macro language -/*! Empty arrays are forbidden */ template class ArrayMV : public MacroValue { @@ -221,8 +220,6 @@ public: template ArrayMV::ArrayMV(MacroDriver &driver, const vector &values_arg) : MacroValue(driver), values(values_arg) { - if (values.size() == 0) - throw "Empty arrays forbidden"; } template @@ -306,7 +303,7 @@ ArrayMV::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(driver, result); else return MacroValue::new_base_value(driver, result[0]);