package net.minecraft.util.parsing.packrat; import java.util.IdentityHashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.function.Supplier; import org.jetbrains.annotations.Nullable; public class Dictionary { private final Map, Dictionary.Entry> terms = new IdentityHashMap(); public NamedRule put(Atom name, Rule rule) { Dictionary.Entry entry = (Dictionary.Entry)this.terms.computeIfAbsent(name, Dictionary.Entry::new); if (entry.value != null) { throw new IllegalArgumentException("Trying to override rule: " + name); } else { entry.value = rule; return entry; } } public NamedRule putComplex(Atom name, Term term, Rule.RuleAction ruleAction) { return this.put(name, Rule.fromTerm(term, ruleAction)); } public NamedRule put(Atom name, Term term, Rule.SimpleRuleAction ruleAction) { return this.put(name, Rule.fromTerm(term, ruleAction)); } public void checkAllBound() { List> list = this.terms.entrySet().stream().filter(entry -> entry.getValue() == null).map(java.util.Map.Entry::getKey).toList(); if (!list.isEmpty()) { throw new IllegalStateException("Unbound names: " + list); } } public NamedRule getOrThrow(Atom name) { return (NamedRule)Objects.requireNonNull((Dictionary.Entry)this.terms.get(name), () -> "No rule called " + name); } public NamedRule forward(Atom name) { return this.getOrCreateEntry(name); } private Dictionary.Entry getOrCreateEntry(Atom name) { return (Dictionary.Entry)this.terms.computeIfAbsent(name, Dictionary.Entry::new); } public Term named(Atom name) { return new Dictionary.Reference<>(this.getOrCreateEntry(name), name); } public Term namedWithAlias(Atom name, Atom alias) { return new Dictionary.Reference<>(this.getOrCreateEntry(name), alias); } static class Entry implements NamedRule, Supplier { private final Atom name; @Nullable Rule value; private Entry(Atom name) { this.name = name; } @Override public Atom name() { return this.name; } @Override public Rule value() { return (Rule)Objects.requireNonNull(this.value, this); } public String get() { return "Unbound rule " + this.name; } } record Reference(Dictionary.Entry ruleToParse, Atom nameToStore) implements Term { @Override public boolean parse(ParseState parseState, Scope scope, Control control) { T object = parseState.parse(this.ruleToParse); if (object == null) { return false; } else { scope.put(this.nameToStore, object); return true; } } } }