Skip to content

Commit b93fd69

Browse files
authored
Implement 'do' statement #105 (#109)
* Implement 'do' extension statement * Add parsing errors test for 'do' statement
1 parent 7e9f5da commit b93fd69

File tree

12 files changed

+149
-14
lines changed

12 files changed

+149
-14
lines changed

include/jinja2cpp/error_info.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ enum class ErrorCode
3434
TemplateNotFound,
3535
TemplateNotParsed,
3636
InvalidValueType,
37+
ExtensionDisabled,
3738
};
3839

3940
struct SourceLocation

include/jinja2cpp/template_env.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,24 @@ namespace jinja2
1414
class IErrorHandler;
1515
class IFilesystemHandler;
1616

17+
enum class Jinja2CompatMode
18+
{
19+
None,
20+
Vesrsion_2_10,
21+
};
22+
1723
struct Settings
1824
{
25+
struct Extensions
26+
{
27+
bool Do = false;
28+
};
29+
1930
bool useLineStatements = false;
2031
bool trimBlocks = false;
2132
bool lstripBlocks = false;
33+
Extensions extensions;
34+
Jinja2CompatMode jinja2CompatMode = Jinja2CompatMode::None;
2235
};
2336

2437
class TemplateEnv

src/error_info.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,9 @@ void RenderErrorInfo(std::basic_ostream<CharT>& os, const ErrorInfoTpl<CharT>& e
200200
case ErrorCode::InvalidValueType:
201201
os << UNIVERSAL_STR("Invalid value type");
202202
break;
203+
case ErrorCode::ExtensionDisabled:
204+
os << UNIVERSAL_STR("Extension disabled");
205+
break;
203206
}
204207
os << std::endl << errInfo.GetLocationDescr();
205208
}

src/expression_parser.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include <sstream>
44
#include <unordered_set>
5+
#include <jinja2cpp/template_env.h>
56

67
namespace jinja2
78
{
@@ -16,7 +17,7 @@ auto ReplaceErrorIfPossible(T& result, const Token& pivotTok, ErrorCode newError
1617
return result.get_unexpected();
1718
}
1819

19-
ExpressionParser::ExpressionParser()
20+
ExpressionParser::ExpressionParser(const Settings& /* settings */)
2021
{
2122

2223
}

src/expression_parser.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "renderer.h"
88

99
#include <nonstd/expected.hpp>
10+
#include <jinja2cpp/template_env.h>
1011

1112
namespace jinja2
1213
{
@@ -16,7 +17,7 @@ class ExpressionParser
1617
template<typename T>
1718
using ParseResult = nonstd::expected<T, ParseError>;
1819

19-
ExpressionParser();
20+
ExpressionParser(const Settings& settings);
2021
ParseResult<RendererPtr> Parse(LexScanner& lexer);
2122
ParseResult<ExpressionEvaluatorPtr<FullExpressionEvaluator>> ParseFullExpression(LexScanner& lexer, bool includeIfPart = true);
2223
ParseResult<CallParams> ParseCallParams(LexScanner& lexer);

src/lexer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ struct Token
9292
Context,
9393
From,
9494
As,
95+
Do,
9596

9697
// Template control
9798
CommentBegin,
@@ -169,6 +170,7 @@ enum class Keyword
169170
Context,
170171
From,
171172
As,
173+
Do,
172174
};
173175

174176
struct LexerHelper

src/statements.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,4 +635,8 @@ void MacroCallStatement::SetupMacroScope(InternalValueMap&)
635635

636636
}
637637

638+
void DoStatement::Render(OutStream& os, RenderContext& values)
639+
{
640+
m_expr->Evaluate(values);
641+
}
638642
} // jinja2

src/statements.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,19 @@ class MacroCallStatement : public MacroStatement
322322
std::string m_macroName;
323323
CallParams m_callParams;
324324
};
325+
326+
class DoStatement : public Statement
327+
{
328+
public:
329+
VISITABLE_STATEMENT();
330+
331+
DoStatement(ExpressionEvaluatorPtr <> expr) : m_expr(expr) {}
332+
333+
void Render(OutStream &os, RenderContext &values) override;
334+
335+
private:
336+
ExpressionEvaluatorPtr<> m_expr;
337+
};
325338
} // jinja2
326339

327340

