got line num etc... into ambig, unreachable warnings

[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 6760]
This commit is contained in:
parrt 2010-03-19 17:00:06 -08:00
parent d72dbb7af4
commit 2aa34fc41e
13 changed files with 879 additions and 740 deletions

View File

@ -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 ">
>>

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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

View File

@ -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
}
}

View File

@ -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); }
}

View File

@ -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 ) {

View File

@ -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),

View File

@ -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) {

View File

@ -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;
}

View File

@ -0,0 +1,4 @@
package org.antlr.v4.tool;
public class RecursionOverflowMessage extends Message {
}

View File

@ -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, ...
}
}