package net.minecraft.util.parsing.packrat; import java.util.ArrayList; import java.util.List; public interface Term { boolean parse(ParseState parseState, Scope scope, Control control); static Term marker(Atom name, T value) { return new Term.Marker<>(name, value); } @SafeVarargs static Term sequence(Term... elements) { return new Term.Sequence<>(elements); } @SafeVarargs static Term alternative(Term... elements) { return new Term.Alternative<>(elements); } static Term optional(Term term) { return new Term.Maybe<>(term); } static Term repeated(NamedRule element, Atom> listName) { return repeated(element, listName, 0); } static Term repeated(NamedRule element, Atom> listName, int minRepetitions) { return new Term.Repeated<>(element, listName, minRepetitions); } static Term repeatedWithTrailingSeparator(NamedRule element, Atom> listName, Term seperator) { return repeatedWithTrailingSeparator(element, listName, seperator, 0); } static Term repeatedWithTrailingSeparator(NamedRule element, Atom> listName, Term seperator, int minRepetitions) { return new Term.RepeatedWithSeparator<>(element, listName, seperator, minRepetitions, true); } static Term repeatedWithoutTrailingSeparator(NamedRule element, Atom> listName, Term seperator) { return repeatedWithoutTrailingSeparator(element, listName, seperator, 0); } static Term repeatedWithoutTrailingSeparator(NamedRule element, Atom> listName, Term seperator, int minRepetitions) { return new Term.RepeatedWithSeparator<>(element, listName, seperator, minRepetitions, false); } static Term positiveLookahead(Term term) { return new Term.LookAhead<>(term, true); } static Term negativeLookahead(Term term) { return new Term.LookAhead<>(term, false); } static Term cut() { return new Term() { @Override public boolean parse(ParseState parseState, Scope scope, Control control) { control.cut(); return true; } public String toString() { return "↑"; } }; } static Term empty() { return new Term() { @Override public boolean parse(ParseState parseState, Scope scope, Control control) { return true; } public String toString() { return "ε"; } }; } static Term fail(Object reason) { return new Term() { @Override public boolean parse(ParseState parseState, Scope scope, Control control) { parseState.errorCollector().store(parseState.mark(), reason); return false; } public String toString() { return "fail"; } }; } public record Alternative(Term[] elements) implements Term { @Override public boolean parse(ParseState parseState, Scope scope, Control control) { Control control2 = parseState.acquireControl(); try { int i = parseState.mark(); scope.splitFrame(); for (Term 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(Term term, boolean positive) implements Term { @Override public boolean parse(ParseState 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(Atom name, T value) implements Term { @Override public boolean parse(ParseState parseState, Scope scope, Control control) { scope.put(this.name, this.value); return true; } } public record Maybe(Term term) implements Term { @Override public boolean parse(ParseState parseState, Scope scope, Control control) { int i = parseState.mark(); if (!this.term.parse(parseState, scope, control)) { parseState.restore(i); } return true; } } public record Repeated(NamedRule element, Atom> listName, int minRepetitions) implements Term { @Override public boolean parse(ParseState parseState, Scope scope, Control control) { int i = parseState.mark(); List 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( NamedRule element, Atom> listName, Term separator, int minRepetitions, boolean allowTrailingSeparator ) implements Term { @Override public boolean parse(ParseState parseState, Scope scope, Control control) { int i = parseState.mark(); List 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(Term[] elements) implements Term { @Override public boolean parse(ParseState parseState, Scope scope, Control control) { int i = parseState.mark(); for (Term term : this.elements) { if (!term.parse(parseState, scope, control)) { parseState.restore(i); return false; } } return true; } } }