static Parser<Expression> arrayInitializerOrRegularExpression(Parser<Expression> expr) { return arrayInitializer(expr).or(expr); }
static final Parser<Relation> aliasable(Parser<Relation> rel) { return alias(rel).or(rel); }
/** * A {@link Parser} that parses non-associative infix operator. * Runs {@code this} for the left operand, and then * runs {@code op} and {@code this} for the operator and the right operand optionally. * The {@link BiFunction} objects * returned from {@code op} are applied to the return values of the two operands, if any. * * <p> {@code p.infixn(op)} is equivalent to {@code p (op p)?} in EBNF. */ public final Parser<T> infixn(Parser<? extends BiFunction<? super T, ? super T, ? extends T>> op) { return next(a -> { Parser<T> shift = Parsers.sequence(op, this, (m2, b) -> m2.apply(a, b)); return shift.or(Parsers.constant(a)); }); }
/** * {@code (foo)} can be a parenthesized expression, or the prefix of a cast expression, * depending on whether there's an expression following. */ static final Parser<Expression> castOrExpression(Parser<Expression> expr) { Parser<Expression> explicitCast = Parsers.sequence(paren(TypeLiteralParser.TYPE_LITERAL), expr, CastExpression::new); return explicitCast.or(paren(expr)); }
static <T> T parse(Parser<T> parser, String source) { return parser.from(INDENTATION.lexer(TOKENIZER, Indentation.WHITESPACES.or(COMMENT).many())) .parse(source); } }
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<Expression> nullCheck(Parser<Expression> expr) { return Parsers.sequence( expr, phrase("is not").retn(Op.NOT).or(phrase("is").retn(Op.IS)), NULL, BinaryExpression::new); }
static Parser<TypeLiteral> elementTypeLiteral() { Parser.Reference<TypeLiteral> ref = Parser.newReference(); Parser<TypeLiteral> lazy = ref.lazy(); Parser<TypeLiteral> arg = wildcard(lazy).or(lazy); Parser<String> nativeTypeName = TerminalParser.oneOf( "byte", "short", "int", "long", "boolean", "char", "float", "double", "void") .map(Object::toString); Parser<String> typeName = nativeTypeName.or(Terminals.Identifier.PARSER); Parser<TypeLiteral> parser = Parsers.sequence( typeName.sepBy1(term(".")), TypeLiteralParser.optionalTypeArgs(arg), SimpleTypeLiteral::new); ref.set(parser.postfix(ARRAY_OF)); return parser; }
static Parser<DefBody> body(Parser<Member> member) { Parser<Member> empty = term(";").retn(null); return Parsers.between(term("{"), empty.or(member).many().map(DeclarationParser::removeNulls), term("}")) .map(DefBody::new); }
/** The {@link Parser} for a full fledged SQL query. */ public static Parser<Relation> query() { Parser.Reference<Relation> relationRef = Parser.newReference(); Parser<Relation> subQuery = ExpressionParser.paren(relationRef.lazy()); Parser.Reference<Expression> conditionRef = Parser.newReference(); Parser<Expression> expr = ExpressionParser.expression(conditionRef.lazy()); Parser<Expression> cond = ExpressionParser.condition(expr, subQuery); Parser<Relation> relation = query(expr, cond, subQuery.or(TABLE)); conditionRef.set(cond); relationRef.set(relation); return relation; }
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<Expression> logical(Parser<Expression> expr) { Parser.Reference<Expression> ref = Parser.newReference(); Parser<Expression> parser = new OperatorTable<Expression>() .prefix(unary("not", Op.NOT), 30) .infixl(binary("and", Op.AND), 20) .infixl(binary("or", Op.OR), 10) .build(paren(ref.lazy()).or(expr)).label("logical expression"); ref.set(parser); return parser; }
static Parser<Relation> join(Parser<Relation> rel, Parser<Expression> cond) { Parser.Reference<Relation> ref = Parser.newReference(); Parser<Relation> lazy = ref.lazy(); Parser<Relation> atom = aliasable(ExpressionParser.paren(lazy).or(rel)); // Cannot use regular infix operator because of the "join ... on ..." syntax. Parser<UnaryOperator<Relation>> crossJoin = TerminalParser.phrase("cross join").next(atom).map(r -> l -> new CrossJoinRelation(l, r)); Parser<Relation> parser = atom.postfix(Parsers.or( joinOn(INNER_JOIN, lazy, cond), joinOn(LEFT_JOIN, lazy, cond), joinOn(RIGHT_JOIN, lazy, cond), joinOn(FULL_JOIN, lazy, cond), crossJoin)); ref.set(parser); return parser; }
static Parser<Integer> parser() { Parser.Reference<Integer> ref = Parser.newReference(); Parser<Integer> term = ref.lazy().between(isChar('('), isChar(')')).or(NUMBER); Parser<Integer> parser = new OperatorTable<Integer>() .prefix(op('-', NEG), 100) .infixl(op('+', PLUS), 10) .infixl(op('-', MINUS), 10) .infixl(op('*', MUL), 20) .infixl(op('/', DIV), 20) .infixl(op('%', MOD), 20) .build(term); ref.set(parser); return parser; } }