/* * Copyright (c) 2012 Sam Harwell, Tunnel Vision Laboratories LLC * All rights reserved. * * The source code of this document is proprietary work, and is not licensed for * distribution. For information about licensing, contact Sam Harwell at: * sam@tunnelvisionlabs.com */ package org.tvl.goworks.editor.go.semantics; import java.util.HashMap; import java.util.Map; import org.antlr.v4.runtime.Parser; import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.TokenStream; import org.antlr.v4.runtime.atn.ATN; import org.antlr.v4.runtime.atn.ATNConfig; import org.antlr.v4.runtime.atn.ATNConfigSet; import org.antlr.v4.runtime.atn.ATNState; import org.antlr.v4.runtime.atn.ParserATNSimulator; import org.antlr.v4.runtime.atn.PredictionContextCache; import org.antlr.v4.runtime.atn.RuleTransition; import org.antlr.v4.runtime.atn.SimulatorState; import org.antlr.v4.runtime.atn.Transition; import org.antlr.v4.runtime.dfa.DFA; import org.antlr.v4.runtime.dfa.DFAState; import org.antlr.v4.runtime.misc.IntegerList; import org.antlr.v4.runtime.misc.IntervalSet; /** * * @author Sam Harwell */ public class TreeCorrectionParserATNSimulator extends ParserATNSimulator { private final Map<Integer, IntervalSet> suppressedRules = new HashMap<>(); private int startIndex; public TreeCorrectionParserATNSimulator(Parser parser, ATN atn) { super(parser, atn); } public void suppressRule(int inputIndex, int ruleIndex) { IntervalSet set = suppressedRules.get(inputIndex); if (set != null) { set.add(ruleIndex); return; } suppressedRules.put(inputIndex, IntervalSet.of(ruleIndex)); } @Override public int adaptivePredict(TokenStream input, int decision, ParserRuleContext outerContext) { boolean ll1opt = optimize_ll1; try { startIndex = input.index(); if (getSuppressedSet(startIndex).isNil()) { optimize_ll1 = false; } return super.adaptivePredict(input, decision, outerContext); } finally { optimize_ll1 = ll1opt; } } @Override public SimulatorState getStartState(DFA dfa, TokenStream input, ParserRuleContext outerContext, boolean useContext) { // force execATN for special decisions if (getSuppressedSet(startIndex).isNil()) { return null; } return super.getStartState(dfa, input, outerContext, useContext); } @Override protected void addDFAEdge(DFAState p, int t, DFAState q) { if (!getSuppressedSet(startIndex).isNil()) { return; } super.addDFAEdge(p, t, q); } @Override protected DFAState addDFAEdge(DFA dfa, DFAState fromState, int t, IntegerList contextTransitions, ATNConfigSet toConfigs, PredictionContextCache contextCache) { if (!getSuppressedSet(startIndex).isNil()) { DFAState to = addDFAState(dfa, toConfigs, contextCache); return to; } return super.addDFAEdge(dfa, fromState, t, contextTransitions, toConfigs, contextCache); } @Override public ATNState getReachableTarget(ATNConfig source, Transition trans, int ttype) { if (trans instanceof RuleTransition) { IntervalSet suppressed = getSuppressedSet(startIndex); if (suppressed.contains(((RuleTransition)trans).ruleIndex)) { return null; } } return super.getReachableTarget(source, trans, ttype); } private IntervalSet getSuppressedSet(int startIndex) { IntervalSet suppressedSet = suppressedRules.get(startIndex); if (suppressedSet == null) { return IntervalSet.EMPTY_SET; } return suppressedSet; } }