Stronger argument checks for ATN state and transition factory methods

This commit is contained in:
Sam Harwell 2012-12-07 11:16:04 -06:00
parent 26f16bed73
commit 0e91700678
2 changed files with 29 additions and 10 deletions

View File

@ -349,6 +349,7 @@ public abstract class ATNSimulator {
return c==65535 ? -1 : c; return c==65535 ? -1 : c;
} }
@NotNull
public static Transition edgeFactory(@NotNull ATN atn, public static Transition edgeFactory(@NotNull ATN atn,
int type, int src, int trg, int type, int src, int trg,
int arg1, int arg2, int arg3, int arg1, int arg2, int arg3,
@ -372,11 +373,12 @@ public abstract class ATNSimulator {
case Transition.NOT_SET : return new NotSetTransition(target, sets.get(arg1)); case Transition.NOT_SET : return new NotSetTransition(target, sets.get(arg1));
case Transition.WILDCARD : return new WildcardTransition(target); case Transition.WILDCARD : return new WildcardTransition(target);
} }
return null;
throw new IllegalArgumentException("The specified transition type is not valid.");
} }
public static ATNState stateFactory(int type, int stateNumber) { public static ATNState stateFactory(int type, int stateNumber) {
ATNState s = null; ATNState s;
switch (type) { switch (type) {
case ATNState.INVALID_TYPE: return null; case ATNState.INVALID_TYPE: return null;
case ATNState.BASIC : s = new ATNState(); break; case ATNState.BASIC : s = new ATNState(); break;
@ -392,9 +394,10 @@ public abstract class ATNSimulator {
case ATNState.PLUS_LOOP_BACK : s = new PlusLoopbackState(); break; case ATNState.PLUS_LOOP_BACK : s = new PlusLoopbackState(); break;
case ATNState.LOOP_END : s = new LoopEndState(); break; case ATNState.LOOP_END : s = new LoopEndState(); break;
default : default :
System.err.println("invalid state type in ATN deserialization: "+type+" for state "+stateNumber); String message = String.format("The specified state type %d for state %d is not valid.", type, stateNumber);
break; throw new IllegalArgumentException(message);
} }
s.stateNumber = stateNumber; s.stateNumber = stateNumber;
return s; return s;
} }

View File

@ -77,6 +77,7 @@ import org.antlr.v4.tool.ast.QuantifierAST;
import org.antlr.v4.tool.ast.TerminalAST; import org.antlr.v4.tool.ast.TerminalAST;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
@ -621,9 +622,13 @@ public class ParserATNFactory implements ATNFactory {
return t; return t;
} }
// TODO (sam): should we allow this to throw an exception instead of returning null? @NotNull
@Nullable
public <T extends ATNState> T newState(@NotNull Class<T> nodeType, GrammarAST node) { public <T extends ATNState> T newState(@NotNull Class<T> nodeType, GrammarAST node) {
if (!ATNState.class.isAssignableFrom(nodeType)) {
throw new IllegalArgumentException(String.format("%s is not a %s.", nodeType.getName(), ATNState.class.getName()));
}
Exception cause;
try { try {
Constructor<T> ctor = nodeType.getConstructor(); Constructor<T> ctor = nodeType.getConstructor();
T s = ctor.newInstance(); T s = ctor.newInstance();
@ -631,11 +636,22 @@ public class ParserATNFactory implements ATNFactory {
else s.setRuleIndex(currentRule.index); else s.setRuleIndex(currentRule.index);
atn.addState(s); atn.addState(s);
return s; return s;
} catch (InstantiationException ex) {
cause = ex;
} catch (IllegalAccessException ex) {
cause = ex;
} catch (IllegalArgumentException ex) {
cause = ex;
} catch (InvocationTargetException ex) {
cause = ex;
} catch (NoSuchMethodException ex) {
cause = ex;
} catch (SecurityException ex) {
cause = ex;
} }
catch (Exception e) {
ErrorManager.internalError("can't create ATN node: "+nodeType.getName(), e); String message = String.format("Could not create %s of type %s.", ATNState.class.getName(), nodeType.getName());
} throw new UnsupportedOperationException(message, cause);
return null;
} }
@NotNull @NotNull