package net.minecraft.util.parsing.packrat; import java.util.HashMap; import java.util.Map; import java.util.Optional; import org.jetbrains.annotations.Nullable; public abstract class ParseState { private final Map, ParseState.CacheEntry> ruleCache = new HashMap(); private final Dictionary dictionary; private final ErrorCollector errorCollector; protected ParseState(Dictionary dictionary, ErrorCollector errorCollector) { this.dictionary = dictionary; this.errorCollector = errorCollector; } public ErrorCollector errorCollector() { return this.errorCollector; } public Optional parseTopRule(Atom atom) { Optional optional = this.parse(atom); if (optional.isPresent()) { this.errorCollector.finish(this.mark()); } return optional; } public Optional parse(Atom atom) { ParseState.CacheKey cacheKey = new ParseState.CacheKey<>(atom, this.mark()); ParseState.CacheEntry cacheEntry = this.lookupInCache(cacheKey); if (cacheEntry != null) { this.restore(cacheEntry.mark()); return cacheEntry.value; } else { Rule rule = this.dictionary.get(atom); if (rule == null) { throw new IllegalStateException("No symbol " + atom); } else { Optional optional = rule.parse(this); this.storeInCache(cacheKey, optional); return optional; } } } @Nullable private ParseState.CacheEntry lookupInCache(ParseState.CacheKey key) { return (ParseState.CacheEntry)this.ruleCache.get(key); } private void storeInCache(ParseState.CacheKey key, Optional value) { this.ruleCache.put(key, new ParseState.CacheEntry(value, this.mark())); } public abstract S input(); public abstract int mark(); public abstract void restore(int cursor); record CacheEntry(Optional value, int mark) { } record CacheKey(Atom name, int mark) { } }