package org.jtwig.parser.parboiled.node; import org.jtwig.model.expression.VariableExpression; import org.jtwig.model.tree.MacroNode; import org.jtwig.parser.parboiled.ParserContext; import org.jtwig.parser.parboiled.base.*; import org.jtwig.parser.parboiled.expression.VariableExpressionParser; import org.jtwig.parser.parboiled.model.Keyword; import org.parboiled.Rule; import java.util.ArrayList; import java.util.List; import static org.parboiled.Parboiled.createParser; public class MacroNodeParser extends NodeParser<MacroNode> { public MacroNodeParser(ParserContext context) { super(MacroNodeParser.class, context); createParser(ParametersParser.class, context); } @Override public Rule NodeRule() { PositionTrackerParser positionTrackerParser = parserContext().parser(PositionTrackerParser.class); LimitsParser limitsParser = parserContext().parser(LimitsParser.class); SpacingParser spacingParser = parserContext().parser(SpacingParser.class); LexicParser lexicParser = parserContext().parser(LexicParser.class); VariableExpressionParser variableExpressionParser = parserContext().parser(VariableExpressionParser.class); ParametersParser parametersParser = parserContext().parser(ParametersParser.class); CompositeNodeParser nodeParser = parserContext().parser(CompositeNodeParser.class); return Sequence( positionTrackerParser.PushPosition(), // Start Sequence( limitsParser.startCode(), spacingParser.Spacing(), lexicParser.Keyword(Keyword.MACRO), spacingParser.Spacing(), Mandatory(variableExpressionParser.ExpressionRule(), "Missing macro name"), spacingParser.Spacing(), Mandatory(parametersParser.Parameters(), "Missing macro arguments"), spacingParser.Spacing(), Mandatory(limitsParser.endCode(), "Code island not closed"), spacingParser.Spacing() ), nodeParser.NodeRule(), // End Mandatory(Sequence( limitsParser.startCode(), spacingParser.Spacing(), lexicParser.Keyword(Keyword.END_MACRO), spacingParser.Spacing(), Mandatory(limitsParser.endCode(), "Code island not closed") ), "Missing macroend tag"), push(MacroNode.create( positionTrackerParser.pop(3), variableExpressionParser.pop(2), parametersParser.pop(1), nodeParser.pop() )) ); } public static class ParametersParser extends BasicParser<List<VariableExpression>> { public ParametersParser(ParserContext context) { super(ParametersParser.class, context); } Rule Parameters() { SpacingParser spacingParser = parserContext().parser(SpacingParser.class); VariableExpressionParser variableExpressionParser = parserContext().parser(VariableExpressionParser.class); return Sequence( push(new ArrayList<VariableExpression>()), String("("), spacingParser.Spacing(), Optional( variableExpressionParser.ExpressionRule(), spacingParser.Spacing(), peek(1).add(variableExpressionParser.pop()), ZeroOrMore( String(","), spacingParser.Spacing(), variableExpressionParser.ExpressionRule(), spacingParser.Spacing(), peek(1).add(variableExpressionParser.pop()) ) ), String(")") ); } } }