com.github.leeonky.interpreter.Syntax Maven / Gradle / Ivy
package com.github.leeonky.interpreter;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.BiFunction;
import java.util.function.Function;
public abstract class Syntax, P extends Procedure, N, ?, ?>, PA extends Parser,
MA extends Parser.Mandatory
, T, R, A> {
protected final BiFunction
, A> parser;
private Token token;
protected Syntax(BiFunction
, A> parser) {
this.parser = parser;
}
public static , P extends Procedure, N, ?, ?>, PA extends Parser,
MA extends Parser.Mandatory
, T> Syntax, T> single(PA parser) {
return new DefaultSyntax, T>((procedure, syntax) -> {
Optional optional = parser.parse(procedure);
if (optional.isPresent()) {
syntax.isClose(procedure);
syntax.close(procedure);
}
return optional.orElse(null);
}) {
@Override
protected NodeParser parse(Syntax,
T> syntax, Function factory) {
return (P procedure) -> Optional.ofNullable(parser.apply(procedure, syntax)).map(factory);
}
};
}
public static , P extends Procedure, N, ?, ?>, PA extends Parser,
MA extends Parser.Mandatory
, T> Syntax, T> single(MA parser) {
return new DefaultSyntax, T>((procedure, syntax) -> {
T t = parser.parse(procedure);
syntax.isClose(procedure);
syntax.close(procedure);
return t;
}) {
@Override
protected NodeParser.Mandatory parse(Syntax, T> syntax, Function factory) {
return (P procedure) -> factory.apply(parser.apply(procedure, syntax));
}
};
}
public static , P extends Procedure, N, ?, ?>, PA extends Parser,
MA extends Parser.Mandatory
, T> Syntax, List> many(MA mandatory) {
return new DefaultSyntax<>((procedure, syntax) -> procedure.withColumn(() -> new ArrayList() {{
while (!syntax.isClose(procedure)) {
add(mandatory.parse(procedure));
procedure.incrementColumn();
if (!syntax.isSplitter(procedure)) {
syntax.isClose(procedure);
break;
}
}
syntax.close(procedure);
}}));
}
public static , P extends Procedure, N, ?, ?>, PA extends Parser,
MA extends Parser.Mandatory
, T> Syntax, List> many(PA parser) {
return new DefaultSyntax<>((procedure, syntax) -> procedure.withColumn(() -> new ArrayList() {{
while (!syntax.isClose(procedure)) {
Optional optional = parser.parse(procedure);
if (!optional.isPresent())
break;
add(optional.get());
procedure.incrementColumn();
if (!syntax.isSplitter(procedure)) {
syntax.isClose(procedure);
break;
}
}
syntax.close(procedure);
}}));
}
protected abstract boolean isClose(P procedure);
protected abstract void close(P procedure);
protected abstract boolean isSplitter(P procedure);
@SuppressWarnings("unchecked")
protected R parse(Syntax syntax, Function factory) {
return (R) (NodeParser.Mandatory) procedure -> factory.apply(parser.apply(procedure, syntax));
}
public Syntax and(Function,
Syntax> rule) {
return rule.apply(this);
}
public R as(Function factory) {
return parse(this, factory);
}
@SuppressWarnings("unchecked")
public R as() {
return parse(this, a -> (N) a);
}
protected Token getToken() {
return token;
}
protected void setToken(Token token) {
this.token = token;
}
public static class DefaultSyntax, P extends Procedure, N, ?, ?>,
PA extends Parser, MA extends Parser.Mandatory
, T, R, A>
extends Syntax {
public DefaultSyntax(BiFunction, A> parser) {
super(parser);
}
@Override
protected boolean isClose(P procedure) {
return false;
}
@Override
protected void close(P procedure) {
}
@Override
protected boolean isSplitter(P procedure) {
return true;
}
}
public static class CompositeSyntax, P extends Procedure, N, ?, ?>,
PA extends Parser, MA extends Parser.Mandatory
, T, R, A>
extends Syntax {
private final Syntax syntax;
public CompositeSyntax(Syntax syntax) {
super(syntax.parser);
this.syntax = syntax;
}
protected String quote(String label) {
return label.contains("`") ? "'" + label + "'" : "`" + label + "`";
}
@Override
protected boolean isClose(P procedure) {
return syntax.isClose(procedure);
}
@Override
protected void close(P procedure) {
syntax.close(procedure);
}
@Override
protected boolean isSplitter(P procedure) {
return syntax.isSplitter(procedure);
}
@Override
protected R parse(Syntax syntax, Function factory) {
return this.syntax.parse(syntax, factory);
}
@Override
protected Token getToken() {
return syntax.getToken();
}
@Override
protected void setToken(Token token) {
syntax.setToken(token);
}
}
}