Clean up the caching of ATN instances with bypass alternatives

This commit is contained in:
Sam Harwell 2013-12-10 20:15:32 -06:00
parent 2618aa335a
commit df61690758
3 changed files with 32 additions and 26 deletions

View File

@ -51,6 +51,8 @@ import org.antlr.v4.runtime.tree.pattern.ParseTreePatternMatcher;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
/** This is all the parsing support code essentially; most of it is error recovery stuff. */
public abstract class Parser extends Recognizer<Token, ParserATNSimulator> {
@ -98,6 +100,15 @@ public abstract class Parser extends Recognizer<Token, ParserATNSimulator> {
}
}
/**
* This field maps from the serialized ATN string to the deserialized {@link ATN} with
* bypass alternatives.
*
* @see ATNDeserializationOptions#isGenerateRuleBypassTransitions()
*/
private static final Map<String, ATN> bypassAltsAtnCache =
new WeakHashMap<String, ATN>();
/**
* The error handling strategy for the parser. The default value is a new
* instance of {@link DefaultErrorStrategy}.
@ -435,26 +446,30 @@ public abstract class Parser extends Recognizer<Token, ParserATNSimulator> {
_input.getTokenSource().setTokenFactory(factory);
}
/** The ATN with bypass alternatives is expensive to create so we create it lazily.
* The actual generated parsers override this method. These are just
* setters/getters. createATNWithBypassAlts() does the creation.
/**
* The ATN with bypass alternatives is expensive to create so we create it
* lazily.
*
* @throws UnsupportedOperationException if the current parser does not
* implement the {@link #getSerializedATN()} method.
*/
public void setATNWithBypassAlts(ATN atn) { }
public ATN getATNWithBypassAlts() { return null; }
@NotNull
public ATN getATNWithBypassAlts() {
String serializedAtn = getSerializedATN();
if (serializedAtn == null) {
throw new UnsupportedOperationException("The current parser does not support an ATN with bypass alternatives.");
}
/** Create and cache the ATN with bypass alternatives. This is not
* part of the typical API--use compileParseTreePattern().
*/
public void createATNWithBypassAlts() {
if ( getATNWithBypassAlts()==null ) {
synchronized (Parser.class) { // create just one pattern matcher
if ( getATNWithBypassAlts()==null ) { // double-check
String sATN = getSerializedATN();
synchronized (bypassAltsAtnCache) {
ATN result = bypassAltsAtnCache.get(serializedAtn);
if (result == null) {
ATNDeserializationOptions deserializationOptions = new ATNDeserializationOptions();
deserializationOptions.setGenerateRuleBypassTransitions(true);
setATNWithBypassAlts( new ATNDeserializer(deserializationOptions).deserialize(sATN.toCharArray()) );
}
result = new ATNDeserializer(deserializationOptions).deserialize(serializedAtn.toCharArray());
bypassAltsAtnCache.put(serializedAtn, result);
}
return result;
}
}
@ -483,7 +498,6 @@ public abstract class Parser extends Recognizer<Token, ParserATNSimulator> {
public ParseTreePattern compileParseTreePattern(String pattern, int patternRuleIndex,
Lexer lexer)
{
createATNWithBypassAlts();
ParseTreePatternMatcher m = new ParseTreePatternMatcher(lexer, this);
return m.compile(pattern, patternRuleIndex);
}

View File

@ -132,9 +132,6 @@ public class ParseTreePatternMatcher {
public ParseTreePatternMatcher(Lexer lexer, Parser parser) {
this.lexer = lexer;
this.parser = parser;
if ( parser!=null ) {
parser.createATNWithBypassAlts();
}
}
public void setDelimiters(String start, String stop, String escapeLeft) {

View File

@ -247,10 +247,6 @@ public class <parser.name> extends <superClass> {
@Override
public ATN getATN() { return _ATN; }
@Override
public ATN getATNWithBypassAlts() { return _ATNWithBypassAlts; }
@Override
public void setATNWithBypassAlts(ATN atn) { _ATNWithBypassAlts = atn; }
@Override
public Map\<String, Integer> getTokenTypeMap() { return tokenNameToType; }
@ -935,7 +931,6 @@ public static final String _serializedATN =
<endif>
public static final ATN _ATN =
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
public static ATN _ATNWithBypassAlts;
static {
_decisionToDFA = new DFA[_ATN.getNumberOfDecisions()];
for (int i = 0; i \< _ATN.getNumberOfDecisions(); i++) {