package com.googlecode.totallylazy.parser; import com.googlecode.totallylazy.Functor; import com.googlecode.totallylazy.Segment; import com.googlecode.totallylazy.functions.Binary; import com.googlecode.totallylazy.functions.Callables; import com.googlecode.totallylazy.functions.Function1; import com.googlecode.totallylazy.Option; import com.googlecode.totallylazy.Pair; import com.googlecode.totallylazy.Sequence; import com.googlecode.totallylazy.Sequences; import com.googlecode.totallylazy.functions.Unary; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.util.List; import static com.googlecode.totallylazy.Segment.constructors.characters; import static com.googlecode.totallylazy.Sequences.foldLeft; import static com.googlecode.totallylazy.Sequences.foldRight; import static com.googlecode.totallylazy.Sequences.join; import static com.googlecode.totallylazy.Strings.UTF8; public interface Parser<A> extends Functor<A> { Result<A> parse(Segment<Character> characters); default Failure<A> fail(Object expected, Object actual) { return Failure.failure(expected, actual); } @Override String toString(); @Override default <B> Parser<B> map(Function1<? super A, ? extends B> callable) { return MappingParser.map(this, callable); } default <B> Parser<B> flatMap(Function1<? super A, ? extends Result<B>> callable) { return FlatMappingParser.flatMap(this, callable); } default <B> Parser<Pair<A, B>> then(Parser<? extends B> parser) { return PairParser.pair(this, parser); } default <B> Parser<B> next(Parser<? extends B> parser) { return then(parser).map(Callables.<B>second()); } default Parser<A> followedBy(Parser<?> parser) { return then(parser).map(Callables.<A>first()); } default Parser<A> between(Parser<?> before, Parser<?> after) { return Parsers.between(before, this, after); } default Parser<A> surroundedBy(Parser<?> parser) { return between(parser, parser); } default Parser<List<A>> sepBy(Parser<?> parser) { return separatedBy(parser); } default Parser<List<A>> sepBy1(Parser<?> parser) { return followedByOption(parser).many(1); } default Parser<List<A>> separatedBy(Parser<?> parser) { return followedByOption(parser).many(); } default Parser<A> followedByOption(Parser<?> parser) {return followedBy(OptionalParser.optional(parser));} default Parser<Sequence<A>> seqBy(Parser<?> parser) { return sequencedBy(parser); } default Parser<Sequence<A>> sequencedBy(Parser<?> parser) { return followedByOption(parser).sequence(); } default Parser<A> or(Parser<? extends A> parser) { return Parsers.or(this, parser); } default Parser<Option<A>> optional() { return OptionalParser.optional(this); } default Result<A> parse(CharSequence value) { return parse(characters(value)); } default Result<A> parse(Reader value) { return parse(characters(value)); } default Result<A> parse(InputStream value) { return parse(characters(new InputStreamReader(value, UTF8))); } default Parser<Void> ignore() { return map(value -> null); } default Parser<List<A>> times(int number) { return Parsers.list(Sequences.repeat(this).take(number)); } default Parser<List<A>> many() { return ManyParser.many(this); } default Parser<Sequence<A>> sequence() { return SequenceParser.sequence(this); } default Parser<A> pretty(String pretty) { return Parsers.pretty(pretty, this); } default Parser<List<A>> many1() { return many(1); } default Parser<List<A>> many(int min) { return times(min).then(many()).map(p -> join(p.first(), p.second()).toList()); } default Parser<A> debug(String name) { return Parsers.debug(name, this); } default <R> Parser<R> returns(R value) { return next(Parsers.returns(value)); } default Parser<A> peek() { return new PeekParser<>(this); } default Parser<A> peek(Parser<A> parser) { return followedBy(parser.peek()); } default Parser<A> infixLeft(Parser<? extends Binary<A>> op){ return then(op.then(this).many()).map(pair -> foldLeft(pair.second(), pair.first(), (a, p) -> p.first().call(a, p.second()))); } default Parser<A> infixRight(Parser<? extends Binary<A>> op){ return then(op).many().then(this).map(pair -> foldRight(pair.first(), pair.second(), (p, a) -> p.second().call(p.first(), a))); } default Parser<A> prefix(Parser<? extends Unary<A>> op){ return op.many().then(this).map(pair -> foldLeft(pair.first(), pair.second(), (a, p) -> p.call(a) )); } }