package org.jtwig.parser.parboiled.expression; import org.jtwig.model.expression.Expression; import org.jtwig.model.expression.FunctionExpression; import org.jtwig.parser.parboiled.ParserContext; import org.jtwig.parser.parboiled.base.BasicParser; import org.jtwig.parser.parboiled.base.LexicParser; import org.jtwig.parser.parboiled.base.PositionTrackerParser; import org.jtwig.parser.parboiled.base.SpacingParser; 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 FunctionExpressionParser extends ExpressionParser<FunctionExpression> { public FunctionExpressionParser(ParserContext context) { super(FunctionExpressionParser.class, context); createParser(ArgumentsParser.class, context); createParser(FunctionNameParser.class, context); } @Override public Rule ExpressionRule() { PositionTrackerParser positionTrackerParser = parserContext().parser(PositionTrackerParser.class); SpacingParser spacingParser = parserContext().parser(SpacingParser.class); FunctionNameParser functionNameParser = parserContext().parser(FunctionNameParser.class); ArgumentsParser argumentsParser = parserContext().parser(ArgumentsParser.class); return Sequence( positionTrackerParser.PushPosition(), functionNameParser.Name(), argumentsParser.Arguments(), spacingParser.Spacing(), push(new FunctionExpression( positionTrackerParser.pop(2), functionNameParser.pop(1), argumentsParser.pop() )) ); } public static class FunctionNameParser extends BasicParser<String> { public FunctionNameParser(ParserContext context) { super(FunctionNameParser.class, context); } public Rule Name () { return FirstOf( Sequence( parserContext().parser(LexicParser.class).Keyword(Keyword.BLOCK), push("block") ), Sequence( parserContext().parser(LexicParser.class).Identifier(), push(match()) ) ); } } public static class ArgumentsParser extends BasicParser<List<Expression>> { public ArgumentsParser(ParserContext context) { super(ArgumentsParser.class, context); } public Rule Arguments() { SpacingParser spacingParser = parserContext().parser(SpacingParser.class); return Sequence( push(new ArrayList<Expression>()), FirstOf( Sequence( spacingParser.Spacing(), "(", spacingParser.Spacing(), Optional( ArgumentExpression(), ZeroOrMore( String(","), spacingParser.Spacing(), ArgumentExpression() ) ), ")" ), Sequence( spacingParser.Mandatory(), ArgumentPrimaryExpression() ) ) ); } Rule ArgumentExpression() { SpacingParser spacingParser = parserContext().parser(SpacingParser.class); AnyExpressionParser anyExpressionParser = parserContext().parser(AnyExpressionParser.class); return Sequence( anyExpressionParser.ExpressionRule(), spacingParser.Spacing(), peek(1).add(anyExpressionParser.pop()) ); } Rule ArgumentPrimaryExpression() { SpacingParser spacingParser = parserContext().parser(SpacingParser.class); ConstantExpressionParser constantExpressionParser = parserContext().parser(ConstantExpressionParser.class); return Sequence( constantExpressionParser.ExpressionRule(), spacingParser.Spacing(), peek(1).add(constantExpressionParser.pop()) ); } } }