package org.jtwig.parser.parboiled.node; import org.jtwig.model.tree.ForLoopNode; import org.jtwig.parser.parboiled.ParserContext; import org.jtwig.parser.parboiled.base.LexicParser; import org.jtwig.parser.parboiled.base.LimitsParser; import org.jtwig.parser.parboiled.base.PositionTrackerParser; import org.jtwig.parser.parboiled.base.SpacingParser; import org.jtwig.parser.parboiled.expression.AnyExpressionParser; import org.jtwig.parser.parboiled.expression.VariableExpressionParser; import org.jtwig.parser.parboiled.model.Keyword; import org.parboiled.Rule; public class ForLoopNodeParser extends NodeParser<ForLoopNode> { public ForLoopNodeParser(ParserContext context) { super(ForLoopNodeParser.class, context); } @Override public Rule NodeRule() { LimitsParser limitsParser = parserContext().parser(LimitsParser.class); PositionTrackerParser positionTrackerParser = parserContext().parser(PositionTrackerParser.class); SpacingParser spacingParser = parserContext().parser(SpacingParser.class); LexicParser lexicParser = parserContext().parser(LexicParser.class); VariableExpressionParser variableExpressionParser = parserContext().parser(VariableExpressionParser.class); AnyExpressionParser anyExpressionParser = parserContext().parser(AnyExpressionParser.class); CompositeNodeParser compositeNodeParser = parserContext().parser(CompositeNodeParser.class); return Sequence( positionTrackerParser.PushPosition(), // Start Sequence( limitsParser.startCode(), spacingParser.Spacing(), lexicParser.Keyword(Keyword.FOR), spacingParser.Spacing(), Mandatory(variableExpressionParser.ExpressionRule(), "Expecting a variable name in for loop. Example: {% for value in list %}"), spacingParser.Spacing(), FirstOf( Sequence( String(","), spacingParser.Spacing(), Mandatory(variableExpressionParser.ExpressionRule(), "Expecting a second variable name in for loop. Example: {% for key, value in list %}"), spacingParser.Spacing() ), variableExpressionParser.push(null) ), Mandatory(lexicParser.Keyword(Keyword.IN), "Malformed for loop, missing 'in' keyword. For example: {% for i in list %}"), spacingParser.Spacing(), Mandatory(anyExpressionParser.ExpressionRule(), "Expecting an expression in for loop"), spacingParser.Spacing(), Mandatory(limitsParser.endCode(), "Malformed for loop start syntax, missing code island ending symbol") ), compositeNodeParser.NodeRule(), // End Mandatory(Sequence( limitsParser.startCode(), spacingParser.Spacing(), lexicParser.Keyword(Keyword.END_FOR), spacingParser.Spacing(), Mandatory(limitsParser.endCode(), "Malformed for loop end syntax, missing code island ending symbol") ), "Missing endfor tag"), push(new ForLoopNode( positionTrackerParser.pop(4), variableExpressionParser.pop(3), variableExpressionParser.pop(2), variableExpressionParser.pop(1), compositeNodeParser.pop() )) ); } }