1/* 2 * [The "BSD license"] 3 * Copyright (c) 2010 Terence Parr 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28package org.antlr.tool; 29 30import org.antlr.analysis.DFAState; 31import org.antlr.analysis.DecisionProbe; 32import org.antlr.analysis.NFAState; 33import org.antlr.misc.Utils; 34import org.stringtemplate.v4.ST; 35 36import java.util.Iterator; 37import java.util.List; 38import java.util.Set; 39 40/** Reports a potential parsing issue with a decision; the decision is 41 * nondeterministic in some way. 42 */ 43public class GrammarNonDeterminismMessage extends Message { 44 public DecisionProbe probe; 45 public DFAState problemState; 46 47 public GrammarNonDeterminismMessage(DecisionProbe probe, 48 DFAState problemState) 49 { 50 super(ErrorManager.MSG_GRAMMAR_NONDETERMINISM); 51 this.probe = probe; 52 this.problemState = problemState; 53 // flip msg ID if alts are actually token refs in Tokens rule 54 if ( probe.dfa.isTokensRuleDecision() ) { 55 setMessageID(ErrorManager.MSG_TOKEN_NONDETERMINISM); 56 } 57 } 58 59 public String toString() { 60 GrammarAST decisionASTNode = probe.dfa.getDecisionASTNode(); 61 line = decisionASTNode.getLine(); 62 column = decisionASTNode.getCharPositionInLine(); 63 String fileName = probe.dfa.nfa.grammar.getFileName(); 64 if ( fileName!=null ) { 65 file = fileName; 66 } 67 68 ST st = getMessageTemplate(); 69 // Now fill template with information about problemState 70 List labels = probe.getSampleNonDeterministicInputSequence(problemState); 71 String input = probe.getInputSequenceDisplay(labels); 72 st.add("input", input); 73 74 if ( probe.dfa.isTokensRuleDecision() ) { 75 Set disabledAlts = probe.getDisabledAlternatives(problemState); 76 for (Iterator it = disabledAlts.iterator(); it.hasNext();) { 77 Integer altI = (Integer) it.next(); 78 String tokenName = 79 probe.getTokenNameForTokensRuleAlt(altI.intValue()); 80 // reset the line/col to the token definition (pick last one) 81 NFAState ruleStart = 82 probe.dfa.nfa.grammar.getRuleStartState(tokenName); 83 line = ruleStart.associatedASTNode.getLine(); 84 column = ruleStart.associatedASTNode.getCharPositionInLine(); 85 st.add("disabled", tokenName); 86 } 87 } 88 else { 89 st.add("disabled", probe.getDisabledAlternatives(problemState)); 90 } 91 92 List nondetAlts = probe.getNonDeterministicAltsForState(problemState); 93 NFAState nfaStart = probe.dfa.getNFADecisionStartState(); 94 // all state paths have to begin with same NFA state 95 int firstAlt = 0; 96 if ( nondetAlts!=null ) { 97 for (Iterator iter = nondetAlts.iterator(); iter.hasNext();) { 98 Integer displayAltI = (Integer) iter.next(); 99 if ( DecisionProbe.verbose ) { 100 int tracePathAlt = 101 nfaStart.translateDisplayAltToWalkAlt(displayAltI.intValue()); 102 if ( firstAlt == 0 ) { 103 firstAlt = tracePathAlt; 104 } 105 List path = 106 probe.getNFAPathStatesForAlt(firstAlt, 107 tracePathAlt, 108 labels); 109 st.addAggr("paths.{alt, states}", displayAltI, path); 110 } 111 else { 112 if ( probe.dfa.isTokensRuleDecision() ) { 113 // alts are token rules, convert to the names instead of numbers 114 String tokenName = 115 probe.getTokenNameForTokensRuleAlt(displayAltI.intValue()); 116 st.add("conflictingTokens", tokenName); 117 } 118 else { 119 st.add("conflictingAlts", displayAltI); 120 } 121 } 122 } 123 } 124 st.add("hasPredicateBlockedByAction", problemState.dfa.hasPredicateBlockedByAction); 125 return super.toString(st); 126 } 127 128} 129