fj.parser.Parser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of functionaljava Show documentation
Show all versions of functionaljava Show documentation
Functional Java is an open source library that supports closures for the Java programming language
package fj.parser;
import fj.*;
import static fj.P.p;
import static fj.Unit.unit;
import fj.data.List;
import static fj.data.List.cons_;
import fj.data.Stream;
import fj.data.Validation;
import static fj.data.Validation.success;
import static fj.parser.Result.result;
/**
* A parser is a function that takes some input (I) and produces either an error (E) or a parse result (A) and the
* remainder of the input.
*
* @version %build.number%
*/
public final class Parser {
private final F>> f;
private Parser(final F>> f) {
this.f = f;
}
/**
* Parses the input to produce a result or error.
*
* @param i The input to parse.
* @return A parse result with the remaining input or an error.
*/
public Validation> parse(final I i) {
return f.f(i);
}
/**
* Maps the parse input type through an invariant functor.
*
* @param f The function to covariant map.
* @param g The function to contra-variant map.
* @return A parser with the new input type.
*/
public Parser xmap(final F f, final F g) {
return parser(z -> parse(g.f(z)).map(r -> r.mapRest(f)));
}
/**
* Maps the given result type across this parser.
*
* @param f The function to map.
* @return A parser with the new result type.
*/
public Parser map(final F f) {
return parser(i -> parse(i).map(r -> r.mapValue(f)));
}
/**
* Returns a parser that fails with the given error if the result value does not meet the given predicate.
*
* @param f The predicate to filter on.
* @param e The error to in the event that the predicate is not met.
* @return A parser that fails with the given error if the result value does not meet the given predicate.
*/
public Parser filter(final F f, final E e) {
return parser(i -> parse(i).bind(r -> {
final A v = r.value();
return f.f(v) ?
Validation.>success(result(r.rest(), v)) :
Validation.>fail(e);
}));
}
/**
* Binds the given function across the parser with a final join.
*
* @param f The function to apply to the element of this parser.
* @return A new parser after performing the map, then final join.
*/
public Parser bind(final F> f) {
return parser(i -> parse(i).bind(r -> f.f(r.value()).parse(r.rest())));
}
/**
* Binds the given function across the parsers with a final join.
*
* @param f The function to apply to the element of the parsers.
* @param pb A given parser to bind the given function with.
* @return A new parser after performing the map, then final join.
*/
public Parser bind(final Parser pb, final F> f) {
return pb.apply(map(f));
}
/**
* Binds the given function across the parsers with a final join.
*
* @param f The function to apply to the element of the parsers.
* @param pb A given parser to bind the given function with.
* @param pc A given parser to bind the given function with.
* @return A new parser after performing the map, then final join.
*/
public Parser bind(final Parser pb, final Parser pc,
final F>> f) {
return pc.apply(bind(pb, f));
}
/**
* Binds the given function across the parsers with a final join.
*
* @param f The function to apply to the element of the parsers.
* @param pb A given parser to bind the given function with.
* @param pc A given parser to bind the given function with.
* @param pd A given parser to bind the given function with.
* @return A new parser after performing the map, then final join.
*/
public Parser bind(final Parser pb, final Parser pc,
final Parser pd, final F>>> f) {
return pd.apply(bind(pb, pc, f));
}
/**
* Binds the given function across the parsers with a final join.
*
* @param f The function to apply to the element of the parsers.
* @param pb A given parser to bind the given function with.
* @param pc A given parser to bind the given function with.
* @param pd A given parser to bind the given function with.
* @param pe A given parser to bind the given function with.
* @return A new parser after performing the map, then final join.
*/
public Parser bind(final Parser pb, final Parser pc,
final Parser pd, final Parser pe,
final F>>>> f) {
return pe.apply(bind(pb, pc, pd, f));
}
/**
* Binds the given function across the parsers with a final join.
*
* @param f The function to apply to the element of the parsers.
* @param pb A given parser to bind the given function with.
* @param pc A given parser to bind the given function with.
* @param pd A given parser to bind the given function with.
* @param pe A given parser to bind the given function with.
* @param pf A given parser to bind the given function with.
* @return A new parser after performing the map, then final join.
*/
public Parser bind(final Parser pb, final Parser pc,
final Parser pd, final Parser pe,
final Parser pf,
final F>>>>> f) {
return pf.apply(bind(pb, pc, pd, pe, f));
}
/**
* Binds the given function across the parsers with a final join.
*
* @param f The function to apply to the element of the parsers.
* @param pb A given parser to bind the given function with.
* @param pc A given parser to bind the given function with.
* @param pd A given parser to bind the given function with.
* @param pe A given parser to bind the given function with.
* @param pf A given parser to bind the given function with.
* @param pg A given parser to bind the given function with.
* @return A new parser after performing the map, then final join.
*/
public Parser bind(final Parser pb, final Parser pc,
final Parser pd, final Parser pe,
final Parser pf, final Parser pg,
final F>>>>>> f) {
return pg.apply(bind(pb, pc, pd, pe, pf, f));
}
/**
* Binds the given function across the parsers with a final join.
*
* @param f The function to apply to the element of the parsers.
* @param pb A given parser to bind the given function with.
* @param pc A given parser to bind the given function with.
* @param pd A given parser to bind the given function with.
* @param pe A given parser to bind the given function with.
* @param pf A given parser to bind the given function with.
* @param pg A given parser to bind the given function with.
* @param ph A given parser to bind the given function with.
* @return A new parser after performing the map, then final join.
*/
public Parser bind(final Parser pb, final Parser pc,
final Parser pd, final Parser pe,
final Parser pf, final Parser pg,
final Parser ph,
final F>>>>>>> f) {
return ph.apply(bind(pb, pc, pd, pe, pf, pg, f));
}
/**
* Binds anonymously, ignoring the result value.
*
* @param p The parser to bind with.
* @return A parser after binding anonymously.
*/
public Parser sequence(final Parser p) {
return bind(a -> p);
}
/**
* Performs function application within a parser.
*
* @param p The parser returning a function value.
* @return A new parser after function application.
*/
public Parser apply(final Parser, E> p) {
return p.bind((F, Parser>) f1 -> map(f1));
}
/**
* Returns a parser that tries this parser and if it fails, then tries the given parser.
*
* @param alt The parser to try if this parser fails.
* @return A parser that tries this parser and if it fails, then tries the given parser.
*/
public Parser or(final F0> alt) {
return parser(i -> parse(i).f().sequence(alt.f().parse(i)));
}
/**
* Returns a parser that tries this parser and if it fails, then tries the given parser.
*
* @param alt The parser to try if this parser fails.
* @return A parser that tries this parser and if it fails, then tries the given parser.
*/
public Parser or(final Parser alt) {
return or(p(alt));
}
/**
* Returns a parser that tries this parser and if it fails, then tries the given parser. If both parsers fail, then
* append their errors with the given semigroup.
*
* @param alt The parser to try if this parser fails.
* @param s The semigroup to append error messages if both parsers fail.
* @return A parser that tries this parser and if it fails, then tries the given parser.
*/
public Parser or(final F0> alt, final Semigroup s) {
return parser(i -> parse(i).f().bind(e -> alt.f().parse(i).f().map(s.sum(e))));
}
/**
* Returns a parser that tries this parser and if it fails, then tries the given parser. If both parsers fail, then
* append their errors with the given semigroup.
*
* @param alt The parser to try if this parser fails.
* @param s The semigroup to append error messages if both parsers fail.
* @return A parser that tries this parser and if it fails, then tries the given parser.
*/
public Parser or(final Parser alt, final Semigroup s) {
return or(p(alt), s);
}
/**
* Returns a parser that negates this parser. If this parser succeeds, then the returned parser fails and vice versa.
*
* @param e The error message to fail with if this parser succeeds.
* @return A parser that negates this parser.
*/
public Parser not(final F0 e) {
return parser(i -> parse(i).isFail() ?
Validation.>success(result(i, unit())) :
Validation.>fail(e.f()));
}
/**
* Returns a parser that negates this parser. If this parser succeeds, then the returned parser fails and vice versa.
*
* @param e The error message to fail with if this parser succeeds.
* @return A parser that negates this parser.
*/
public Parser not(final E e) {
return not(p(e));
}
/**
* Returns a parser that repeats application of this parser zero or many times.
*
* @return A parser that repeats application of this parser zero or many times.
*/
public Parser, E> repeat() {
return repeat1().or(() -> value(Stream.nil()));
}
/**
* Returns a parser that repeats application of this parser one or many times.
*
* @return A parser that repeats application of this parser one or many times.
*/
public Parser, E> repeat1() {
return bind(a -> repeat().map(as -> as.cons(a)));
}
/**
* Maps the given function across this parser's error.
*
* @param f The function to map this parser's error with.
* @return A new parser with a new error type.
*/
public Parser mapError(final F f) {
return parser(i -> Parser.this.f.f(i).f().map(f));
}
/**
* Returns a parser that computes using the given function.
*
* @param f The function to construct the parser with.
* @return A parser that computes using the given function.
*/
public static Parser parser(final F>> f) {
return new Parser<>(f);
}
/**
* Constructs a parser that always returns the given value. The unital for a parser.
*
* @param a The value to consistently return from a parser.
* @return A parser that always returns the given value.
*/
public static Parser value(final A a) {
return parser(i -> success(result(i, a)));
}
/**
* Returns a parser that always fails with the given error.
*
* @param e The error to fail with.
* @return A parser that always fails with the given error.
*/
public static Parser fail(final E e) {
return parser(i -> Validation.fail(e));
}
/**
* Sequence the list of parsers through {@link #bind}.
*
* @param ps The parsers to sequence.
* @return A parser after sequencing.
*/
public static Parser, E> sequence(final List> ps) {
return ps.isEmpty() ?
Parser., E>value(List.nil()) :
ps.head().bind(a -> sequence(ps.tail()).map(cons_(a)));
}
/**
* Parsers that accept {@link Stream} input.
*/
public static final class StreamParser {
private StreamParser() {
}
/**
* Returns a parser that produces an element from the stream if it is available and fails otherwise.
*
* @param e The error to fail with if no element is available.
* @return A parser that produces an element from the stream if it is available and fails otherwise.
*/
public static Parser, I, E> element(final F0 e) {
return parser(is -> is.isEmpty() ?
Validation., I>>fail(e.f()) :
Validation., I>>success(result(is.tail()._1(), is.head())));
}
/**
* Returns a parser that produces an element from the stream if it is available and fails otherwise.
*
* @param e The error to fail with if no element is available.
* @return A parser that produces an element from the stream if it is available and fails otherwise.
*/
public static Parser, I, E> element(final E e) {
return element(p(e));
}
/**
* Returns a parser that produces an element from the stream that satisfies the given predicate, or fails.
*
* @param missing The error if no element is available.
* @param sat The error if the element does not satisfy the predicate.
* @param f The predicate that the element should satisfy.
* @return A parser that produces an element from the stream that satisfies the given predicate, or fails.
*/
public static Parser, I, E> satisfy(final F0 missing, final F sat,
final F f) {
return StreamParser.element(missing).bind(x -> f.f(x) ?
Parser., I, E>value(x) :
Parser., I, E>fail(sat.f(x)));
}
/**
* Returns a parser that produces an element from the stream that satisfies the given predicate, or fails.
*
* @param missing The error if no element is available.
* @param sat The error if the element does not satisfy the predicate.
* @param f The predicate that the element should satisfy.
* @return A parser that produces an element from the stream that satisfies the given predicate, or fails.
*/
public static Parser, I, E> satisfy(final E missing, final F sat, final F f) {
return satisfy(p(missing), sat, f);
}
}
/**
* Parsers that accept {@link Stream Stream<Character>} input.
*/
public static final class CharsParser {
private CharsParser() {
}
/**
* Returns a parser that produces a character if one is available or fails with the given error.
*
* @param e The error to fail with if a character is unavailable.
* @return A parser that produces a character if one is available or fails with the given error.
*/
public static Parser, Character, E> character(final F0 e) {
return StreamParser.element(e);
}
/**
* Returns a parser that produces a character if one is available or fails with the given error.
*
* @param e The error to fail with if a character is unavailable.
* @return A parser that produces a character if one is available or fails with the given error.
*/
public static Parser, Character, E> character(final E e) {
return character(p(e));
}
/**
* Returns a parser that produces the given character or fails otherwise.
*
* @param missing The error if no character is available.
* @param sat The error if the produced character is not the one given.
* @param c The character to produce in the parser.
* @return A parser that produces the given character or fails otherwise.
*/
public static Parser, Character, E> character(final F0 missing, final F sat,
final char c) {
return StreamParser.satisfy(missing, sat, x -> x == c);
}
/**
* Returns a parser that produces the given character or fails otherwise.
*
* @param missing The error if no character is available.
* @param sat The error if the produced character is not the one given.
* @param c The character to produce in the parser.
* @return A parser that produces the given character or fails otherwise.
*/
public static Parser, Character, E> character(final E missing, final F sat,
final char c) {
return character(p(missing), sat, c);
}
/**
* Returns a parser that produces the given number of characters, or fails with the given error.
*
* @param missing The error if the given number of characters is unavailable.
* @param n The number of characters to produce in the parse result.
* @return A parser that produces the given number of characters, or fails with the given error.
*/
public static Parser, Stream, E> characters(final F0 missing, final int n) {
return n <= 0 ?
Parser., Stream, E>value(Stream.nil()) :
character(missing).bind(characters(missing, n - 1), Stream.cons_());
}
/**
* Returns a parser that produces the given number of characters, or fails with the given error.
*
* @param missing The error if the given number of characters is unavailable.
* @param n The number of characters to produce in the parse result.
* @return A parser that produces the given number of characters, or fails with the given error.
*/
public static Parser, Stream, E> characters(final E missing, final int n) {
return characters(p(missing), n);
}
/**
* Returns a parser that produces the given stream of characters or fails otherwise.
*
* @param missing The error if the producing stream could not supply more characters.
* @param sat The error if a character was produced that is not the given stream of characters.
* @param cs The stream of characters to produce.
* @return A parser that produces the given stream of characters or fails otherwise.
*/
public static Parser, Stream, E> characters(final F0 missing,
final F sat,
final Stream cs) {
return cs.isEmpty() ?
Parser., Stream, E>value(Stream.nil()) :
character(missing, sat, cs.head()).bind(characters(missing, sat, cs.tail()._1()), Stream.cons_());
}
/**
* Returns a parser that produces the given stream of characters or fails otherwise.
*
* @param missing The error if the producing stream could not supply more characters.
* @param sat The error if a character was produced that is not the given stream of characters.
* @param cs The stream of characters to produce.
* @return A parser that produces the given stream of characters or fails otherwise.
*/
public static Parser, Stream, E> characters(final E missing,
final F sat,
final Stream cs) {
return characters(p(missing), sat, cs);
}
/**
* Returns a parser that produces the given string or fails otherwise.
*
* @param missing The error if the producing stream could not supply more characters.
* @param sat The error if a character was produced that is not the given string.
* @param s The string to produce.
* @return A parser that produces the given string or fails otherwise.
*/
public static Parser, String, E> string(final F0 missing, final F sat,
final String s) {
return characters(missing, sat, List.fromString(s).toStream()).map(cs -> List.asString(cs.toList()));
}
/**
* Returns a parser that produces the given string or fails otherwise.
*
* @param missing The error if the producing stream could not supply more characters.
* @param sat The error if a character was produced that is not the given string.
* @param s The string to produce.
* @return A parser that produces the given string or fails otherwise.
*/
public static Parser, String, E> string(final E missing, final F sat,
final String s) {
return string(p(missing), sat, s);
}
/**
* Returns a parser that produces a digit (0 to 9).
*
* @param missing The error if there is no character on the stream to produce a digit with.
* @param sat The error if the produced character is not a digit.
* @return A parser that produces a digit (0 to 9).
*/
public static Parser, Digit, E> digit(final F0 missing, final F sat) {
return StreamParser.satisfy(missing, sat, c -> Character.isDigit(c)).map(c1 -> Digit.fromChar(c1).some());
}
/**
* Returns a parser that produces a digit (0 to 9).
*
* @param missing The error if there is no character on the stream to produce a digit with.
* @param sat The error if the produced character is not a digit.
* @return A parser that produces a digit (0 to 9).
*/
public static Parser, Digit, E> digit(final E missing, final F sat) {
return digit(p(missing), sat);
}
/**
* Returns a parser that produces a lower-case character.
*
* @param missing The error if there is no character on the stream to produce a lower-case character with.
* @param sat The error if the produced character is not a lower-case character.
* @return A parser that produces a lower-case character.
* @see Character#isLowerCase(char)
*/
public static Parser, Character, E> lower(final F0 missing, final F sat) {
return StreamParser.satisfy(missing, sat, c -> Character.isLowerCase(c));
}
/**
* Returns a parser that produces a lower-case character.
*
* @param missing The error if there is no character on the stream to produce a lower-case character with.
* @param sat The error if the produced character is not a lower-case character.
* @return A parser that produces a lower-case character.
* @see Character#isLowerCase(char)
*/
public static Parser, Character, E> lower(final E missing, final F sat) {
return lower(p(missing), sat);
}
/**
* Returns a parser that produces a upper-case character.
*
* @param missing The error if there is no character on the stream to produce a upper-case character with.
* @param sat The error if the produced character is not a upper-case character.
* @return A parser that produces a upper-case character.
* @see Character#isUpperCase(char)
*/
public static Parser, Character, E> upper(final F0 missing, final F sat) {
return StreamParser.satisfy(missing, sat, c -> Character.isUpperCase(c));
}
/**
* Returns a parser that produces a upper-case character.
*
* @param missing The error if there is no character on the stream to produce a upper-case character with.
* @param sat The error if the produced character is not a upper-case character.
* @return A parser that produces a upper-case character.
* @see Character#isUpperCase(char)
*/
public static Parser, Character, E> upper(final E missing, final F sat) {
return upper(p(missing), sat);
}
/**
* Returns a parser that produces a defined character.
*
* @param missing The error if there is no character on the stream to produce a defined character with.
* @param sat The error if the produced character is not a defined character.
* @return A parser that produces a defined character.
* @see Character#isDefined(char)
*/
public static Parser, Character, E> defined(final F0 missing, final F sat) {
return StreamParser.satisfy(missing, sat, c -> Character.isDefined(c));
}
/**
* Returns a parser that produces a defined character.
*
* @param missing The error if there is no character on the stream to produce a defined character with.
* @param sat The error if the produced character is not a defined character.
* @return A parser that produces a defined character.
* @see Character#isDefined(char)
*/
public static Parser, Character, E> defined(final E missing, final F sat) {
return defined(p(missing), sat);
}
/**
* Returns a parser that produces a high-surrogate character.
*
* @param missing The error if there is no character on the stream to produce a high-surrogate character with.
* @param sat The error if the produced character is not a high-surrogate character.
* @return A parser that produces a high-surrogate character.
* @see Character#isHighSurrogate(char)
*/
public static Parser, Character, E> highSurrogate(final F0 missing,
final F sat) {
return StreamParser.satisfy(missing, sat, c -> Character.isHighSurrogate(c));
}
/**
* Returns a parser that produces a high-surrogate character.
*
* @param missing The error if there is no character on the stream to produce a high-surrogate character with.
* @param sat The error if the produced character is not a high-surrogate character.
* @return A parser that produces a high-surrogate character.
* @see Character#isHighSurrogate(char)
*/
public static Parser, Character, E> highSurrogate(final E missing,
final F sat) {
return highSurrogate(p(missing), sat);
}
/**
* Returns a parser that produces an identifier-ignorable character.
*
* @param missing The error if there is no character on the stream to produce an identifier-ignorable character with.
* @param sat The error if the produced character is not an identifier-ignorable character.
* @return A parser that produces an identifier-ignorable character.
* @see Character#isIdentifierIgnorable(char)
*/
public static Parser, Character, E> identifierIgnorable(final F0 missing,
final F sat) {
return StreamParser.satisfy(missing, sat, c -> Character.isIdentifierIgnorable(c));
}
/**
* Returns a parser that produces an identifier-ignorable character.
*
* @param missing The error if there is no character on the stream to produce an identifier-ignorable character with.
* @param sat The error if the produced character is not an identifier-ignorable character.
* @return A parser that produces an identifier-ignorable character.
* @see Character#isIdentifierIgnorable(char)
*/
public static Parser, Character, E> identifierIgnorable(final E missing,
final F sat) {
return identifierIgnorable(p(missing), sat);
}
/**
* Returns a parser that produces an ISO control character.
*
* @param missing The error if there is no character on the stream to produce an ISO control character with.
* @param sat The error if the produced character is not an ISO control character.
* @return A parser that produces an ISO control character.
* @see Character#isISOControl(char)
*/
public static Parser, Character, E> isoControl(final F0 missing,
final F sat) {
return StreamParser.satisfy(missing, sat, c -> Character.isISOControl(c));
}
/**
* Returns a parser that produces an ISO control character.
*
* @param missing The error if there is no character on the stream to produce an ISO control character with.
* @param sat The error if the produced character is not an ISO control character.
* @return A parser that produces an ISO control character.
* @see Character#isISOControl(char)
*/
public static Parser, Character, E> isoControl(final E missing, final F sat) {
return isoControl(p(missing), sat);
}
/**
* Returns a parser that produces a Java identifier part character.
*
* @param missing The error if there is no character on the stream to produce a Java identifier part character with.
* @param sat The error if the produced character is not a Java identifier part character.
* @return A parser that produces a Java identifier part character.
* @see Character#isJavaIdentifierPart(char)
*/
public static Parser, Character, E> javaIdentifierPart(final F0 missing,
final F sat) {
return StreamParser.satisfy(missing, sat, c -> Character.isJavaIdentifierPart(c));
}
/**
* Returns a parser that produces a Java identifier part character.
*
* @param missing The error if there is no character on the stream to produce a Java identifier part character with.
* @param sat The error if the produced character is not a Java identifier part character.
* @return A parser that produces a Java identifier part character.
* @see Character#isJavaIdentifierPart(char)
*/
public static Parser, Character, E> javaIdentifierPart(final E missing,
final F sat) {
return javaIdentifierPart(p(missing), sat);
}
/**
* Returns a parser that produces a Java identifier start character.
*
* @param missing The error if there is no character on the stream to produce a Java identifier start character with.
* @param sat The error if the produced character is not a Java identifier start character.
* @return A parser that produces a Java identifier start character.
* @see Character#isJavaIdentifierStart(char)
*/
public static Parser, Character, E> javaIdentifierStart(final F0 missing,
final F sat) {
return StreamParser.satisfy(missing, sat, c -> Character.isJavaIdentifierStart(c));
}
/**
* Returns a parser that produces a Java identifier start character.
*
* @param missing The error if there is no character on the stream to produce a Java identifier start character with.
* @param sat The error if the produced character is not a Java identifier start character.
* @return A parser that produces a Java identifier start character.
* @see Character#isJavaIdentifierStart(char)
*/
public static Parser, Character, E> javaIdentifierStart(final E missing,
final F sat) {
return javaIdentifierStart(p(missing), sat);
}
/**
* Returns a parser that produces an alpha character.
*
* @param missing The error if there is no character on the stream to produce an alpha character with.
* @param sat The error if the produced character is not an alpha character.
* @return A parser that produces an alpha character.
* @see Character#isLetter(char)
*/
public static Parser, Character, E> alpha(final F0 missing, final F sat) {
return StreamParser.satisfy(missing, sat, c -> Character.isLetter(c));
}
/**
* Returns a parser that produces an alpha character.
*
* @param missing The error if there is no character on the stream to produce an alpha character with.
* @param sat The error if the produced character is not an alpha character.
* @return A parser that produces an alpha character.
* @see Character#isLetter(char)
*/
public static Parser, Character, E> alpha(final E missing, final F sat) {
return alpha(p(missing), sat);
}
/**
* Returns a parser that produces an alpha-numeric character.
*
* @param missing The error if there is no character on the stream to produce an alpha-numeric character with.
* @param sat The error if the produced character is not an alpha-numeric character.
* @return A parser that produces an alpha-numeric character.
* @see Character#isLetterOrDigit(char)
*/
public static Parser, Character, E> alphaNum(final F0 missing, final F sat) {
return StreamParser.satisfy(missing, sat, c -> Character.isLetterOrDigit(c));
}
/**
* Returns a parser that produces an alpha-numeric character.
*
* @param missing The error if there is no character on the stream to produce an alpha-numeric character with.
* @param sat The error if the produced character is not an alpha-numeric character.
* @return A parser that produces an alpha-numeric character.
* @see Character#isLetterOrDigit(char)
*/
public static Parser, Character, E> alphaNum(final E missing, final F sat) {
return alphaNum(p(missing), sat);
}
/**
* Returns a parser that produces a low-surrogate character.
*
* @param missing The error if there is no character on the stream to produce a low-surrogate character with.
* @param sat The error if the produced character is not a low-surrogate character.
* @return A parser that produces a low-surrogate character.
* @see Character#isLowSurrogate(char)
*/
public static Parser, Character, E> lowSurrogate(final F0