246 lines
6.3 KiB
Java
246 lines
6.3 KiB
Java
package net.minecraft.util.parsing.packrat;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
public interface Term<S> {
|
|
boolean parse(ParseState<S> parseState, Scope scope, Control control);
|
|
|
|
static <S, T> Term<S> marker(Atom<T> name, T value) {
|
|
return new Term.Marker<>(name, value);
|
|
}
|
|
|
|
@SafeVarargs
|
|
static <S> Term<S> sequence(Term<S>... elements) {
|
|
return new Term.Sequence<>(elements);
|
|
}
|
|
|
|
@SafeVarargs
|
|
static <S> Term<S> alternative(Term<S>... elements) {
|
|
return new Term.Alternative<>(elements);
|
|
}
|
|
|
|
static <S> Term<S> optional(Term<S> term) {
|
|
return new Term.Maybe<>(term);
|
|
}
|
|
|
|
static <S, T> Term<S> repeated(NamedRule<S, T> element, Atom<List<T>> listName) {
|
|
return repeated(element, listName, 0);
|
|
}
|
|
|
|
static <S, T> Term<S> repeated(NamedRule<S, T> element, Atom<List<T>> listName, int minRepetitions) {
|
|
return new Term.Repeated<>(element, listName, minRepetitions);
|
|
}
|
|
|
|
static <S, T> Term<S> repeatedWithTrailingSeparator(NamedRule<S, T> element, Atom<List<T>> listName, Term<S> seperator) {
|
|
return repeatedWithTrailingSeparator(element, listName, seperator, 0);
|
|
}
|
|
|
|
static <S, T> Term<S> repeatedWithTrailingSeparator(NamedRule<S, T> element, Atom<List<T>> listName, Term<S> seperator, int minRepetitions) {
|
|
return new Term.RepeatedWithSeparator<>(element, listName, seperator, minRepetitions, true);
|
|
}
|
|
|
|
static <S, T> Term<S> repeatedWithoutTrailingSeparator(NamedRule<S, T> element, Atom<List<T>> listName, Term<S> seperator) {
|
|
return repeatedWithoutTrailingSeparator(element, listName, seperator, 0);
|
|
}
|
|
|
|
static <S, T> Term<S> repeatedWithoutTrailingSeparator(NamedRule<S, T> element, Atom<List<T>> listName, Term<S> seperator, int minRepetitions) {
|
|
return new Term.RepeatedWithSeparator<>(element, listName, seperator, minRepetitions, false);
|
|
}
|
|
|
|
static <S> Term<S> positiveLookahead(Term<S> term) {
|
|
return new Term.LookAhead<>(term, true);
|
|
}
|
|
|
|
static <S> Term<S> negativeLookahead(Term<S> term) {
|
|
return new Term.LookAhead<>(term, false);
|
|
}
|
|
|
|
static <S> Term<S> cut() {
|
|
return new Term<S>() {
|
|
@Override
|
|
public boolean parse(ParseState<S> parseState, Scope scope, Control control) {
|
|
control.cut();
|
|
return true;
|
|
}
|
|
|
|
public String toString() {
|
|
return "↑";
|
|
}
|
|
};
|
|
}
|
|
|
|
static <S> Term<S> empty() {
|
|
return new Term<S>() {
|
|
@Override
|
|
public boolean parse(ParseState<S> parseState, Scope scope, Control control) {
|
|
return true;
|
|
}
|
|
|
|
public String toString() {
|
|
return "ε";
|
|
}
|
|
};
|
|
}
|
|
|
|
static <S> Term<S> fail(Object reason) {
|
|
return new Term<S>() {
|
|
@Override
|
|
public boolean parse(ParseState<S> parseState, Scope scope, Control control) {
|
|
parseState.errorCollector().store(parseState.mark(), reason);
|
|
return false;
|
|
}
|
|
|
|
public String toString() {
|
|
return "fail";
|
|
}
|
|
};
|
|
}
|
|
|
|
public record Alternative<S>(Term<S>[] elements) implements Term<S> {
|
|
@Override
|
|
public boolean parse(ParseState<S> parseState, Scope scope, Control control) {
|
|
Control control2 = parseState.acquireControl();
|
|
|
|
try {
|
|
int i = parseState.mark();
|
|
scope.splitFrame();
|
|
|
|
for (Term<S> term : this.elements) {
|
|
if (term.parse(parseState, scope, control2)) {
|
|
scope.mergeFrame();
|
|
return true;
|
|
}
|
|
|
|
scope.clearFrameValues();
|
|
parseState.restore(i);
|
|
if (control2.hasCut()) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
scope.popFrame();
|
|
return false;
|
|
} finally {
|
|
parseState.releaseControl();
|
|
}
|
|
}
|
|
}
|
|
|
|
public record LookAhead<S>(Term<S> term, boolean positive) implements Term<S> {
|
|
@Override
|
|
public boolean parse(ParseState<S> parseState, Scope scope, Control control) {
|
|
int i = parseState.mark();
|
|
boolean bl = this.term.parse(parseState.silent(), scope, control);
|
|
parseState.restore(i);
|
|
return this.positive == bl;
|
|
}
|
|
}
|
|
|
|
public record Marker<S, T>(Atom<T> name, T value) implements Term<S> {
|
|
@Override
|
|
public boolean parse(ParseState<S> parseState, Scope scope, Control control) {
|
|
scope.put(this.name, this.value);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public record Maybe<S>(Term<S> term) implements Term<S> {
|
|
@Override
|
|
public boolean parse(ParseState<S> parseState, Scope scope, Control control) {
|
|
int i = parseState.mark();
|
|
if (!this.term.parse(parseState, scope, control)) {
|
|
parseState.restore(i);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public record Repeated<S, T>(NamedRule<S, T> element, Atom<List<T>> listName, int minRepetitions) implements Term<S> {
|
|
@Override
|
|
public boolean parse(ParseState<S> parseState, Scope scope, Control control) {
|
|
int i = parseState.mark();
|
|
List<T> list = new ArrayList(this.minRepetitions);
|
|
|
|
while (true) {
|
|
int j = parseState.mark();
|
|
T object = parseState.parse(this.element);
|
|
if (object == null) {
|
|
parseState.restore(j);
|
|
if (list.size() < this.minRepetitions) {
|
|
parseState.restore(i);
|
|
return false;
|
|
} else {
|
|
scope.put(this.listName, list);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
list.add(object);
|
|
}
|
|
}
|
|
}
|
|
|
|
public record RepeatedWithSeparator<S, T>(
|
|
NamedRule<S, T> element, Atom<List<T>> listName, Term<S> separator, int minRepetitions, boolean allowTrailingSeparator
|
|
) implements Term<S> {
|
|
@Override
|
|
public boolean parse(ParseState<S> parseState, Scope scope, Control control) {
|
|
int i = parseState.mark();
|
|
List<T> list = new ArrayList(this.minRepetitions);
|
|
boolean bl = true;
|
|
|
|
while (true) {
|
|
int j = parseState.mark();
|
|
if (!bl && !this.separator.parse(parseState, scope, control)) {
|
|
parseState.restore(j);
|
|
break;
|
|
}
|
|
|
|
int k = parseState.mark();
|
|
T object = parseState.parse(this.element);
|
|
if (object == null) {
|
|
if (bl) {
|
|
parseState.restore(k);
|
|
} else {
|
|
if (!this.allowTrailingSeparator) {
|
|
parseState.restore(i);
|
|
return false;
|
|
}
|
|
|
|
parseState.restore(k);
|
|
}
|
|
break;
|
|
}
|
|
|
|
list.add(object);
|
|
bl = false;
|
|
}
|
|
|
|
if (list.size() < this.minRepetitions) {
|
|
parseState.restore(i);
|
|
return false;
|
|
} else {
|
|
scope.put(this.listName, list);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
public record Sequence<S>(Term<S>[] elements) implements Term<S> {
|
|
@Override
|
|
public boolean parse(ParseState<S> parseState, Scope scope, Control control) {
|
|
int i = parseState.mark();
|
|
|
|
for (Term<S> term : this.elements) {
|
|
if (!term.parse(parseState, scope, control)) {
|
|
parseState.restore(i);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
}
|