/** * A {@link Parser} that fails if {@code this} succeeds. Any input consumption is undone. */ public final Parser<?> not() { return not(toString()); }
/** * A {@link Parser} that succeeds if {@code this} succeeds and the pattern recognized by {@code parser} isn't * following. */ public final Parser<T> notFollowedBy(Parser<?> parser) { return followedBy(parser.not()); }
public static Parser<?> term(String name) { if (name.equals(">>")) { // manually do the exclusion so that ">>>" never gets interpreted partially as ">>", // even if it can be interpreted as ">" followed by ">>" or three ">"s. return adjacent(">>>").not().next(adjacent(">>")); } if (name.equals("<<") || name.equals(">>>")) { return adjacent(name); } return TERMS.token(name); }
/** * 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} 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()); }