forked from jasder/antlr
got more messages for recursion in there.
[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 6767]
This commit is contained in:
parent
ad036f9ab1
commit
a87f6e7666
|
@ -272,21 +272,29 @@ Input such as "<arg.input>" is insufficiently covered with predicates at locatio
|
||||||
<if(arg.hasPredicateBlockedByAction)><\n>At least one possibly relevant semantic predicate was hidden by action(s).<endif>
|
<if(arg.hasPredicateBlockedByAction)><\n>At least one possibly relevant semantic predicate was hidden by action(s).<endif>
|
||||||
>>
|
>>
|
||||||
|
|
||||||
DUPLICATE_SET_ENTRY(arg) ::=
|
ANALYSIS_TIMEOUT(arg) ::= <<
|
||||||
"duplicate token type <arg> when collapsing subrule into set"
|
ANTLR could not analyze this decision in rule <arg.enclosingRule>; often this is because of recursive rule references visible from the left edge of alternatives. ANTLR will re-analyze the decision with a fixed lookahead of k=1. Consider using "options {k=1;}" for that decision and possibly adding a syntactic predicate
|
||||||
|
|
||||||
ANALYSIS_ABORTED(enclosingRule) ::= <<
|
|
||||||
ANTLR could not analyze this decision in rule <enclosingRule>; often this is because of recursive rule references visible from the left edge of alternatives. ANTLR will re-analyze the decision with a fixed lookahead of k=1. Consider using "options {k=1;}" for that decision and possibly adding a syntactic predicate.
|
|
||||||
>>
|
>>
|
||||||
|
|
||||||
RECURSION_OVERFLOW(alt,input,targetRules,callSiteStates) ::= <<
|
RECURSION_OVERFLOW(alt,input,targetRules,callSiteStates) ::= <<
|
||||||
Alternative <alt>: after matching input such as <input> decision cannot predict what comes next due to recursion overflow <targetRules,callSiteStates:{t,c|to <t> from <c:{s|<s.enclosingRule.name>};separator=", ">}; separator=" and ">
|
Alternative <alt>: after matching input such as <input> decision cannot predict what comes next due to recursion overflow <targetRules,callSiteStates:{t,c|to <t> from <c:{s|<s.enclosingRule.name>};separator=", ">}; separator=" and ">
|
||||||
>>
|
>>
|
||||||
|
|
||||||
|
LEFT_RECURSION_CYCLES(arg) ::= <<
|
||||||
|
The following sets of rules are mutually left-recursive <arg:{c| [<c:{r|<r.name>}; separator=", ">]}; separator=" and ">
|
||||||
|
>>
|
||||||
|
|
||||||
|
MULTIPLE_RECURSIVE_ALTS(arg) ::= <<
|
||||||
|
[fatal] rule <arg.ruleName> has non-LL(*) decision due to recursive rule invocations reachable from alts <arg.alts; separator=",">. Resolve by left-factoring or using syntactic predicates or using backtrack=true option.
|
||||||
|
>>
|
||||||
|
|
||||||
UNREACHABLE_TOKENS(tokens) ::= <<
|
UNREACHABLE_TOKENS(tokens) ::= <<
|
||||||
The following token definitions can never be matched because prior tokens match the same input: <tokens; separator=",">
|
The following token definitions can never be matched because prior tokens match the same input: <tokens; separator=",">
|
||||||
>>
|
>>
|
||||||
|
|
||||||
|
DUPLICATE_SET_ENTRY(arg) ::=
|
||||||
|
"duplicate token type <arg> when collapsing subrule into set"
|
||||||
|
|
||||||
TOKEN_NONDETERMINISM(input,conflictingTokens,paths,disabled,hasPredicateBlockedByAction) ::=
|
TOKEN_NONDETERMINISM(input,conflictingTokens,paths,disabled,hasPredicateBlockedByAction) ::=
|
||||||
<<
|
<<
|
||||||
<if(paths)>
|
<if(paths)>
|
||||||
|
@ -297,15 +305,6 @@ Multiple token rules can match input such as "<input>": <conflictingTokens; sepa
|
||||||
<endif>
|
<endif>
|
||||||
<if(disabled)><\n>As a result, token(s) <disabled; separator=","> were disabled for that input<endif><if(hasPredicateBlockedByAction)><\n>Semantic predicates were present but were hidden by actions.<endif>
|
<if(disabled)><\n>As a result, token(s) <disabled; separator=","> were disabled for that input<endif><if(hasPredicateBlockedByAction)><\n>Semantic predicates were present but were hidden by actions.<endif>
|
||||||
>>
|
>>
|
||||||
|
|
||||||
LEFT_RECURSION_CYCLES(arg) ::= <<
|
|
||||||
The following sets of rules are mutually left-recursive <arg:{c| [<c:{r|<r.name>}; separator=", ">]}; separator=" and ">
|
|
||||||
>>
|
|
||||||
|
|
||||||
NONREGULAR_DECISION(ruleName,alts) ::= <<
|
|
||||||
[fatal] rule <ruleName> has non-LL(*) decision due to recursive rule invocations reachable from alts <alts; separator=",">. Resolve by left-factoring or using syntactic predicates or using backtrack=true option.
|
|
||||||
>>
|
|
||||||
|
|
||||||
/* l10n for message levels */
|
/* l10n for message levels */
|
||||||
WARNING() ::= "warning"
|
WARNING() ::= "warning"
|
||||||
ERROR() ::= "error"
|
ERROR() ::= "error"
|
||||||
|
|
|
@ -2,6 +2,7 @@ package org.antlr.v4.analysis;
|
||||||
|
|
||||||
import org.antlr.v4.automata.DFA;
|
import org.antlr.v4.automata.DFA;
|
||||||
import org.antlr.v4.automata.DecisionState;
|
import org.antlr.v4.automata.DecisionState;
|
||||||
|
import org.antlr.v4.tool.ErrorManager;
|
||||||
import org.antlr.v4.tool.Grammar;
|
import org.antlr.v4.tool.Grammar;
|
||||||
|
|
||||||
public class AnalysisPipeline {
|
public class AnalysisPipeline {
|
||||||
|
@ -36,8 +37,7 @@ public class AnalysisPipeline {
|
||||||
if ( dfa.valid() ) System.out.println("stack limited valid");
|
if ( dfa.valid() ) System.out.println("stack limited valid");
|
||||||
|
|
||||||
if ( dfa.valid() ) {
|
if ( dfa.valid() ) {
|
||||||
// ambig / unreachable errors
|
conv.issueAmbiguityWarnings(); // ambig / unreachable errors
|
||||||
conv.issueAmbiguityWarnings();
|
|
||||||
|
|
||||||
System.out.println("MINIMIZE");
|
System.out.println("MINIMIZE");
|
||||||
DFAMinimizer dmin = new DFAMinimizer(dfa);
|
DFAMinimizer dmin = new DFAMinimizer(dfa);
|
||||||
|
@ -52,14 +52,25 @@ public class AnalysisPipeline {
|
||||||
|
|
||||||
// REAL LL(*) ANALYSIS IF THAT FAILS
|
// REAL LL(*) ANALYSIS IF THAT FAILS
|
||||||
conv = new RecursionLimitedNFAToDFAConverter(g, s);
|
conv = new RecursionLimitedNFAToDFAConverter(g, s);
|
||||||
dfa = conv.createDFA();
|
try {
|
||||||
System.out.print("DFA="+dfa);
|
dfa = conv.createDFA();
|
||||||
|
System.out.print("DFA="+dfa);
|
||||||
|
}
|
||||||
|
catch (RecursionOverflowSignal ros) {
|
||||||
|
ErrorManager.recursionOverflow(g.fileName, dfa, ros.state, ros.altNum, ros.depth);
|
||||||
|
}
|
||||||
|
catch (MultipleRecursiveAltsSignal mras) {
|
||||||
|
ErrorManager.multipleRecursiveAlts(g.fileName, dfa, mras.recursiveAltSet);
|
||||||
|
}
|
||||||
|
catch (AnalysisTimeoutSignal at) {// TODO: nobody throws yet
|
||||||
|
ErrorManager.analysisTimeout();
|
||||||
|
}
|
||||||
|
|
||||||
// ambig / unreachable errors
|
conv.issueAmbiguityWarnings(); // ambig / unreachable errors
|
||||||
conv.issueAmbiguityWarnings();
|
//conv.issueRecursionWarnings();
|
||||||
if ( !dfa.valid() ) {
|
if ( !dfa.valid() ) {
|
||||||
System.out.println("non-LL(*)");
|
System.out.println("non-LL(*)");
|
||||||
System.out.println("recursion limited NOT valid :)");
|
System.out.println("recursion limited NOT valid");
|
||||||
}
|
}
|
||||||
else System.out.println("recursion limited valid");
|
else System.out.println("recursion limited valid");
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
package org.antlr.v4.analysis;
|
||||||
|
|
||||||
|
public class AnalysisTimeoutSignal extends RuntimeException {
|
||||||
|
public AnalysisTimeoutSignal() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -34,7 +34,7 @@ public class LeftRecursionDetector {
|
||||||
}
|
}
|
||||||
//System.out.println("cycles="+listOfRecursiveCycles);
|
//System.out.println("cycles="+listOfRecursiveCycles);
|
||||||
if ( listOfRecursiveCycles.size()>0 ) {
|
if ( listOfRecursiveCycles.size()>0 ) {
|
||||||
ErrorManager.leftRecursionCycles(listOfRecursiveCycles);
|
ErrorManager.leftRecursionCycles(nfa.g.fileName, listOfRecursiveCycles);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
package org.antlr.v4.analysis;
|
||||||
|
|
||||||
|
import org.antlr.v4.misc.IntSet;
|
||||||
|
|
||||||
|
public class MultipleRecursiveAltsSignal extends RuntimeException {
|
||||||
|
public IntSet recursiveAltSet;
|
||||||
|
public MultipleRecursiveAltsSignal(IntSet recursiveAltSet) {
|
||||||
|
this.recursiveAltSet = recursiveAltSet;
|
||||||
|
}
|
||||||
|
}
|
|
@ -215,14 +215,14 @@ public class RecursionLimitedNFAToDFAConverter extends StackLimitedNFAToDFAConve
|
||||||
if ( depth==1 ) { // recursion
|
if ( depth==1 ) { // recursion
|
||||||
recursiveAltSet.add(altNum); // indicate that this alt is recursive
|
recursiveAltSet.add(altNum); // indicate that this alt is recursive
|
||||||
if ( recursiveAltSet.size()>1 ) {
|
if ( recursiveAltSet.size()>1 ) {
|
||||||
throw new RuntimeException("recursion in >1 alt: "+recursiveAltSet);
|
throw new MultipleRecursiveAltsSignal(recursiveAltSet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Detect an attempt to recurse too high
|
// Detect an attempt to recurse too high
|
||||||
// if this context has hit the max recursions for p.stateNumber,
|
// if this context has hit the max recursions for p.stateNumber,
|
||||||
// don't allow it to enter p.stateNumber again
|
// don't allow it to enter p.stateNumber again
|
||||||
if ( depth >= r ) {
|
if ( depth >= r ) {
|
||||||
throw new RuntimeException("recursion overflow in "+altNum);
|
throw new RecursionOverflowSignal(altNum, depth, s);
|
||||||
}
|
}
|
||||||
// first create a new context and push onto call tree,
|
// first create a new context and push onto call tree,
|
||||||
// recording the fact that we are invoking a rule and
|
// recording the fact that we are invoking a rule and
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
package org.antlr.v4.analysis;
|
||||||
|
|
||||||
|
import org.antlr.v4.automata.NFAState;
|
||||||
|
|
||||||
|
public class RecursionOverflowSignal extends RuntimeException {
|
||||||
|
int altNum;
|
||||||
|
int depth;
|
||||||
|
NFAState state;
|
||||||
|
public RecursionOverflowSignal(int altNum, int depth, NFAState state) {
|
||||||
|
this.altNum = altNum;
|
||||||
|
this.depth = depth;
|
||||||
|
this.state = state;
|
||||||
|
}
|
||||||
|
}
|
|
@ -245,9 +245,7 @@ public class Resolver {
|
||||||
return alt;
|
return alt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void issueAmbiguityWarnings() {
|
||||||
|
|
||||||
void issueAmbiguityWarnings() {
|
|
||||||
MachineProbe probe = new MachineProbe(converter.dfa);
|
MachineProbe probe = new MachineProbe(converter.dfa);
|
||||||
|
|
||||||
for (DFAState d : converter.ambiguousStates) {
|
for (DFAState d : converter.ambiguousStates) {
|
||||||
|
@ -295,9 +293,89 @@ public class Resolver {
|
||||||
converter.hasPredicateBlockedByAction);
|
converter.hasPredicateBlockedByAction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( converter.unreachableAlts.size()>0 ) {
|
if ( converter.unreachableAlts!=null && converter.unreachableAlts.size()>0 ) {
|
||||||
ErrorManager.unreachableAlts(converter.g.fileName, converter.dfa, converter.unreachableAlts);
|
ErrorManager.unreachableAlts(converter.g.fileName, converter.dfa, converter.unreachableAlts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
void issueRecursionWarnings() {
|
||||||
|
// RECURSION OVERFLOW
|
||||||
|
Set dfaStatesWithRecursionProblems =
|
||||||
|
converter.stateToRecursionOverflowConfigurationsMap.keySet();
|
||||||
|
// now walk truly unique (unaliased) list of dfa states with inf recur
|
||||||
|
// Goal: create a map from alt to map<target,List<callsites>>
|
||||||
|
// Map<Map<String target, List<NFAState call sites>>
|
||||||
|
Map<Integer, Map<>> altToT argetToCallSitesMap = new HashMap();
|
||||||
|
// track a single problem DFA state for each alt
|
||||||
|
Map<Integer, DFAState> altToDFAState = new HashMap<Integer, DFAState>();
|
||||||
|
computeAltToProblemMaps(dfaStatesWithRecursionProblems,
|
||||||
|
converter.stateToRecursionOverflowConfigurationsMap,
|
||||||
|
altToTargetToCallSitesMap, // output param
|
||||||
|
altToDFAState); // output param
|
||||||
|
|
||||||
|
// walk each alt with recursion overflow problems and generate error
|
||||||
|
Set<Integer> alts = altToTargetToCallSitesMap.keySet();
|
||||||
|
List<Integer> sortedAlts = new ArrayList<Integer>(alts);
|
||||||
|
Collections.sort(sortedAlts);
|
||||||
|
for (Iterator altsIt = sortedAlts.iterator(); altsIt.hasNext();) {
|
||||||
|
Integer altI = (Integer) altsIt.next();
|
||||||
|
Map<Integer, > targetToCallSiteMap =
|
||||||
|
altToTargetToCallSitesMap.get(altI);
|
||||||
|
Set targetRules = targetToCallSiteMap.keySet();
|
||||||
|
Collection callSiteStates = targetToCallSiteMap.values();
|
||||||
|
DFAState sampleBadState = altToDFAState.get(altI);
|
||||||
|
ErrorManager.recursionOverflow(this,
|
||||||
|
sampleBadState,
|
||||||
|
altI.intValue(),
|
||||||
|
targetRules,
|
||||||
|
callSiteStates);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void computeAltToProblemMaps(Set<DFAState> dfaStatesUnaliased,
|
||||||
|
Map configurationsMap,
|
||||||
|
Map<Integer, NFAState> altToTargetToCallSitesMap,
|
||||||
|
Map altToDFAState)
|
||||||
|
{
|
||||||
|
for (DFAState d : dfaStatesUnaliased) {
|
||||||
|
for (NFAConfig c : d.nfaConfigs) {
|
||||||
|
NFAState ruleInvocationState = c.state;
|
||||||
|
RuleTransition rt = (RuleTransition)ruleInvocationState.transition(0);
|
||||||
|
String targetRule = rt.rule.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (Iterator it = dfaStatesUnaliased.iterator(); it.hasNext();) {
|
||||||
|
Integer stateI = (Integer) it.next();
|
||||||
|
// walk this DFA's config list
|
||||||
|
List configs = (List)configurationsMap.get(stateI);
|
||||||
|
for (int i = 0; i < configs.size(); i++) {
|
||||||
|
NFAConfig c = (NFAConfig) configs.get(i);
|
||||||
|
NFAState ruleInvocationState = c.state;
|
||||||
|
Transition transition0 = ruleInvocationState.transition(0);
|
||||||
|
RuleTransition ref = (RuleTransition)transition0;
|
||||||
|
String targetRule = ((NFAState) ref.target).rule.name;
|
||||||
|
Integer altI = org.antlr.misc.Utils.integer(c.alt);
|
||||||
|
Map<Integer, NFAState> targetToCallSiteMap =
|
||||||
|
altToTargetToCallSitesMap.get(altI);
|
||||||
|
if ( targetToCallSiteMap==null ) {
|
||||||
|
targetToCallSiteMap = new HashMap();
|
||||||
|
altToTargetToCallSitesMap.put(altI, targetToCallSiteMap);
|
||||||
|
}
|
||||||
|
Set<NFAState> callSites = targetToCallSiteMap.get(targetRule);
|
||||||
|
if ( callSites==null ) {
|
||||||
|
callSites = new HashSet();
|
||||||
|
targetToCallSiteMap.put(targetRule, callSites);
|
||||||
|
}
|
||||||
|
callSites.add(ruleInvocationState);
|
||||||
|
// track one problem DFA state per alt
|
||||||
|
if ( altToDFAState.get(altI)==null ) {
|
||||||
|
DFAState sampleBadState = converter.dfa.states.get(stateI.intValue());
|
||||||
|
altToDFAState.put(altI, sampleBadState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import org.antlr.v4.misc.IntervalSet;
|
||||||
import org.antlr.v4.misc.OrderedHashSet;
|
import org.antlr.v4.misc.OrderedHashSet;
|
||||||
import org.antlr.v4.tool.Grammar;
|
import org.antlr.v4.tool.Grammar;
|
||||||
import org.antlr.v4.tool.Rule;
|
import org.antlr.v4.tool.Rule;
|
||||||
|
import org.stringtemplate.v4.misc.MultiMap;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
@ -67,7 +68,13 @@ public class StackLimitedNFAToDFAConverter {
|
||||||
|
|
||||||
public boolean hasPredicateBlockedByAction = false;
|
public boolean hasPredicateBlockedByAction = false;
|
||||||
|
|
||||||
public Set<DFAState> recursionOverflowStates = new HashSet<DFAState>();
|
/** Recursion is limited to a particular depth. If that limit is exceeded
|
||||||
|
* the proposed new NFA configuration is recorded for the associated DFA state.
|
||||||
|
*/
|
||||||
|
protected MultiMap<DFAState, NFAConfig> stateToRecursionOverflowConfigurationsMap =
|
||||||
|
new MultiMap<DFAState, NFAConfig>();
|
||||||
|
|
||||||
|
//public Set<DFAState> recursionOverflowStates = new HashSet<DFAState>();
|
||||||
|
|
||||||
/** Are there any loops in this DFA? Computed by DFAVerifier */
|
/** Are there any loops in this DFA? Computed by DFAVerifier */
|
||||||
public boolean cyclic = false;
|
public boolean cyclic = false;
|
||||||
|
@ -575,4 +582,5 @@ public class StackLimitedNFAToDFAConverter {
|
||||||
}
|
}
|
||||||
|
|
||||||
void issueAmbiguityWarnings() { resolver.issueAmbiguityWarnings(); }
|
void issueAmbiguityWarnings() { resolver.issueAmbiguityWarnings(); }
|
||||||
|
//void issueRecursionWarnings() { resolver.issueRecursionWarnings(); }
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
package org.antlr.v4.tool;
|
||||||
|
|
||||||
|
public class AnalysisTimeoutMessage extends Message {
|
||||||
|
public AnalysisTimeoutMessage() {
|
||||||
|
super(ErrorType.ANALYSIS_TIMEOUT);
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,8 @@ import org.antlr.runtime.RecognitionException;
|
||||||
import org.antlr.runtime.Token;
|
import org.antlr.runtime.Token;
|
||||||
import org.antlr.v4.automata.DFA;
|
import org.antlr.v4.automata.DFA;
|
||||||
import org.antlr.v4.automata.DFAState;
|
import org.antlr.v4.automata.DFAState;
|
||||||
|
import org.antlr.v4.automata.NFAState;
|
||||||
|
import org.antlr.v4.misc.IntSet;
|
||||||
import org.antlr.v4.parse.v4ParserException;
|
import org.antlr.v4.parse.v4ParserException;
|
||||||
import org.stringtemplate.v4.ST;
|
import org.stringtemplate.v4.ST;
|
||||||
import org.stringtemplate.v4.STErrorListener;
|
import org.stringtemplate.v4.STErrorListener;
|
||||||
|
@ -346,17 +348,31 @@ public class ErrorManager {
|
||||||
state.get().listener.warning(msg);
|
state.get().listener.warning(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void leftRecursionCycles(Collection cycles) {
|
public static void leftRecursionCycles(String fileName, Collection cycles) {
|
||||||
state.get().errors++;
|
state.get().errors++;
|
||||||
Message msg = new LeftRecursionCyclesMessage(cycles);
|
Message msg = new LeftRecursionCyclesMessage(fileName, cycles);
|
||||||
state.get().listener.warning(msg);
|
state.get().listener.error(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Process a new message by sending it on to the error listener associated with the current thread
|
public static void recursionOverflow(String fileName,
|
||||||
* and recording any information we need in the error state for the current thread.
|
DFA dfa, NFAState s, int altNum, int depth) {
|
||||||
*/
|
state.get().errors++;
|
||||||
private static void processMessage() {
|
Message msg = new RecursionOverflowMessage(fileName, dfa, s, altNum, depth);
|
||||||
}
|
state.get().listener.error(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void multipleRecursiveAlts(String fileName,
|
||||||
|
DFA dfa, IntSet recursiveAltSet) {
|
||||||
|
state.get().errors++;
|
||||||
|
Message msg = new MultipleRecursiveAltsMessage(fileName, dfa, recursiveAltSet);
|
||||||
|
state.get().listener.error(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void analysisTimeout() {
|
||||||
|
state.get().errors++;
|
||||||
|
Message msg = new AnalysisTimeoutMessage();
|
||||||
|
state.get().listener.error(msg);
|
||||||
|
}
|
||||||
|
|
||||||
public static int getNumErrors() {
|
public static int getNumErrors() {
|
||||||
return state.get().errors;
|
return state.get().errors;
|
||||||
|
|
|
@ -134,10 +134,14 @@ public enum ErrorType {
|
||||||
|
|
||||||
AMBIGUITY(ErrorSeverity.ERROR, true, true),
|
AMBIGUITY(ErrorSeverity.ERROR, true, true),
|
||||||
UNREACHABLE_ALTS(ErrorSeverity.ERROR, true, true),
|
UNREACHABLE_ALTS(ErrorSeverity.ERROR, true, true),
|
||||||
RECURSION_OVERFLOW(ErrorSeverity.ERROR, true, true),
|
MULTIPLE_RECURSIVE_ALTS(ErrorSeverity.ERROR, true, true),
|
||||||
INSUFFICIENT_PREDICATES(ErrorSeverity.ERROR, true, true),
|
INSUFFICIENT_PREDICATES(ErrorSeverity.ERROR, true, true),
|
||||||
|
|
||||||
|
// these next 3 can happen in recursion-limited LL(*)
|
||||||
|
RECURSION_OVERFLOW(ErrorSeverity.ERROR, true, true),
|
||||||
LEFT_RECURSION_CYCLES(ErrorSeverity.ERROR, true, true),
|
LEFT_RECURSION_CYCLES(ErrorSeverity.ERROR, true, true),
|
||||||
|
ANALYSIS_TIMEOUT(ErrorSeverity.ERROR, true, true),
|
||||||
|
|
||||||
/** Documentation comment is unterminated */
|
/** Documentation comment is unterminated */
|
||||||
//UNTERMINATED_DOC_COMMENT(ErrorSeverity.ERROR, true, true),
|
//UNTERMINATED_DOC_COMMENT(ErrorSeverity.ERROR, true, true),
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,9 @@ import java.util.Collection;
|
||||||
public class LeftRecursionCyclesMessage extends Message {
|
public class LeftRecursionCyclesMessage extends Message {
|
||||||
public Collection cycles;
|
public Collection cycles;
|
||||||
|
|
||||||
public LeftRecursionCyclesMessage(Collection cycles) {
|
public LeftRecursionCyclesMessage(String fileName, Collection cycles) {
|
||||||
super(ErrorType.LEFT_RECURSION_CYCLES, cycles);
|
super(ErrorType.LEFT_RECURSION_CYCLES, cycles);
|
||||||
this.cycles = cycles;
|
this.cycles = cycles;
|
||||||
|
this.fileName = fileName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
package org.antlr.v4.tool;
|
||||||
|
|
||||||
|
import org.antlr.v4.automata.DFA;
|
||||||
|
import org.antlr.v4.misc.IntSet;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class MultipleRecursiveAltsMessage extends Message {
|
||||||
|
public DFA dfa;
|
||||||
|
public IntSet recursiveAltSet;
|
||||||
|
|
||||||
|
public MultipleRecursiveAltsMessage(String fileName, DFA dfa, IntSet recursiveAltSet) {
|
||||||
|
super(ErrorType.MULTIPLE_RECURSIVE_ALTS);
|
||||||
|
this.dfa = dfa;
|
||||||
|
this.recursiveAltSet = recursiveAltSet;
|
||||||
|
|
||||||
|
this.line = dfa.decisionNFAStartState.ast.getLine();
|
||||||
|
this.charPosition = dfa.decisionNFAStartState.ast.getCharPositionInLine();
|
||||||
|
this.fileName = fileName;
|
||||||
|
|
||||||
|
Map<String, Object> info = new HashMap<String, Object>();
|
||||||
|
info.put("dfa", dfa);
|
||||||
|
info.put("ruleName", dfa.decisionNFAStartState.rule.name);
|
||||||
|
info.put("alts", recursiveAltSet);
|
||||||
|
args = new Object[] {info}; // pass this whole object in to message
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,34 @@
|
||||||
package org.antlr.v4.tool;
|
package org.antlr.v4.tool;
|
||||||
|
|
||||||
|
import org.antlr.v4.automata.DFA;
|
||||||
|
import org.antlr.v4.automata.NFAState;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class RecursionOverflowMessage extends Message {
|
public class RecursionOverflowMessage extends Message {
|
||||||
|
DFA dfa;
|
||||||
|
NFAState s;
|
||||||
|
int altNum;
|
||||||
|
int depth;
|
||||||
|
public RecursionOverflowMessage(String fileName, DFA dfa, NFAState s, int altNum, int depth) {
|
||||||
|
super(ErrorType.RECURSION_OVERFLOW);
|
||||||
|
this.dfa = dfa;
|
||||||
|
this.s = s;
|
||||||
|
this.altNum = altNum;
|
||||||
|
this.depth = depth;
|
||||||
|
|
||||||
|
this.line = dfa.decisionNFAStartState.ast.getLine();
|
||||||
|
this.charPosition = dfa.decisionNFAStartState.ast.getCharPositionInLine();
|
||||||
|
this.fileName = fileName;
|
||||||
|
|
||||||
|
Map<String, Object> info = new HashMap<String, Object>();
|
||||||
|
info.put("dfa", dfa);
|
||||||
|
info.put("alt", altNum);
|
||||||
|
info.put("depth", depth);
|
||||||
|
info.put("nfaState", s);
|
||||||
|
info.put("sourceRule", s.rule);
|
||||||
|
info.put("targetRule", s.transition(0).target.rule);
|
||||||
|
args = new Object[] {info}; // pass this whole object in to message
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue