001: /*
002: [The "BSD licence"]
003: Copyright (c) 2005-2006 Terence Parr
004: All rights reserved.
005:
006: Redistribution and use in source and binary forms, with or without
007: modification, are permitted provided that the following conditions
008: are met:
009: 1. Redistributions of source code must retain the above copyright
010: notice, this list of conditions and the following disclaimer.
011: 2. Redistributions in binary form must reproduce the above copyright
012: notice, this list of conditions and the following disclaimer in the
013: documentation and/or other materials provided with the distribution.
014: 3. The name of the author may not be used to endorse or promote products
015: derived from this software without specific prior written permission.
016:
017: THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
018: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
019: OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
020: IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
021: INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
022: NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
023: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
024: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
025: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
026: THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027: */
028: package org.antlr.tool;
029:
030: import org.antlr.analysis.DFAState;
031: import org.antlr.analysis.DecisionProbe;
032: import org.antlr.analysis.NFAState;
033: import org.antlr.stringtemplate.StringTemplate;
034:
035: import java.util.Iterator;
036: import java.util.List;
037: import java.util.Set;
038:
039: /** Reports a potential parsing issue with a decision; the decision is
040: * nondeterministic in some way.
041: */
042: public class GrammarNonDeterminismMessage extends Message {
043: public DecisionProbe probe;
044: public DFAState problemState;
045:
046: public GrammarNonDeterminismMessage(DecisionProbe probe,
047: DFAState problemState) {
048: super (ErrorManager.MSG_GRAMMAR_NONDETERMINISM);
049: this .probe = probe;
050: this .problemState = problemState;
051: // flip msg ID if alts are actually token refs in Tokens rule
052: if (probe.dfa.isTokensRuleDecision()) {
053: setMessageID(ErrorManager.MSG_TOKEN_NONDETERMINISM);
054: }
055: }
056:
057: public String toString() {
058: GrammarAST decisionASTNode = probe.dfa.getDecisionASTNode();
059: line = decisionASTNode.getLine();
060: column = decisionASTNode.getColumn();
061: String fileName = probe.dfa.nfa.grammar.getFileName();
062: if (fileName != null) {
063: file = fileName;
064: }
065:
066: StringTemplate st = getMessageTemplate();
067: // Now fill template with information about problemState
068: List labels = probe
069: .getSampleNonDeterministicInputSequence(problemState);
070: String input = probe.getInputSequenceDisplay(labels);
071: st.setAttribute("input", input);
072:
073: if (probe.dfa.isTokensRuleDecision()) {
074: Set disabledAlts = probe
075: .getDisabledAlternatives(problemState);
076: for (Iterator it = disabledAlts.iterator(); it.hasNext();) {
077: Integer altI = (Integer) it.next();
078: String tokenName = probe
079: .getTokenNameForTokensRuleAlt(altI.intValue());
080: // reset the line/col to the token definition (pick last one)
081: NFAState ruleStart = probe.dfa.nfa.grammar
082: .getRuleStartState(tokenName);
083: line = ruleStart.getAssociatedASTNode().getLine();
084: column = ruleStart.getAssociatedASTNode().getColumn();
085: st.setAttribute("disabled", tokenName);
086: }
087: } else {
088: st.setAttribute("disabled", probe
089: .getDisabledAlternatives(problemState));
090: }
091:
092: List nondetAlts = probe
093: .getNonDeterministicAltsForState(problemState);
094: NFAState nfaStart = probe.dfa.getNFADecisionStartState();
095: // all state paths have to begin with same NFA state
096: int firstAlt = 0;
097: if (nondetAlts != null) {
098: for (Iterator iter = nondetAlts.iterator(); iter.hasNext();) {
099: Integer displayAltI = (Integer) iter.next();
100: if (DecisionProbe.verbose) {
101: int tracePathAlt = nfaStart
102: .translateDisplayAltToWalkAlt(probe.dfa,
103: displayAltI.intValue());
104: if (firstAlt == 0) {
105: firstAlt = tracePathAlt;
106: }
107: List path = probe.getNFAPathStatesForAlt(firstAlt,
108: tracePathAlt, labels);
109: st.setAttribute("paths.{alt,states}", displayAltI,
110: path);
111: } else {
112: if (probe.dfa.isTokensRuleDecision()) {
113: // alts are token rules, convert to the names instead of numbers
114: String tokenName = probe
115: .getTokenNameForTokensRuleAlt(displayAltI
116: .intValue());
117: st.setAttribute("conflictingTokens", tokenName);
118: } else {
119: st.setAttribute("conflictingAlts", displayAltI);
120: }
121: }
122: }
123: }
124: return super.toString(st);
125: }
126:
127: }
|