@@ -693,7 +693,7 @@ enum SpaceHandling { Keep, Strip, StripSpaces, StripNewline };
693
693
694
694
class TemplateToken {
695
695
public:
696
- enum class Type { Text, Expression, If, Else, Elif, EndIf, For, EndFor, Set, EndSet, Comment, Macro, EndMacro, Filter, EndFilter };
696
+ enum class Type { Text, Expression, If, Else, Elif, EndIf, For, EndFor, Generation, EndGeneration, Set, EndSet, Comment, Macro, EndMacro, Filter, EndFilter };
697
697
698
698
static std::string typeToString (Type t) {
699
699
switch (t) {
@@ -712,6 +712,8 @@ class TemplateToken {
712
712
case Type::EndMacro: return " endmacro" ;
713
713
case Type::Filter: return " filter" ;
714
714
case Type::EndFilter: return " endfilter" ;
715
+ case Type::Generation: return " generation" ;
716
+ case Type::EndGeneration: return " endgeneration" ;
715
717
}
716
718
return " Unknown" ;
717
719
}
@@ -788,6 +790,14 @@ struct EndForTemplateToken : public TemplateToken {
788
790
EndForTemplateToken (const Location & location, SpaceHandling pre, SpaceHandling post) : TemplateToken(Type::EndFor, location, pre, post) {}
789
791
};
790
792
793
+ struct GenerationTemplateToken : public TemplateToken {
794
+ GenerationTemplateToken (const Location & location, SpaceHandling pre, SpaceHandling post) : TemplateToken(Type::Generation, location, pre, post) {}
795
+ };
796
+
797
+ struct EndGenerationTemplateToken : public TemplateToken {
798
+ EndGenerationTemplateToken (const Location & location, SpaceHandling pre, SpaceHandling post) : TemplateToken(Type::EndGeneration, location, pre, post) {}
799
+ };
800
+
791
801
struct SetTemplateToken : public TemplateToken {
792
802
std::string ns;
793
803
std::vector<std::string> var_names;
@@ -2149,7 +2159,7 @@ class Parser {
2149
2159
static std::regex comment_tok (R"( \{#([-~]?)(.*?)([-~]?)#\})" );
2150
2160
static std::regex expr_open_regex (R"( \{\{([-~])?)" );
2151
2161
static std::regex block_open_regex (R"( ^\{%([-~])?[\s\n\r]*)" );
2152
- static std::regex block_keyword_tok (R"( (if|else|elif|endif|for|endfor|set|endset|block|endblock|macro|endmacro|filter|endfilter)\b)" );
2162
+ static std::regex block_keyword_tok (R"( (if|else|elif|endif|for|endfor|generation|endgeneration| set|endset|block|endblock|macro|endmacro|filter|endfilter)\b)" );
2153
2163
static std::regex non_text_open_regex (R"( \{\{|\{%|\{#)" );
2154
2164
static std::regex expr_close_regex (R"( [\s\n\r]*([-~])?\}\})" );
2155
2165
static std::regex block_close_regex (R"( [\s\n\r]*([-~])?%\})" );
@@ -2229,6 +2239,12 @@ class Parser {
2229
2239
} else if (keyword == " endfor" ) {
2230
2240
auto post_space = parseBlockClose ();
2231
2241
tokens.push_back (std::make_unique<EndForTemplateToken>(location, pre_space, post_space));
2242
+ } else if (keyword == " generation" ) {
2243
+ auto post_space = parseBlockClose ();
2244
+ tokens.push_back (std::make_unique<GenerationTemplateToken>(location, pre_space, post_space));
2245
+ } else if (keyword == " endgeneration" ) {
2246
+ auto post_space = parseBlockClose ();
2247
+ tokens.push_back (std::make_unique<EndGenerationTemplateToken>(location, pre_space, post_space));
2232
2248
} else if (keyword == " set" ) {
2233
2249
static std::regex namespaced_var_regex (R"( (\w+)[\s\n\r]*\.[\s\n\r]*(\w+))" );
2234
2250
@@ -2330,6 +2346,13 @@ class Parser {
2330
2346
throw unterminated (**start);
2331
2347
}
2332
2348
children.emplace_back (std::make_shared<ForNode>(token->location , std::move (for_token->var_names ), std::move (for_token->iterable ), std::move (for_token->condition ), std::move (body), for_token->recursive , std::move (else_body)));
2349
+ } else if (dynamic_cast <GenerationTemplateToken*>(token.get ())) {
2350
+ auto body = parseTemplate (begin, it, end);
2351
+ if (it == end || (*(it++))->type != TemplateToken::Type::EndGeneration) {
2352
+ throw unterminated (**start);
2353
+ }
2354
+ // Treat as a no-op, as our scope is templates for inference, not training (`{% generation %}` wraps generated tokens for masking).
2355
+ children.emplace_back (std::move (body));
2333
2356
} else if (auto text_token = dynamic_cast <TextTemplateToken*>(token.get ())) {
2334
2357
SpaceHandling pre_space = (it - 1 ) != begin ? (*(it - 2 ))->post_space : SpaceHandling::Keep;
2335
2358
SpaceHandling post_space = it != end ? (*it)->pre_space : SpaceHandling::Keep;
@@ -2397,6 +2420,7 @@ class Parser {
2397
2420
|| dynamic_cast <EndFilterTemplateToken*>(token.get ())
2398
2421
|| dynamic_cast <EndIfTemplateToken*>(token.get ())
2399
2422
|| dynamic_cast <ElseTemplateToken*>(token.get ())
2423
+ || dynamic_cast <EndGenerationTemplateToken*>(token.get ())
2400
2424
|| dynamic_cast <ElifTemplateToken*>(token.get ())) {
2401
2425
it--; // unconsume the token
2402
2426
break ; // exit the loop
0 commit comments