com.github.leeonky.interpreter.Parser Maven / Gradle / Ivy
package com.github.leeonky.interpreter;
import java.util.Optional;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;
import java.util.stream.Stream;
import static java.util.Optional.empty;
public interface Parser, PA extends Parser
,
MA extends Parser.Mandatory
, T> extends MapAble {
@Override
default PA map(UnaryOperator mapper) {
return castParser(procedure -> parse(procedure).map(mapper));
}
@SuppressWarnings("unchecked")
static , PA extends Parser
,
MA extends Parser.Mandatory
, T> PA oneOf(PA... parsers) {
return parsers[0].castParser(procedure -> Stream.of(parsers).map(parser -> parser.parse(procedure)).
filter(Optional::isPresent).findFirst().orElse(empty()));
}
static , P extends Procedure, N, ?, ?>> ClauseParser lazyClause(
Supplier> parser) {
return procedure -> parser.get().parse(procedure);
}
static , P extends Procedure, N, ?, ?>> NodeParser lazyNode(
Supplier> parser) {
return procedure -> parser.get().parse(procedure);
}
Optional parse(P procedure);
default PA castParser(Parser parser) {
throw new IllegalStateException();
}
default MA castMandatory(Parser.Mandatory
mandatory) {
throw new IllegalStateException();
}
default MA or(MA mandatory) {
return castMandatory(procedure -> parse(procedure).orElseGet(() -> mandatory.parse(procedure)));
}
default MA mandatory(String message) {
return castMandatory(procedure -> parse(procedure)
.orElseThrow(() -> procedure.getSourceCode().syntaxError(message, 0)));
}
default PA notStartWith(Notation, ?, ?, P, ?> notation) {
return castParser(procedure -> {
if (procedure.getSourceCode().startsWith(notation))
return empty();
return parse(procedure);
});
}
interface Mandatory
, PA extends Parser
,
MA extends Mandatory
, T> extends MapAble {
default PA castParser(Parser parser) {
throw new IllegalStateException();
}
default MA castMandatory(Parser.Mandatory
mandatory) {
throw new IllegalStateException();
}
T parse(P procedure);
@Override
default MA map(UnaryOperator mapper) {
return castMandatory(procedure -> mapper.apply(parse(procedure)));
}
}
}