@@ -22,6 +22,9 @@ namespace inja {
2222 * \brief Class for parsing an inja Template.
2323 */
2424class Parser {
25+ using Arguments = std::vector<std::shared_ptr<ExpressionNode>>;
26+ using OperatorStack = std::stack<std::shared_ptr<FunctionNode>>;
27+
2528 const ParserConfig& config;
2629
2730 Lexer lexer;
@@ -31,18 +34,11 @@ class Parser {
3134 Token tok, peek_tok;
3235 bool have_peek_tok {false };
3336
34- size_t current_paren_level {0 };
35- size_t current_bracket_level {0 };
36- size_t current_brace_level {0 };
37-
3837 std::string_view literal_start;
3938
4039 BlockNode* current_block {nullptr };
4140 ExpressionListNode* current_expression_list {nullptr };
42- std::stack<std::pair<FunctionNode*, size_t >> function_stack;
43- std::vector<std::shared_ptr<ExpressionNode>> arguments;
4441
45- std::stack<std::shared_ptr<FunctionNode>> operator_stack;
4642 std::stack<IfStatementNode*> if_statement_stack;
4743 std::stack<ForStatementNode*> for_statement_stack;
4844 std::stack<BlockStatementNode*> block_statement_stack;
@@ -67,12 +63,12 @@ class Parser {
6763 }
6864 }
6965
70- inline void add_literal (const char * content_ptr) {
66+ inline void add_literal (Arguments &arguments, const char * content_ptr) {
7167 std::string_view data_text (literal_start.data (), tok.text .data () - literal_start.data () + tok.text .size ());
7268 arguments.emplace_back (std::make_shared<LiteralNode>(data_text, data_text.data () - content_ptr));
7369 }
7470
75- inline void add_operator () {
71+ inline void add_operator (Arguments &arguments, OperatorStack &operator_stack ) {
7672 auto function = operator_stack.top ();
7773 operator_stack.pop ();
7874
@@ -140,19 +136,29 @@ class Parser {
140136 }
141137
142138 bool parse_expression (Template& tmpl, Token::Kind closing) {
143- while (tok.kind != closing && tok.kind != Token::Kind::Eof) {
139+ current_expression_list->root = parse_expression (tmpl);
140+ return tok.kind == closing;
141+ }
142+
143+ std::shared_ptr<ExpressionNode> parse_expression (Template& tmpl) {
144+ size_t current_bracket_level {0 };
145+ size_t current_brace_level {0 };
146+ Arguments arguments;
147+ OperatorStack operator_stack;
148+
149+ while (tok.kind != Token::Kind::Eof) {
144150 // Literals
145151 switch (tok.kind ) {
146152 case Token::Kind::String: {
147153 if (current_brace_level == 0 && current_bracket_level == 0 ) {
148154 literal_start = tok.text ;
149- add_literal (tmpl.content .c_str ());
155+ add_literal (arguments, tmpl.content .c_str ());
150156 }
151157 } break ;
152158 case Token::Kind::Number: {
153159 if (current_brace_level == 0 && current_bracket_level == 0 ) {
154160 literal_start = tok.text ;
155- add_literal (tmpl.content .c_str ());
161+ add_literal (arguments, tmpl.content .c_str ());
156162 }
157163 } break ;
158164 case Token::Kind::LeftBracket: {
@@ -174,7 +180,7 @@ class Parser {
174180
175181 current_bracket_level -= 1 ;
176182 if (current_brace_level == 0 && current_bracket_level == 0 ) {
177- add_literal (tmpl.content .c_str ());
183+ add_literal (arguments, tmpl.content .c_str ());
178184 }
179185 } break ;
180186 case Token::Kind::RightBrace: {
@@ -184,7 +190,7 @@ class Parser {
184190
185191 current_brace_level -= 1 ;
186192 if (current_brace_level == 0 && current_bracket_level == 0 ) {
187- add_literal (tmpl.content .c_str ());
193+ add_literal (arguments, tmpl.content .c_str ());
188194 }
189195 } break ;
190196 case Token::Kind::Id: {
@@ -195,7 +201,7 @@ class Parser {
195201 tok.text == static_cast <decltype (tok.text )>(" null" )) {
196202 if (current_brace_level == 0 && current_bracket_level == 0 ) {
197203 literal_start = tok.text ;
198- add_literal (tmpl.content .c_str ());
204+ add_literal (arguments, tmpl.content .c_str ());
199205 }
200206
201207 // Operator
@@ -204,8 +210,30 @@ class Parser {
204210
205211 // Functions
206212 } else if (peek_tok.kind == Token::Kind::LeftParen) {
207- operator_stack.emplace (std::make_shared<FunctionNode>(static_cast <std::string>(tok.text ), tok.text .data () - tmpl.content .c_str ()));
208- function_stack.emplace (operator_stack.top ().get (), current_paren_level);
213+ auto func = std::make_shared<FunctionNode>(tok.text , tok.text .data () - tmpl.content .c_str ());
214+ get_next_token ();
215+ do {
216+ get_next_token ();
217+ auto expr = parse_expression (tmpl);
218+ if (!expr) {
219+ break ;
220+ }
221+ func->number_args += 1 ;
222+ func->arguments .emplace_back (expr);
223+ } while (tok.kind == Token::Kind::Comma);
224+ if (tok.kind != Token::Kind::RightParen) {
225+ throw_parser_error (" expected right parenthesis, got '" + tok.describe () + " '" );
226+ }
227+
228+ auto function_data = function_storage.find_function (func->name , func->number_args );
229+ if (function_data.operation == FunctionStorage::Operation::None) {
230+ throw_parser_error (" unknown function " + func->name );
231+ }
232+ func->operation = function_data.operation ;
233+ if (function_data.operation == FunctionStorage::Operation::Callback) {
234+ func->callback = function_data.callback ;
235+ }
236+ arguments.emplace_back (func);
209237
210238 // Variables
211239 } else {
@@ -291,20 +319,15 @@ class Parser {
291319
292320 while (!operator_stack.empty () &&
293321 ((operator_stack.top ()->precedence > function_node->precedence ) ||
294- (operator_stack.top ()->precedence == function_node->precedence && function_node->associativity == FunctionNode::Associativity::Left)) &&
295- (operator_stack.top ()->operation != FunctionStorage::Operation::ParenLeft)) {
296- add_operator ();
322+ (operator_stack.top ()->precedence == function_node->precedence && function_node->associativity == FunctionNode::Associativity::Left))) {
323+ add_operator (arguments, operator_stack);
297324 }
298325
299326 operator_stack.emplace (function_node);
300327 } break ;
301328 case Token::Kind::Comma: {
302329 if (current_brace_level == 0 && current_bracket_level == 0 ) {
303- if (function_stack.empty ()) {
304- throw_parser_error (" unexpected ','" );
305- }
306-
307- function_stack.top ().first ->number_args += 1 ;
330+ goto break_loop;
308331 }
309332 } break ;
310333 case Token::Kind::Colon: {
@@ -313,64 +336,36 @@ class Parser {
313336 }
314337 } break ;
315338 case Token::Kind::LeftParen: {
316- current_paren_level += 1 ;
317- operator_stack.emplace (std::make_shared<FunctionNode>(FunctionStorage::Operation::ParenLeft, tok.text .data () - tmpl.content .c_str ()));
318-
319- get_peek_token ();
320- if (peek_tok.kind == Token::Kind::RightParen) {
321- if (!function_stack.empty () && function_stack.top ().second == current_paren_level - 1 ) {
322- function_stack.top ().first ->number_args = 0 ;
323- }
324- }
325- } break ;
326- case Token::Kind::RightParen: {
327- current_paren_level -= 1 ;
328- while (!operator_stack.empty () && operator_stack.top ()->operation != FunctionStorage::Operation::ParenLeft) {
329- add_operator ();
339+ get_next_token ();
340+ auto expr = parse_expression (tmpl);
341+ if (tok.kind != Token::Kind::RightParen) {
342+ throw_parser_error (" expected right parenthesis, got '" + tok.describe () + " '" );
330343 }
331-
332- if (!operator_stack.empty () && operator_stack.top ()->operation == FunctionStorage::Operation::ParenLeft) {
333- operator_stack.pop ();
344+ if (!expr) {
345+ throw_parser_error (" empty expression in parentheses" );
334346 }
335-
336- if (!function_stack.empty () && function_stack.top ().second == current_paren_level) {
337- auto func = function_stack.top ().first ;
338- auto function_data = function_storage.find_function (func->name , func->number_args );
339- if (function_data.operation == FunctionStorage::Operation::None) {
340- throw_parser_error (" unknown function " + func->name );
341- }
342- func->operation = function_data.operation ;
343- if (function_data.operation == FunctionStorage::Operation::Callback) {
344- func->callback = function_data.callback ;
345- }
346-
347- if (operator_stack.empty ()) {
348- throw_parser_error (" internal error at function " + func->name );
349- }
350-
351- add_operator ();
352- function_stack.pop ();
353- }
354- }
347+ arguments.emplace_back (expr);
348+ } break ;
355349 default :
356- break ;
350+ goto break_loop ;
357351 }
358352
359353 get_next_token ();
360354 }
361355
356+ break_loop:
362357 while (!operator_stack.empty ()) {
363- add_operator ();
358+ add_operator (arguments, operator_stack );
364359 }
365360
361+ std::shared_ptr<ExpressionNode> expr;
366362 if (arguments.size () == 1 ) {
367- current_expression_list-> root = arguments[0 ];
363+ expr = arguments[0 ];
368364 arguments = {};
369365 } else if (arguments.size () > 1 ) {
370366 throw_parser_error (" malformed expression" );
371367 }
372-
373- return true ;
368+ return expr;
374369 }
375370
376371 bool parse_statement (Template& tmpl, Token::Kind closing, std::string_view path) {
@@ -604,10 +599,6 @@ class Parser {
604599 current_expression_list = expression_list_node.get ();
605600
606601 if (!parse_expression (tmpl, Token::Kind::ExpressionClose)) {
607- throw_parser_error (" expected expression, got '" + tok.describe () + " '" );
608- }
609-
610- if (tok.kind != Token::Kind::ExpressionClose) {
611602 throw_parser_error (" expected expression close, got '" + tok.describe () + " '" );
612603 }
613604 } break ;
0 commit comments