diff --git a/doc/macroprocessor/macroprocessor.tex b/doc/macroprocessor/macroprocessor.tex index fec6052f31b3a3464a0a57bfddf8e68712dac9b6..4d26aa165780b430ca2fce86a0e674c8d05fa0d0 100644 --- a/doc/macroprocessor/macroprocessor.tex +++ b/doc/macroprocessor/macroprocessor.tex @@ -399,12 +399,26 @@ end; \end{frame} \begin{frame}[fragile=singleslide] - \frametitle{Loop directive} - \begin{block}{Syntax} + \frametitle{Loop directive (1/2)} + \begin{block}{Syntax 1} \verb+@#for +\textit{variable\_name}\verb+ in +\textit{array\_expr} \\ \verb+ +\textit{loop\_body} \\ \verb+@#endfor+ \end{block} + \begin{block}{Syntax 2} +\verb+@#for +\textit{tuple}\verb+ in +\textit{array\_expr} \\ +\verb+ +\textit{loop\_body} \\ +\verb+@#endfor+ + \end{block} + \begin{block}{Syntax 3} +\verb+@#for +\textit{tuple\_or\_variable}\verb+ in +\textit{array\_expr} \verb+ when +\textit{expr}\\ +\verb+ +\textit{loop\_body} \\ +\verb+@#endfor+ + \end{block} +\end{frame} + +\begin{frame}[fragile=singleslide] + \frametitle{Loop directive (2/2)} \begin{block}{Example: before macro processing} \small \begin{verbatim} diff --git a/src/macro/Parser.yy b/src/macro/Parser.yy index e6ba09dc79e0e38a6d86da9102621290fda44f6f..b46cea4bacf15ab09b62c7ca3dfd57d4ad4c29bc 100644 --- a/src/macro/Parser.yy +++ b/src/macro/Parser.yy @@ -95,11 +95,10 @@ using namespace macro; %type <DirectivePtr> directive directive_one_line directive_multiline for if ifdef ifndef text eval %type <vector<pair<ExpressionPtr, vector<DirectivePtr>>>> if_list if_list1 %type <pair<ExpressionPtr, vector<DirectivePtr>>> elseif else -%type <ExpressionPtr> primary_expr oper_expr colon_expr expr +%type <ExpressionPtr> primary_expr oper_expr colon_expr expr for_when %type <FunctionPtr> function %type <VariablePtr> symbol -%type <vector<VariablePtr>> comma_name %type <vector<ExpressionPtr>> comma_expr function_args tuple_comma_expr %% @@ -149,38 +148,43 @@ directive_multiline : for | ifndef ; -for_begin : FOR { driver.pushContext(); } ; +for_when : %empty + { $$ = shared_ptr<Expression>(); } + | WHEN expr + { $$ = $2; } + ; -for : for_begin symbol IN expr EOL statements ENDFOR - { - vector<VariablePtr> vvnp = {$2}; - auto vdp = driver.popContext(); - vdp.emplace_back(make_shared<TextNode>("\n", driver.env, @7)); - $$ = make_shared<For>(vvnp, $4, vdp, driver.env, @$); - } - | for_begin LPAREN comma_name RPAREN IN expr EOL statements ENDFOR +for : FOR { driver.pushContext(); } expr IN expr for_when EOL statements ENDFOR { vector<VariablePtr> vvnp; - for (auto & it : $3) - { - auto vnp = dynamic_pointer_cast<Variable>(it); - if (!vnp) - error(@$, "For loop indices must be variables"); - vvnp.push_back(vnp); - } + auto tmpt = dynamic_pointer_cast<Tuple>($3); + auto tmpv = dynamic_pointer_cast<Variable>($3); + if (tmpv) + vvnp.emplace_back(tmpv); + else if (tmpt) + for (auto & it : tmpt->getValue()) + { + auto vnp = dynamic_pointer_cast<Variable>(it); + if (!vnp) + error(@$, "For loop indices must be variables"); + vvnp.emplace_back(vnp); + } + else + error(@1, "For loop indices must be a variable or a tuple"); + auto vdp = driver.popContext(); vdp.emplace_back(make_shared<TextNode>("\n", driver.env, @9)); - $$ = make_shared<For>(vvnp, $6, vdp, driver.env, @$); + + if (!$6) + $$ = make_shared<For>(vvnp, $5, vdp, driver.env, @$); + else + { + auto tmpc = make_shared<Comprehension>(true, $3, $5, $6, driver.env, @6); + $$ = make_shared<For>(vvnp, tmpc, vdp, driver.env, @$); + } } ; -comma_name : NAME - { $$ = vector<VariablePtr>{make_shared<Variable>($1, driver.env, @$)}; } - | comma_name COMMA NAME - { $1.emplace_back(make_shared<Variable>($3, driver.env, @3)); $$ = $1; } - ; - - if : IF { driver.pushContext(); } if_list ENDIF { $$ = make_shared<If>($3, driver.env, @$); } ;