minecraft-src/net/minecraft/util/parsing/packrat/CachedParseState.java
2025-07-04 03:45:38 +03:00

228 lines
5.6 KiB
Java

package net.minecraft.util.parsing.packrat;
import net.minecraft.Util;
import org.jetbrains.annotations.Nullable;
public abstract class CachedParseState<S> implements ParseState<S> {
private CachedParseState.PositionCache[] positionCache = new CachedParseState.PositionCache[256];
private final ErrorCollector<S> errorCollector;
private final Scope scope = new Scope();
private CachedParseState.SimpleControl[] controlCache = new CachedParseState.SimpleControl[16];
private int nextControlToReturn;
private final CachedParseState<S>.Silent silent = new CachedParseState.Silent();
protected CachedParseState(ErrorCollector<S> errorCollector) {
this.errorCollector = errorCollector;
}
@Override
public Scope scope() {
return this.scope;
}
@Override
public ErrorCollector<S> errorCollector() {
return this.errorCollector;
}
@Nullable
@Override
public <T> T parse(NamedRule<S, T> rule) {
int i = this.mark();
CachedParseState.PositionCache positionCache = this.getCacheForPosition(i);
int j = positionCache.findKeyIndex(rule.name());
if (j != -1) {
CachedParseState.CacheEntry<T> cacheEntry = positionCache.getValue(j);
if (cacheEntry != null) {
if (cacheEntry == CachedParseState.CacheEntry.NEGATIVE) {
return null;
}
this.restore(cacheEntry.markAfterParse);
return cacheEntry.value;
}
} else {
j = positionCache.allocateNewEntry(rule.name());
}
T object = rule.value().parse(this);
CachedParseState.CacheEntry<T> cacheEntry2;
if (object == null) {
cacheEntry2 = CachedParseState.CacheEntry.negativeEntry();
} else {
int k = this.mark();
cacheEntry2 = new CachedParseState.CacheEntry<>(object, k);
}
positionCache.setValue(j, cacheEntry2);
return object;
}
private CachedParseState.PositionCache getCacheForPosition(int position) {
int i = this.positionCache.length;
if (position >= i) {
int j = Util.growByHalf(i, position + 1);
CachedParseState.PositionCache[] positionCaches = new CachedParseState.PositionCache[j];
System.arraycopy(this.positionCache, 0, positionCaches, 0, i);
this.positionCache = positionCaches;
}
CachedParseState.PositionCache positionCache = this.positionCache[position];
if (positionCache == null) {
positionCache = new CachedParseState.PositionCache();
this.positionCache[position] = positionCache;
}
return positionCache;
}
@Override
public Control acquireControl() {
int i = this.controlCache.length;
if (this.nextControlToReturn >= i) {
int j = Util.growByHalf(i, this.nextControlToReturn + 1);
CachedParseState.SimpleControl[] simpleControls = new CachedParseState.SimpleControl[j];
System.arraycopy(this.controlCache, 0, simpleControls, 0, i);
this.controlCache = simpleControls;
}
int j = this.nextControlToReturn++;
CachedParseState.SimpleControl simpleControl = this.controlCache[j];
if (simpleControl == null) {
simpleControl = new CachedParseState.SimpleControl();
this.controlCache[j] = simpleControl;
} else {
simpleControl.reset();
}
return simpleControl;
}
@Override
public void releaseControl() {
this.nextControlToReturn--;
}
@Override
public ParseState<S> silent() {
return this.silent;
}
record CacheEntry<T>(@Nullable T value, int markAfterParse) {
public static final CachedParseState.CacheEntry<?> NEGATIVE = new CachedParseState.CacheEntry(null, -1);
public static <T> CachedParseState.CacheEntry<T> negativeEntry() {
return (CachedParseState.CacheEntry<T>)NEGATIVE;
}
}
static class PositionCache {
public static final int ENTRY_STRIDE = 2;
private static final int NOT_FOUND = -1;
private Object[] atomCache = new Object[16];
private int nextKey;
public int findKeyIndex(Atom<?> atom) {
for (int i = 0; i < this.nextKey; i += 2) {
if (this.atomCache[i] == atom) {
return i;
}
}
return -1;
}
public int allocateNewEntry(Atom<?> entry) {
int i = this.nextKey;
this.nextKey += 2;
int j = i + 1;
int k = this.atomCache.length;
if (j >= k) {
int l = Util.growByHalf(k, j + 1);
Object[] objects = new Object[l];
System.arraycopy(this.atomCache, 0, objects, 0, k);
this.atomCache = objects;
}
this.atomCache[i] = entry;
return i;
}
@Nullable
public <T> CachedParseState.CacheEntry<T> getValue(int index) {
return (CachedParseState.CacheEntry<T>)this.atomCache[index + 1];
}
public void setValue(int index, CachedParseState.CacheEntry<?> value) {
this.atomCache[index + 1] = value;
}
}
class Silent implements ParseState<S> {
private final ErrorCollector<S> silentCollector = new ErrorCollector.Nop<>();
@Override
public ErrorCollector<S> errorCollector() {
return this.silentCollector;
}
@Override
public Scope scope() {
return CachedParseState.this.scope();
}
@Nullable
@Override
public <T> T parse(NamedRule<S, T> rule) {
return CachedParseState.this.parse(rule);
}
@Override
public S input() {
return CachedParseState.this.input();
}
@Override
public int mark() {
return CachedParseState.this.mark();
}
@Override
public void restore(int cursor) {
CachedParseState.this.restore(cursor);
}
@Override
public Control acquireControl() {
return CachedParseState.this.acquireControl();
}
@Override
public void releaseControl() {
CachedParseState.this.releaseControl();
}
@Override
public ParseState<S> silent() {
return this;
}
}
static class SimpleControl implements Control {
private boolean hasCut;
@Override
public void cut() {
this.hasCut = true;
}
@Override
public boolean hasCut() {
return this.hasCut;
}
public void reset() {
this.hasCut = false;
}
}
}