/** * A {@link Parser} that matches this parser zero or many times * until the given parser succeeds. The input that matches the given parser * will not be consumed. The input that matches this parser will * be collected in a list that will be returned by this function. * * @since 2.2 */ public final Parser<List<T>> until(Parser<?> parser) { return parser.not().next(this).many().followedBy(parser.peek()); }
/** * A {@link Parser} that runs {@code this} for 0 or more times delimited and terminated by * {@code delim}. * * <p>The return values are collected in a {@link List}. */ public final Parser<List<T>> endBy(Parser<?> delim) { return followedBy(delim).many(); }
static Parser<Declaration> classDef(Parser<Modifier> mod, Parser<Member> member) { return Parsers.sequence( mod.many(), term("class").next(Terminals.Identifier.PARSER), TYPE_PARAMETERS.optional(), term("extends").next(TypeLiteralParser.ELEMENT_TYPE_LITERAL).optional(), term("implements").next(TypeLiteralParser.ELEMENT_TYPE_LITERAL.sepBy1(term(","))).optional(), body(member), ClassDef::new); }
static Parser<Relation> union(Parser<Relation> rel) { Parser.Reference<Relation> ref = Parser.newReference(); Parser<Relation> parser = ExpressionParser.paren(ref.lazy()).or(rel).infixl( TerminalParser.term("union").next(TerminalParser.term("all").succeeds()) .label("relation") .map(a -> (l, r) -> new UnionRelation(l, a, r))); ref.set(parser); return parser; }
static Parser<LambdaExpression> lambdaExpression( Parser<Expression> expression, Parser<Statement> stmt) { Parser<LambdaExpression.Parameter> typedParam = Parsers.sequence( TypeLiteralParser.TYPE_LITERAL, Terminals.Identifier.PARSER, LambdaExpression.Parameter::new); Parser<LambdaExpression.Parameter> simpleParam = Terminals.Identifier.PARSER.map(LambdaExpression.Parameter::new); Parser<LambdaExpression.Parameter> lambdaParam = typedParam.or(simpleParam); Parser<List<LambdaExpression.Parameter>> params = paren(lambdaParam.sepBy(term(","))).or(lambdaParam.map(Collections::singletonList)); Parser<Statement> body = StatementParser.blockStatement(stmt).<Statement>cast() .or(expression.map(ExpressionStatement::new)); return Parsers.sequence(params, term("->").next(body), LambdaExpression::new); }
static Parser<Annotation> annotation(Parser<Expression> expr) { Parser<Annotation.Element> element = Parsers.sequence( Terminals.Identifier.PARSER.followedBy(term("=")).atomic().optional(), ExpressionParser.arrayInitializerOrRegularExpression(expr), Annotation.Element::new); return Parsers.sequence( term("@").next(TypeLiteralParser.ELEMENT_TYPE_LITERAL), paren(element.sepBy(term(","))).optional(), Annotation::new); }
@SuppressWarnings({"rawtypes", "unchecked"}) private static <T> Parser<T> build( Parser op, Associativity associativity, Parser<T> operand) { switch (associativity) { case PREFIX: return operand.prefix(op); case POSTFIX: return operand.postfix(op); case LASSOC: return operand.infixl(op); case RASSOC: return operand.infixr(op); case NASSOC: return operand.infixn(op); default: throw new AssertionError(); } } }
static Parser<Statement> tryStatement(Parser<Modifier> mod, Parser<Statement> stmt) { Parser<BlockStatement> block = blockStatement(stmt); return Parsers.sequence( term("try").next(block), Parsers.sequence( term("catch").next(between(term("("), parameter(mod), term(")"))), block, TryStatement.CatchBlock::new).many(), term("finally").next(block).optional(), TryStatement::new); }
static Parser<Statement> assertStatement(Parser<Expression> expr) { return Parsers.sequence( term("assert").next(expr), term(":").next(expr).optional().followedBy(term(";")), AssertStatement::new); }
/** * A {@link Parser} that succeeds only if the {@link Token} objects in the {@link List} are * adjacent. */ public static Parser<Token> adjacent(Parser<List<Token>> parser, final Parser<?> otherwise) { return parser.next(tokens -> { if (tokens.isEmpty()) return Parsers.always(); int offset = tokens.get(0).index(); for (Token token : tokens) { if (token.index() != offset) { return otherwise; } offset += token.length(); } return Parsers.always(); }).atomic().source().token(); }
/** * A scanner for a non-nestable block comment that starts with {@code begin} and ends with * {@code end}. * * @param begin begins a block comment * @param end ends a block comment * @param commented the commented pattern. * @return the Scanner for the block comment. */ public static Parser<Void> blockComment(Parser<Void> begin, Parser<Void> end, Parser<?> commented) { return Parsers.sequence(begin, end.not().next(commented).skipMany(), end); }
/** * A {@link Parser} for left-associative infix operator. Runs {@code this} for the left operand, and then runs * {@code operator} and {@code this} for the operator and the right operand for 0 or more times greedily. * The {@link BiFunction} objects returned from {@code operator} are applied from left to right to the * return values of {@code this}, if any. For example: * {@code a + b + c + d} is evaluated as {@code (((a + b)+c)+d)}. * * <p> {@code p.infixl(op)} is equivalent to {@code p (op p)*} in EBNF. */ public final Parser<T> infixl( Parser<? extends BiFunction<? super T, ? super T, ? extends T>> operator) { BiFunction<BiFunction<? super T, ? super T, ? extends T>, T, Function<? super T, ? extends T>> rightToLeft = (op, r) -> l -> op.apply(l, r); return next(first -> Parsers.sequence(operator, this, rightToLeft) .many() .map(maps -> applyInfixOperators(first, maps))); }
static Parser<Statement> expressionList(Parser<Expression> expr) { return expr.sepBy1(term(",")).followedBy(term(";")).map(ExpressionListStatement::new); }