src/template_parser.cpp

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,11 @@ StatementsParser::ParseResult StatementsParser::Parse(LexScanner& lexer, Stateme
6262
case Keyword::From:
6363
result = ParseFrom(lexer, statementsInfo, tok);
6464
break;
65+
case Keyword::Do:
66+
if (!m_settings.extensions.Do)
67+
return MakeParseError(ErrorCode::ExtensionDisabled, tok);
68+
result = ParseDo(lexer, statementsInfo, tok);
69+
break;
6570
case Keyword::Filter:
6671
case Keyword::EndFilter:
6772
case Keyword::EndSet:
@@ -142,7 +147,7 @@ StatementsParser::ParseResult StatementsParser::ParseFor(LexScanner &lexer, Stat
142147
}
143148

144149
auto pivotToken = lexer.PeekNextToken();
145-
ExpressionParser exprPraser;
150+
ExpressionParser exprPraser(m_settings);
146151
auto valueExpr = exprPraser.ParseFullExpression(lexer, false);
147152
if (!valueExpr)
148153
return valueExpr.get_unexpected();
@@ -213,7 +218,7 @@ StatementsParser::ParseResult StatementsParser::ParseIf(LexScanner &lexer, State
213218
const Token &stmtTok)
214219
{
215220
auto pivotTok = lexer.PeekNextToken();
216-
ExpressionParser exprParser;
221+
ExpressionParser exprParser(m_settings);
217222
auto valueExpr = exprParser.ParseFullExpression(lexer);
218223
if (!valueExpr)
219224
return MakeParseError(ErrorCode::ExpectedExpression, pivotTok);
@@ -239,7 +244,7 @@ StatementsParser::ParseResult StatementsParser::ParseElIf(LexScanner& lexer, Sta
239244
, const Token& stmtTok)
240245
{
241246
auto pivotTok = lexer.PeekNextToken();
242-
ExpressionParser exprParser;
247+
ExpressionParser exprParser(m_settings);
243248
auto valueExpr = exprParser.ParseFullExpression(lexer);
244249
if (!valueExpr)
245250
return MakeParseError(ErrorCode::ExpectedExpression, pivotTok);
@@ -309,7 +314,7 @@ StatementsParser::ParseResult StatementsParser::ParseSet(LexScanner& lexer, Stat
309314
ExpressionEvaluatorPtr<> valueExpr;
310315
if (operTok == '=')
311316
{
312-
ExpressionParser exprParser;
317+
ExpressionParser exprParser(m_settings);
313318
auto expr = exprParser.ParseFullExpression(lexer);
314319
if (!expr)
315320
return expr.get_unexpected();
@@ -478,7 +483,7 @@ nonstd::expected<MacroParams, ParseError> StatementsParser::ParseMacroParams(Lex
478483
if (lexer.EatIfEqual(')'))
479484
return std::move(items);
480485

481-
ExpressionParser exprParser;
486+
ExpressionParser exprParser(m_settings);
482487

483488
do
484489
{
@@ -562,7 +567,7 @@ StatementsParser::ParseResult StatementsParser::ParseCall(LexScanner& lexer, Sta
562567
CallParams callParams;
563568
if (lexer.EatIfEqual('('))
564569
{
565-
ExpressionParser exprParser;
570+
ExpressionParser exprParser(m_settings);
566571
auto result = exprParser.ParseCallParams(lexer);
567572
if (!result)
568573
return result.get_unexpected();
@@ -606,7 +611,7 @@ StatementsParser::ParseResult StatementsParser::ParseInclude(LexScanner& lexer,
606611

607612
// auto operTok = lexer.NextToken();
608613
ExpressionEvaluatorPtr<> valueExpr;
609-
ExpressionParser exprParser;
614+
ExpressionParser exprParser(m_settings);
610615
auto expr = exprParser.ParseFullExpression(lexer);
611616
if (!expr)
612617
return expr.get_unexpected();
@@ -662,7 +667,7 @@ StatementsParser::ParseResult StatementsParser::ParseInclude(LexScanner& lexer,
662667
StatementsParser::ParseResult StatementsParser::ParseImport(LexScanner& lexer, StatementInfoList& statementsInfo, const Token& stmtTok)
663668
{
664669
ExpressionEvaluatorPtr<> valueExpr;
665-
ExpressionParser exprParser;
670+
ExpressionParser exprParser(m_settings);
666671
auto expr = exprParser.ParseFullExpression(lexer);
667672
if (!expr)
668673
return expr.get_unexpected();
@@ -709,7 +714,7 @@ StatementsParser::ParseResult StatementsParser::ParseImport(LexScanner& lexer, S
709714
StatementsParser::ParseResult StatementsParser::ParseFrom(LexScanner& lexer, StatementInfoList& statementsInfo, const Token& stmtTok)
710715
{
711716
ExpressionEvaluatorPtr<> valueExpr;
712-
ExpressionParser exprParser;
717+
ExpressionParser exprParser(m_settings);
713718
auto expr = exprParser.ParseFullExpression(lexer);
714719
if (!expr)
715720
return expr.get_unexpected();
@@ -795,4 +800,19 @@ StatementsParser::ParseResult StatementsParser::ParseFrom(LexScanner& lexer, Sta
795800
return ParseResult();
796801
}
797802

803+
StatementsParser::ParseResult StatementsParser::ParseDo(LexScanner& lexer, StatementInfoList& statementsInfo, const Token& stmtTok)
804+
{
805+
ExpressionEvaluatorPtr<> valueExpr;
806+
ExpressionParser exprParser(m_settings);
807+
auto expr = exprParser.ParseFullExpression(lexer);
808+
if (!expr)
809+
return expr.get_unexpected();
810+
valueExpr = *expr;
811+
812+
auto renderer = std::make_shared<DoStatement>(valueExpr);
813+
statementsInfo.back().currentComposition->AddRenderer(renderer);
814+
815+
return jinja2::StatementsParser::ParseResult();
816+
}
817+
798818
}

src/template_parser.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ template<typename T = void>
4949
struct ParserTraitsBase
5050
{
5151
static Token::Type s_keywords[];
52-
static KeywordsInfo s_keywordsInfo[39];
52+
static KeywordsInfo s_keywordsInfo[40];
5353
static std::unordered_map<int, MultiStringLiteral> s_tokens;
5454
};
5555

@@ -194,6 +194,10 @@ class StatementsParser
194194
public:
195195
using ParseResult = nonstd::expected<void, ParseError>;
196196

197+
StatementsParser(const Settings& settings)
198+
: m_settings(settings)
199+
{}
200+
197201
ParseResult Parse(LexScanner& lexer, StatementInfoList& statementsInfo);
198202

199203
private:
@@ -216,6 +220,10 @@ class StatementsParser
216220
ParseResult ParseInclude(LexScanner& lexer, StatementInfoList& statementsInfo, const Token& stmtTok);
217221
ParseResult ParseImport(LexScanner& lexer, StatementInfoList& statementsInfo, const Token& stmtTok);
218222
ParseResult ParseFrom(LexScanner& lexer, StatementInfoList& statementsInfo, const Token& stmtTok);
223+
ParseResult ParseDo(LexScanner& lexer, StatementInfoList& statementsInfo, const Token& stmtTok);
224+
225+
private:
226+
Settings m_settings;
219227
};
220228

221229
template<typename CharT>
@@ -532,7 +540,7 @@ class TemplateParser : public LexerHelper
532540
if (!lexer.Preprocess())
533541
return MakeParseError(ErrorCode::Unspecified, MakeToken(Token::Unknown, {range.startOffset, range.startOffset + 1}));
534542

535-
P praser;
543+
P praser(m_settings);
536544
LexScanner scanner(lexer);
537545
auto result = praser.Parse(scanner, std::forward<Args>(args)...);
538546
if (!result)
@@ -773,7 +781,7 @@ class TemplateParser : public LexerHelper
773781
};
774782

775783
template<typename T>
776-
KeywordsInfo ParserTraitsBase<T>::s_keywordsInfo[39] = {
784+
KeywordsInfo ParserTraitsBase<T>::s_keywordsInfo[40] = {
777785
{UNIVERSAL_STR("for"), Keyword::For},
778786
{UNIVERSAL_STR("endfor"), Keyword::Endfor},
779787
{UNIVERSAL_STR("in"), Keyword::In},
@@ -813,6 +821,7 @@ KeywordsInfo ParserTraitsBase<T>::s_keywordsInfo[39] = {
813821
{UNIVERSAL_STR("context"), Keyword::Context},
814822
{UNIVERSAL_STR("from"), Keyword::From},
815823
{UNIVERSAL_STR("as"), Keyword::As},
824+
{UNIVERSAL_STR("do"), Keyword::Do},
816825
};
817826

818827
template<typename T>
@@ -878,6 +887,7 @@ std::unordered_map<int, MultiStringLiteral> ParserTraitsBase<T>::s_tokens = {
878887
{Token::Context, UNIVERSAL_STR("context")},
879888
{Token::From, UNIVERSAL_STR("form")},
880889
{Token::As, UNIVERSAL_STR("as")},
890+
{Token::Do, UNIVERSAL_STR("do")},
881891
{Token::CommentBegin, UNIVERSAL_STR("{#")},
882892
{Token::CommentEnd, UNIVERSAL_STR("#}")},
883893
{Token::StmtBegin, UNIVERSAL_STR("{%")},

0 commit comments

Comments
 (0)