/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. * Use of this file is governed by the BSD 3-clause license that * can be found in the LICENSE.txt file in the project root. */ #include "atn/PredictionContext.h" #include "atn/ATNConfig.h" #include "atn/ATNConfigSet.h" #include "Parser.h" #include "misc/Interval.h" #include "dfa/DFA.h" #include "DiagnosticErrorListener.h" using namespace antlr4; DiagnosticErrorListener::DiagnosticErrorListener() : DiagnosticErrorListener(true) { } DiagnosticErrorListener::DiagnosticErrorListener(bool exactOnly_) : exactOnly(exactOnly_) { } void DiagnosticErrorListener::reportAmbiguity(Parser *recognizer, const dfa::DFA &dfa, size_t startIndex, size_t stopIndex, bool exact, const antlrcpp::BitSet &ambigAlts, atn::ATNConfigSet *configs) { if (exactOnly && !exact) { return; } std::string decision = getDecisionDescription(recognizer, dfa); antlrcpp::BitSet conflictingAlts = getConflictingAlts(ambigAlts, configs); std::string text = recognizer->getTokenStream()->getText(misc::Interval(startIndex, stopIndex)); std::string message = "reportAmbiguity d=" + decision + ": ambigAlts=" + conflictingAlts.toString() + ", input='" + text + "'"; recognizer->notifyErrorListeners(message); } void DiagnosticErrorListener::reportAttemptingFullContext(Parser *recognizer, const dfa::DFA &dfa, size_t startIndex, size_t stopIndex, const antlrcpp::BitSet &/*conflictingAlts*/, atn::ATNConfigSet * /*configs*/) { std::string decision = getDecisionDescription(recognizer, dfa); std::string text = recognizer->getTokenStream()->getText(misc::Interval(startIndex, stopIndex)); std::string message = "reportAttemptingFullContext d=" + decision + ", input='" + text + "'"; recognizer->notifyErrorListeners(message); } void DiagnosticErrorListener::reportContextSensitivity(Parser *recognizer, const dfa::DFA &dfa, size_t startIndex, size_t stopIndex, size_t /*prediction*/, atn::ATNConfigSet * /*configs*/) { std::string decision = getDecisionDescription(recognizer, dfa); std::string text = recognizer->getTokenStream()->getText(misc::Interval(startIndex, stopIndex)); std::string message = "reportContextSensitivity d=" + decision + ", input='" + text + "'"; recognizer->notifyErrorListeners(message); } std::string DiagnosticErrorListener::getDecisionDescription(Parser *recognizer, const dfa::DFA &dfa) { size_t decision = dfa.decision; size_t ruleIndex = (reinterpret_cast(dfa.atnStartState))->ruleIndex; const std::vector& ruleNames = recognizer->getRuleNames(); if (ruleIndex == INVALID_INDEX || ruleIndex >= ruleNames.size()) { return std::to_string(decision); } std::string ruleName = ruleNames[ruleIndex]; if (ruleName == "" || ruleName.empty()) { return std::to_string(decision); } return std::to_string(decision) + " (" + ruleName + ")"; } antlrcpp::BitSet DiagnosticErrorListener::getConflictingAlts(const antlrcpp::BitSet &reportedAlts, atn::ATNConfigSet *configs) { if (reportedAlts.count() > 0) { // Not exactly like the original Java code, but this listener is only used // in the TestRig (where it never provides a good alt set), so it's probably ok so. return reportedAlts; } antlrcpp::BitSet result; for (auto &config : configs->configs) { result.set(config->alt); } return result; }