package org.jtwig.parser.parboiled.node; import org.jtwig.model.expression.ConstantExpression; import org.jtwig.model.tree.IfNode; import org.jtwig.model.tree.IfNode.IfConditionNode; import org.jtwig.parser.parboiled.ParserContext; import org.jtwig.parser.parboiled.base.*; import org.jtwig.parser.parboiled.expression.AnyExpressionParser; import org.jtwig.parser.parboiled.model.Keyword; import org.parboiled.Rule; import java.util.ArrayList; import java.util.Collection; import static org.parboiled.Parboiled.createParser; public class IfNodeParser extends NodeParser<IfNode> { public IfNodeParser(ParserContext context) { super(IfNodeParser.class, context); createParser(IfConditionNodeParser.class, context); } @Override public Rule NodeRule() { PositionTrackerParser positionTrackerParser = parserContext().parser(PositionTrackerParser.class); IfConditionNodeParser conditionNodeParser = parserContext().parser(IfConditionNodeParser.class); return Sequence( positionTrackerParser.PushPosition(), conditionNodeParser.NodeRule(), push(new IfNode(positionTrackerParser.pop(1), conditionNodeParser.pop())) ); } public static class IfConditionNodeParser extends BasicParser<Collection<IfConditionNode>> { public IfConditionNodeParser(ParserContext context) { super(IfConditionNodeParser.class, context); } Rule NodeRule() { PositionTrackerParser positionTrackerParser = parserContext().parser(PositionTrackerParser.class); LimitsParser limitsParser = parserContext().parser(LimitsParser.class); SpacingParser spacingParser = parserContext().parser(SpacingParser.class); AnyExpressionParser anyExpressionParser = parserContext().parser(AnyExpressionParser.class); LexicParser lexicParser = parserContext().parser(LexicParser.class); CompositeNodeParser compositeNodeParser = parserContext().parser(CompositeNodeParser.class); return Sequence( push(new ArrayList<IfConditionNode>()), // Start Sequence( positionTrackerParser.PushPosition(), limitsParser.startCode(), spacingParser.Spacing(), lexicParser.Keyword(Keyword.IF) ), ifConditionExpression(limitsParser, spacingParser, anyExpressionParser), // Content compositeNodeParser.NodeRule(), peek(3).add(new IfConditionNode( positionTrackerParser.pop(2), anyExpressionParser.pop(1), compositeNodeParser.pop() )), ZeroOrMore( elseIfCondition() ), Optional( elseCondition() ), // End Mandatory(Sequence( limitsParser.startCode(), spacingParser.Spacing(), lexicParser.Keyword(Keyword.END_IF), spacingParser.Spacing(), Mandatory(limitsParser.endCode(), "If condition endif code island not closed") ), "Missing endif tag") ); } public Rule ifConditionExpression(LimitsParser limitsParser, SpacingParser spacingParser, AnyExpressionParser anyExpressionParser) { return Sequence( spacingParser.Spacing(), Mandatory(anyExpressionParser.ExpressionRule(), "Expecting an expression together with the if construction"), spacingParser.Spacing(), Mandatory(limitsParser.endCode(), "If condition code island not closed") ); } Rule elseIfCondition() { PositionTrackerParser positionTrackerParser = parserContext().parser(PositionTrackerParser.class); LimitsParser limitsParser = parserContext().parser(LimitsParser.class); SpacingParser spacingParser = parserContext().parser(SpacingParser.class); AnyExpressionParser anyExpressionParser = parserContext().parser(AnyExpressionParser.class); LexicParser lexicParser = parserContext().parser(LexicParser.class); CompositeNodeParser compositeNodeParser = parserContext().parser(CompositeNodeParser.class); return Sequence( // Start Sequence( positionTrackerParser.PushPosition(), limitsParser.startCode(), spacingParser.Spacing(), lexicParser.Keyword(Keyword.ELSE_IF) ), ifConditionExpression(limitsParser, spacingParser, anyExpressionParser), // Content compositeNodeParser.NodeRule(), peek(3).add(new IfConditionNode( positionTrackerParser.pop(2), anyExpressionParser.pop(1), compositeNodeParser.pop() )) ); } Rule elseCondition() { PositionTrackerParser positionTrackerParser = parserContext().parser(PositionTrackerParser.class); LimitsParser limitsParser = parserContext().parser(LimitsParser.class); SpacingParser spacingParser = parserContext().parser(SpacingParser.class); LexicParser lexicParser = parserContext().parser(LexicParser.class); CompositeNodeParser compositeNodeParser = parserContext().parser(CompositeNodeParser.class); return Sequence( // Start Sequence( positionTrackerParser.PushPosition(), limitsParser.startCode(), spacingParser.Spacing(), lexicParser.Keyword(Keyword.ELSE), spacingParser.Spacing(), Mandatory(limitsParser.endCode(), "Expecting ending of else block") ), compositeNodeParser.NodeRule(), peek(2).add(new IfConditionNode( positionTrackerParser.pop(1), new ConstantExpression(positionTrackerParser.currentPosition(), true), compositeNodeParser.pop() )) ); } } }