Create ATNType enumeration for ATN.grammarType field, use UUID instead of incrementing a version number for improved reliability across branches

This commit is contained in:
Sam Harwell 2013-03-21 11:40:03 -05:00
parent 507f331bd0
commit 36abbda44f
4 changed files with 122 additions and 11 deletions

View File

@ -44,9 +44,6 @@ import java.util.Map;
public class ATN {
public static final int INVALID_ALT_NUMBER = 0;
public static final int PARSER = 1;
public static final int LEXER = 2;
@NotNull
public final List<ATNState> states = new ArrayList<ATNState>();
@ -64,8 +61,11 @@ public class ATN {
public final Map<String, TokensStartState> modeNameToStartState =
new LinkedHashMap<String, TokensStartState>();
// runtime for parsers, lexers
public int grammarType; // ATN.LEXER, ...
/**
* The type of the ATN.
*/
public ATNType grammarType;
public int maxTokenType;
// runtime for lexer only

View File

@ -40,11 +40,23 @@ import java.util.ArrayList;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Locale;
import java.util.UUID;
public abstract class ATNSimulator {
public static final int SERIALIZED_VERSION;
static {
SERIALIZED_VERSION = 2;
/* This value should never change. Updates following this version are
* reflected as change in the unique ID SERIALIZED_UUID.
*/
SERIALIZED_VERSION = 3;
}
public static final UUID SERIALIZED_UUID;
static {
/* WARNING: DO NOT MERGE THIS LINE. If UUIDs differ during a merge,
* resolve the conflict by generating a new ID!
*/
SERIALIZED_UUID = UUID.fromString("065C46D6-8859-4FD7-A158-83E693BF2B52");
}
/** Must distinguish between missing edge and edge we know leads nowhere */
@ -115,7 +127,14 @@ public abstract class ATNSimulator {
throw new UnsupportedOperationException(new InvalidClassException(ATN.class.getName(), reason));
}
atn.grammarType = toInt(data[p++]);
UUID uuid = toUUID(data, p);
p += 8;
if (!uuid.equals(SERIALIZED_UUID)) {
String reason = String.format(Locale.getDefault(), "Could not deserialize ATN with UUID %s (expected %s).", uuid, SERIALIZED_UUID);
throw new UnsupportedOperationException(new InvalidClassException(ATN.class.getName(), reason));
}
atn.grammarType = ATNType.values()[toInt(data[p++])];
atn.maxTokenType = toInt(data[p++]);
//
@ -164,7 +183,7 @@ public abstract class ATNSimulator {
// RULES
//
int nrules = toInt(data[p++]);
if ( atn.grammarType == ATN.LEXER ) {
if ( atn.grammarType == ATNType.LEXER ) {
atn.ruleToTokenType = new int[nrules];
atn.ruleToActionIndex = new int[nrules];
}
@ -173,7 +192,7 @@ public abstract class ATNSimulator {
int s = toInt(data[p++]);
RuleStartState startState = (RuleStartState)atn.states.get(s);
atn.ruleToStartState[i] = startState;
if ( atn.grammarType == ATN.LEXER ) {
if ( atn.grammarType == ATNType.LEXER ) {
int tokenType = toInt(data[p++]);
atn.ruleToTokenType[i] = tokenType;
int actionIndex = toInt(data[p++]);
@ -376,6 +395,21 @@ public abstract class ATNSimulator {
return c==65535 ? -1 : c;
}
public static int toInt32(char[] data, int offset) {
return (int)data[offset] | ((int)data[offset + 1] << 16);
}
public static long toLong(char[] data, int offset) {
long lowOrder = toInt32(data, offset) & 0x00000000FFFFFFFFL;
return lowOrder | ((long)toInt32(data, offset + 2) << 32);
}
public static UUID toUUID(char[] data, int offset) {
long leastSigBits = toLong(data, offset);
long mostSigBits = toLong(data, offset + 4);
return new UUID(mostSigBits, leastSigBits);
}
@NotNull
public static Transition edgeFactory(@NotNull ATN atn,
int type, int src, int trg,

View File

@ -0,0 +1,50 @@
/*
* [The "BSD license"]
* Copyright (c) 2013 Terence Parr
* Copyright (c) 2013 Sam Harwell
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.runtime.atn;
/**
* Represents the type of recognizer an ATN applies to.
*
* @author Sam Harwell
*/
public enum ATNType {
/**
* A lexer grammar.
*/
LEXER,
/**
* A parser grammar.
*/
PARSER,
}

View File

@ -35,6 +35,7 @@ import org.antlr.v4.parse.ANTLRParser;
import org.antlr.v4.runtime.atn.ATN;
import org.antlr.v4.runtime.atn.ATNSimulator;
import org.antlr.v4.runtime.atn.ATNState;
import org.antlr.v4.runtime.atn.ATNType;
import org.antlr.v4.runtime.atn.ActionTransition;
import org.antlr.v4.runtime.atn.AtomTransition;
import org.antlr.v4.runtime.atn.BlockStartState;
@ -55,6 +56,8 @@ import java.io.InvalidClassException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.UUID;
public class ATNSerializer {
public Grammar g;
@ -90,15 +93,17 @@ public class ATNSerializer {
public IntegerList serialize() {
IntegerList data = new IntegerList();
data.add(ATNSimulator.SERIALIZED_VERSION);
serializeUUID(data, ATNSimulator.SERIALIZED_UUID);
// convert grammar type to ATN const to avoid dependence on ANTLRParser
switch (g.getType()) {
case ANTLRParser.LEXER:
data.add(ATN.LEXER);
data.add(ATNType.LEXER.ordinal());
break;
case ANTLRParser.PARSER:
case ANTLRParser.COMBINED:
data.add(ATN.PARSER);
data.add(ATNType.PARSER.ordinal());
break;
default:
@ -285,6 +290,13 @@ public class ATNSerializer {
throw new UnsupportedOperationException(new InvalidClassException(ATN.class.getName(), reason));
}
UUID uuid = ATNSimulator.toUUID(data, p);
p += 8;
if (!uuid.equals(ATNSimulator.SERIALIZED_UUID)) {
String reason = String.format(Locale.getDefault(), "Could not deserialize ATN with UUID %s (expected %s).", uuid, ATNSimulator.SERIALIZED_UUID);
throw new UnsupportedOperationException(new InvalidClassException(ATN.class.getName(), reason));
}
int grammarType = ATNSimulator.toInt(data[p++]);
int maxType = ATNSimulator.toInt(data[p++]);
buf.append("max type ").append(maxType).append("\n");
@ -384,4 +396,19 @@ public class ATNSerializer {
char[] data = Utils.toCharArray(serialized);
return new ATNSerializer(g, atn).decode(data);
}
private void serializeUUID(IntegerList data, UUID uuid) {
serializeLong(data, uuid.getLeastSignificantBits());
serializeLong(data, uuid.getMostSignificantBits());
}
private void serializeLong(IntegerList data, long value) {
serializeInt(data, (int)value);
serializeInt(data, (int)(value >> 32));
}
private void serializeInt(IntegerList data, int value) {
data.add((char)value);
data.add((char)(value >> 16));
}
}