forked from jasder/antlr
got line num etc... into ambig, unreachable warnings
[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 6760]
This commit is contained in:
parent
d72dbb7af4
commit
2aa34fc41e
|
@ -240,6 +240,11 @@ CONFLICTING_OPTION_IN_TREE_FILTER(arg,arg2) ::=
|
|||
|
||||
// GRAMMAR WARNINGS
|
||||
|
||||
AMBIGUITY(arg) ::= <<
|
||||
Decision can match input such as "<arg.input>" using multiple alternatives:
|
||||
<arg.conflictingPaths.keys:{alt | alt <alt> via tokens <arg.conflictingPaths.(alt); separator=","><\n>}>
|
||||
>>
|
||||
|
||||
GRAMMAR_NONDETERMINISM(input,conflictingAlts,paths,disabled,hasPredicateBlockedByAction) ::=
|
||||
<<
|
||||
<if(paths)>
|
||||
|
@ -255,8 +260,8 @@ DANGLING_STATE(danglingAlts,input) ::= <<
|
|||
the decision cannot distinguish between alternative(s) <danglingAlts; separator=","> for input such as "<input>"
|
||||
>>
|
||||
|
||||
UNREACHABLE_ALTS(alts) ::= <<
|
||||
The following alternatives can never be matched: <alts; separator=","><\n>
|
||||
UNREACHABLE_ALTS(arg) ::= <<
|
||||
The following alternatives can never be matched: <arg.alts; separator=","><\n>
|
||||
>>
|
||||
|
||||
INSUFFICIENT_PREDICATES(upon,altToLocations,hasPredicateBlockedByAction) ::= <<
|
||||
|
@ -270,7 +275,7 @@ 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_OVERLOW(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 ">
|
||||
>>
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@ public class DFAMinimizer {
|
|||
// we may have also have multiple accepts per alt--put all of them in same partition
|
||||
for (int alt=1; alt<=dfa.nAlts; alt++) {
|
||||
List<DFAState> acceptsForAlt = dfa.altToAcceptStates[alt];
|
||||
if ( acceptsForAlt==null ) continue; // hmm...must be unreachable
|
||||
// distinguish all these accepts from every other state
|
||||
for (DFAState p : acceptsForAlt) {
|
||||
for (int i=0; i<n; i++) {
|
||||
|
@ -141,7 +142,7 @@ public class DFAMinimizer {
|
|||
uniq.add(s);
|
||||
}
|
||||
System.out.println("uniq sets = "+uniq);
|
||||
if ( uniq.size()==0 ) {
|
||||
if ( uniq.size()==dfa.states.size() ) {
|
||||
System.out.println("was already minimal");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import org.antlr.v4.automata.*;
|
|||
import org.antlr.v4.misc.IntSet;
|
||||
import org.antlr.v4.misc.IntervalSet;
|
||||
import org.antlr.v4.misc.OrderedHashSet;
|
||||
import org.antlr.v4.tool.ErrorManager;
|
||||
import org.antlr.v4.tool.Grammar;
|
||||
import org.antlr.v4.tool.Rule;
|
||||
|
||||
|
@ -571,7 +572,7 @@ public class StackLimitedNFAToDFAConverter {
|
|||
// TODO: where does this belong?
|
||||
void issueAmbiguityWarnings() {
|
||||
MachineProbe probe = new MachineProbe(dfa);
|
||||
|
||||
|
||||
for (DFAState d : ambiguousStates) {
|
||||
Set<Integer> alts = resolver.getAmbiguousAlts(d);
|
||||
List<Integer> sorted = new ArrayList<Integer>(alts);
|
||||
|
@ -586,8 +587,10 @@ public class StackLimitedNFAToDFAConverter {
|
|||
|
||||
List<IntSet> labels = probe.getEdgeLabels(d);
|
||||
|
||||
System.out.println("labels="+probe.getInputSequenceDisplay(g, labels));
|
||||
String input = probe.getInputSequenceDisplay(g, labels);
|
||||
System.out.println("input="+ input);
|
||||
|
||||
LinkedHashMap<Integer,List<Token>> altPaths = new LinkedHashMap<Integer,List<Token>>();
|
||||
for (int alt : sorted) {
|
||||
List<Set<NFAState>> nfaStates = new ArrayList<Set<NFAState>>();
|
||||
for (DFAState d2 : dfaStates) {
|
||||
|
@ -596,9 +599,13 @@ public class StackLimitedNFAToDFAConverter {
|
|||
System.out.println("NFAConfigs per state: "+nfaStates);
|
||||
List<Token> path =
|
||||
probe.getGrammarLocationsForInputSequence(nfaStates, labels);
|
||||
altPaths.put(alt, path);
|
||||
System.out.println("path = "+path);
|
||||
}
|
||||
ErrorManager.ambiguity(dfa.g.fileName, d, sorted, input, altPaths);
|
||||
}
|
||||
if ( unreachableAlts.size()>0 ) {
|
||||
ErrorManager.unreachableAlts(dfa.g.fileName, dfa, unreachableAlts);
|
||||
}
|
||||
if ( unreachableAlts.size()>0 ) System.err.println("unreachable="+unreachableAlts);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -570,7 +570,8 @@ altList
|
|||
// use a separate rule so that the BLOCK node has start and stop
|
||||
// boundaries set correctly by rule post processing of rewrites.
|
||||
ruleBlock
|
||||
: altList -> ^(BLOCK<BlockAST> altList)
|
||||
@init {Token colon = input.LT(-1);}
|
||||
: altList -> ^(BLOCK<BlockAST>[colon,"BLOCK"] altList)
|
||||
;
|
||||
catch [ResyncToEndOfRuleBlock e] {
|
||||
// just resyncing; ignore error
|
||||
|
@ -601,11 +602,11 @@ element
|
|||
}
|
||||
@after { paraphrases.pop(); }
|
||||
: labeledElement
|
||||
( ebnfSuffix -> ^( ebnfSuffix ^(BLOCK<BlockAST> ^(ALT labeledElement ) ))
|
||||
( ebnfSuffix -> ^( ebnfSuffix ^(BLOCK<BlockAST>[$labeledElement.start,"BLOCK"] ^(ALT labeledElement ) ))
|
||||
| -> labeledElement
|
||||
)
|
||||
| atom
|
||||
( ebnfSuffix -> ^( ebnfSuffix ^(BLOCK<BlockAST> ^(ALT atom ) ) )
|
||||
( ebnfSuffix -> ^( ebnfSuffix ^(BLOCK<BlockAST>[$atom.start,"BLOCK"] ^(ALT atom) ) )
|
||||
| -> atom
|
||||
)
|
||||
| ebnf
|
||||
|
@ -615,7 +616,7 @@ element
|
|||
| -> SEMPRED
|
||||
)
|
||||
| treeSpec
|
||||
( ebnfSuffix -> ^( ebnfSuffix ^(BLOCK<BlockAST> ^(ALT treeSpec ) ) )
|
||||
( ebnfSuffix -> ^( ebnfSuffix ^(BLOCK<BlockAST>[$treeSpec.start,"BLOCK"] ^(ALT treeSpec ) ) )
|
||||
| -> treeSpec
|
||||
)
|
||||
;
|
||||
|
@ -804,7 +805,7 @@ block
|
|||
( optionsSpec? ra+=ruleAction* COLON )?
|
||||
altList
|
||||
RPAREN
|
||||
-> ^(BLOCK<BlockAST> optionsSpec? $ra* altList )
|
||||
-> ^(BLOCK<BlockAST>[$LPAREN,"BLOCK"] optionsSpec? $ra* altList )
|
||||
;
|
||||
|
||||
// ----------------
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,41 @@
|
|||
package org.antlr.v4.tool;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.antlr.v4.automata.DFAState;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class AmbiguityMessage extends Message {
|
||||
public DFAState d;
|
||||
public List<Integer> conflictingAlts;
|
||||
public String input;
|
||||
public LinkedHashMap<Integer,List<Token>> conflictingPaths;
|
||||
|
||||
public AmbiguityMessage(ErrorType etype,
|
||||
String fileName,
|
||||
DFAState d,
|
||||
List<Integer> conflictingAlts,
|
||||
String input,
|
||||
LinkedHashMap<Integer,List<Token>> conflictingPaths)
|
||||
{
|
||||
super(etype);
|
||||
this.fileName = fileName;
|
||||
this.d = d;
|
||||
this.conflictingAlts = conflictingAlts;
|
||||
this.input = input;
|
||||
this.conflictingPaths = conflictingPaths;
|
||||
|
||||
this.line = d.dfa.decisionNFAStartState.ast.getLine();
|
||||
this.charPosition = d.dfa.decisionNFAStartState.ast.getCharPositionInLine();
|
||||
|
||||
Map<String, Object> info = new HashMap<String, Object>();
|
||||
info.put("dfaState", d);
|
||||
info.put("conflictingAlts", conflictingAlts);
|
||||
info.put("input", input);
|
||||
info.put("conflictingPaths", conflictingPaths);
|
||||
args = new Object[] {info}; // pass this whole object in to message
|
||||
}
|
||||
}
|
|
@ -1,8 +1,6 @@
|
|||
package org.antlr.v4.tool;
|
||||
|
||||
import org.antlr.runtime.CommonToken;
|
||||
import org.antlr.runtime.Token;
|
||||
import org.antlr.v4.parse.ANTLRParser;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
@ -18,5 +16,6 @@ public class BlockAST extends GrammarASTWithOptions {
|
|||
|
||||
public BlockAST(Token t) { super(t); }
|
||||
public BlockAST(int type) { super(type); }
|
||||
public BlockAST(int type, Token t) { super(type, t); }
|
||||
public BlockAST(int type, Token t) { super(type, t); }
|
||||
public BlockAST(int type, Token t, String text) { super(type,t,text); }
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@ import org.antlr.runtime.NoViableAltException;
|
|||
import org.antlr.runtime.Parser;
|
||||
import org.antlr.runtime.RecognitionException;
|
||||
import org.antlr.runtime.Token;
|
||||
import org.antlr.v4.automata.DFA;
|
||||
import org.antlr.v4.automata.DFAState;
|
||||
import org.antlr.v4.parse.v4ParserException;
|
||||
import org.stringtemplate.v4.ST;
|
||||
import org.stringtemplate.v4.STErrorListener;
|
||||
|
@ -13,6 +15,9 @@ import org.stringtemplate.v4.misc.ErrorBuffer;
|
|||
import org.stringtemplate.v4.misc.STMessage;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
/** Defines all the errors ANTLR can generator for both the tool and for
|
||||
|
@ -295,7 +300,38 @@ public class ErrorManager {
|
|||
state.get().listener.warning(msg);
|
||||
}
|
||||
|
||||
/** Process a new message by sending it on to the error listener associated with the current thread
|
||||
public static void ambiguity(String fileName,
|
||||
DFAState d,
|
||||
List<Integer> conflictingAlts,
|
||||
String input,
|
||||
LinkedHashMap<Integer,List<Token>> conflictingPaths)
|
||||
{
|
||||
state.get().warnings++;
|
||||
AmbiguityMessage msg =
|
||||
new AmbiguityMessage(ErrorType.AMBIGUITY,fileName,
|
||||
d,
|
||||
conflictingAlts,
|
||||
input,
|
||||
conflictingPaths);
|
||||
state.get().listener.warning(msg);
|
||||
}
|
||||
|
||||
public static void unreachableAlts(String fileName,
|
||||
DFA dfa,
|
||||
Collection<Integer> unreachableAlts)
|
||||
{
|
||||
System.err.println("unreachable="+unreachableAlts);
|
||||
state.get().warnings++;
|
||||
UnreachableAltsMessage msg =
|
||||
new UnreachableAltsMessage(ErrorType.UNREACHABLE_ALTS,
|
||||
fileName,
|
||||
dfa,
|
||||
unreachableAlts);
|
||||
state.get().listener.warning(msg);
|
||||
}
|
||||
|
||||
|
||||
/** Process a new message by sending it on to the error listener associated with the current thread
|
||||
* and recording any information we need in the error state for the current thread.
|
||||
*/
|
||||
private static void processMessage() {
|
||||
|
@ -358,6 +394,7 @@ public class ErrorManager {
|
|||
}
|
||||
|
||||
messages = new STGroupFile(fileName, "UTF-8");
|
||||
messages.debug = true;
|
||||
messages.load();
|
||||
if ( initSTListener.errors.size()>0 ) {
|
||||
rawError("ANTLR installation corrupted; can't load messages format file:\n"+
|
||||
|
@ -398,6 +435,7 @@ public class ErrorManager {
|
|||
}
|
||||
|
||||
format = new STGroupFile(fileName, "UTF-8");
|
||||
format.debug = true;
|
||||
format.load();
|
||||
|
||||
if ( initSTListener.errors.size()>0 ) {
|
||||
|
|
|
@ -131,6 +131,11 @@ public enum ErrorType {
|
|||
AST_OP_IN_ALT_WITH_REWRITE(ErrorSeverity.ERROR, true, true),
|
||||
WILDCARD_AS_ROOT(ErrorSeverity.ERROR, true, true),
|
||||
CONFLICTING_OPTION_IN_TREE_FILTER(ErrorSeverity.ERROR, true, true),
|
||||
|
||||
AMBIGUITY(ErrorSeverity.ERROR, true, true),
|
||||
UNREACHABLE_ALTS(ErrorSeverity.ERROR, true, true),
|
||||
RECURSION_OVERFLOW(ErrorSeverity.ERROR, true, true),
|
||||
|
||||
/** Documentation comment is unterminated */
|
||||
//UNTERMINATED_DOC_COMMENT(ErrorSeverity.ERROR, true, true),
|
||||
|
||||
|
|
|
@ -16,11 +16,15 @@ public class GrammarAST extends CommonTree {
|
|||
public GrammarAST(Token t) { super(t); }
|
||||
public GrammarAST(GrammarAST node) { super(node); }
|
||||
public GrammarAST(int type) { super(new CommonToken(type, ANTLRParser.tokenNames[type])); }
|
||||
public GrammarAST(int type, Token t) { this(t); t.setType(type); }
|
||||
public GrammarAST(int type, Token t) {
|
||||
this(new CommonToken(type, t.getText()));
|
||||
token.setLine(t.getLine());
|
||||
token.setCharPositionInLine(t.getCharPositionInLine());
|
||||
}
|
||||
public GrammarAST(int type, Token t, String text) {
|
||||
this(t);
|
||||
t.setType(type);
|
||||
t.setText(text);
|
||||
this(new CommonToken(type, text));
|
||||
token.setLine(t.getLine());
|
||||
token.setCharPositionInLine(t.getCharPositionInLine());
|
||||
}
|
||||
|
||||
public List<GrammarAST> getNodesWithType(int ttype) {
|
||||
|
|
|
@ -72,6 +72,8 @@ public class Message {
|
|||
|
||||
if (locationValid) reportST.add("location", locationST);
|
||||
reportST.add("message", messageFormatST);
|
||||
//((DebugST)reportST).inspect();
|
||||
//reportST.impl.dump();
|
||||
return reportST;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
package org.antlr.v4.tool;
|
||||
|
||||
public class RecursionOverflowMessage extends Message {
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package org.antlr.v4.tool;
|
||||
|
||||
import org.antlr.v4.automata.DFA;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class UnreachableAltsMessage extends Message {
|
||||
public DFA dfa;
|
||||
public Collection<Integer> conflictingAlts;
|
||||
|
||||
public UnreachableAltsMessage(ErrorType etype,
|
||||
String fileName,
|
||||
DFA dfa,
|
||||
Collection<Integer> conflictingAlts)
|
||||
{
|
||||
super(etype);
|
||||
this.fileName = fileName;
|
||||
this.dfa = dfa;
|
||||
this.conflictingAlts = conflictingAlts;
|
||||
this.line = dfa.decisionNFAStartState.ast.getLine();
|
||||
this.charPosition = dfa.decisionNFAStartState.ast.getCharPositionInLine();
|
||||
|
||||
Map<String, Object> info = new HashMap<String, Object>();
|
||||
info.put("dfa", dfa);
|
||||
info.put("alts", conflictingAlts);
|
||||
args = new Object[] {info}; // pass in a map so we can name the args instead of arg1, arg2, ...
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue