package parser; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import util.ArrayUtils; import grammar.Expression; import grammar.Expression.Rule; /** * Memoizes only the last {@link #AMOUNT} parses for each rule. */ public class LimitedMemo implements Memo { /****************************************************************************/ private final Map<Expression, Memoed> memo = new HashMap<>(); /****************************************************************************/ private final Matcher matcher; /****************************************************************************/ public static final int AMOUNT = 10; /****************************************************************************/ LimitedMemo(Matcher matcher) { this.matcher = matcher; } /****************************************************************************/ private static class Memoed { private final Integer [] positions = new Integer [AMOUNT]; private final ParseData [] pdatas = new ParseData [AMOUNT]; int last = 0; { Arrays.fill(positions, -1); } ParseData atPosition(int position) { int index = ArrayUtils.search(positions, position); return index >= 0 ? pdatas[index] : null; } void insert(int position, ParseData pdata) { positions [last] = position; pdatas [last] = pdata; last = ++last % AMOUNT; } } /****************************************************************************/ @Override public ParseData get(int position, Expression expr) { if (!(expr instanceof Rule)) { return matcher.parse(expr); } Memoed memoed = memo.get(expr); if (memoed == null) { memoed = new Memoed(); memo.put(expr, memoed); } ParseData out = memoed.atPosition(position); if (out == null) { out = matcher.parse(expr); memoed.insert(position, out); } return out; } /****************************************************************************/ @Override public void clear() { memo.clear(); } }