﻿/* 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 "NoViableAltException.h"
#include "misc/IntervalSet.h"
#include "atn/ParserATNSimulator.h"
#include "InputMismatchException.h"
#include "FailedPredicateException.h"
#include "ParserRuleContext.h"
#include "atn/RuleTransition.h"
#include "atn/ATN.h"
#include "atn/ATNState.h"
#include "Parser.h"
#include "CommonToken.h"
#include "Vocabulary.h"
#include "support/StringUtils.h"

#include "DefaultErrorStrategy.h"

using namespace antlr4;
using namespace antlr4::atn;

using namespace antlrcpp;

DefaultErrorStrategy::DefaultErrorStrategy() {
  InitializeInstanceFields();
}

DefaultErrorStrategy::~DefaultErrorStrategy() {
}

void DefaultErrorStrategy::reset(Parser *recognizer) {
  _errorSymbols.clear();
  endErrorCondition(recognizer);
}

void DefaultErrorStrategy::beginErrorCondition(Parser * /*recognizer*/) {
  errorRecoveryMode = true;
}

bool DefaultErrorStrategy::inErrorRecoveryMode(Parser * /*recognizer*/) {
  return errorRecoveryMode;
}

void DefaultErrorStrategy::endErrorCondition(Parser * /*recognizer*/) {
  errorRecoveryMode = false;
  lastErrorIndex = -1;
}

void DefaultErrorStrategy::reportMatch(Parser *recognizer) {
  endErrorCondition(recognizer);
}

void DefaultErrorStrategy::reportError(Parser *recognizer, const RecognitionException &e) {
  // If we've already reported an error and have not matched a token
  // yet successfully, don't report any errors.
  if (inErrorRecoveryMode(recognizer)) {
    return; // don't report spurious errors
  }

  beginErrorCondition(recognizer);
  if (is<const NoViableAltException *>(&e)) {
    reportNoViableAlternative(recognizer, static_cast<const NoViableAltException &>(e));
  } else if (is<const InputMismatchException *>(&e)) {
    reportInputMismatch(recognizer, static_cast<const InputMismatchException &>(e));
  } else if (is<const FailedPredicateException *>(&e)) {
    reportFailedPredicate(recognizer, static_cast<const FailedPredicateException &>(e));
  } else if (is<const RecognitionException *>(&e)) {
    recognizer->notifyErrorListeners(e.getOffendingToken(), e.what(), std::current_exception());
  }
}

void DefaultErrorStrategy::recover(Parser *recognizer, std::exception_ptr /*e*/) {
  if (lastErrorIndex == static_cast<int>(recognizer->getInputStream()->index()) &&
      lastErrorStates.contains(recognizer->getState())) {

    // uh oh, another error at same token index and previously-visited
    // state in ATN; must be a case where LT(1) is in the recovery
    // token set so nothing got consumed. Consume a single token
    // at least to prevent an infinite loop; this is a failsafe.
    recognizer->consume();
  }
  lastErrorIndex = static_cast<int>(recognizer->getInputStream()->index());
  lastErrorStates.add(recognizer->getState());
  misc::IntervalSet followSet = getErrorRecoverySet(recognizer);
  consumeUntil(recognizer, followSet);
}

void DefaultErrorStrategy::sync(Parser *recognizer) {
  atn::ATNState *s = recognizer->getInterpreter<atn::ATNSimulator>()->atn.states[recognizer->getState()];

  // If already recovering, don't try to sync
  if (inErrorRecoveryMode(recognizer)) {
    return;
  }

  TokenStream *tokens = recognizer->getTokenStream();
  size_t la = tokens->LA(1);

  // try cheaper subset first; might get lucky. seems to shave a wee bit off
  auto nextTokens = recognizer->getATN().nextTokens(s);
  if (nextTokens.contains(Token::EPSILON) || nextTokens.contains(la)) {
    return;
  }

  switch (s->getStateType()) {
    case atn::ATNState::BLOCK_START:
    case atn::ATNState::STAR_BLOCK_START:
    case atn::ATNState::PLUS_BLOCK_START:
    case atn::ATNState::STAR_LOOP_ENTRY:
      // report error and recover if possible
      if (singleTokenDeletion(recognizer) != nullptr) {
        return;
      }

      throw InputMismatchException(recognizer);

    case atn::ATNState::PLUS_LOOP_BACK:
    case atn::ATNState::STAR_LOOP_BACK: {
      reportUnwantedToken(recognizer);
      misc::IntervalSet expecting = recognizer->getExpectedTokens();
      misc::IntervalSet whatFollowsLoopIterationOrRule = expecting.Or(getErrorRecoverySet(recognizer));
      consumeUntil(recognizer, whatFollowsLoopIterationOrRule);
    }
      break;

    default:
      // do nothing if we can't identify the exact kind of ATN state
      break;
  }
}

void DefaultErrorStrategy::reportNoViableAlternative(Parser *recognizer, const NoViableAltException &e) {
  TokenStream *tokens = recognizer->getTokenStream();
  std::string input;
  if (tokens != nullptr) {
    if (e.getStartToken()->getType() == Token::EOF) {
      input = "<EOF>";
    } else {
      input = tokens->getText(e.getStartToken(), e.getOffendingToken());
    }
  } else {
    input = "<unknown input>";
  }
  std::string msg = "no viable alternative at input " + escapeWSAndQuote(input);
  recognizer->notifyErrorListeners(e.getOffendingToken(), msg, std::make_exception_ptr(e));
}

void DefaultErrorStrategy::reportInputMismatch(Parser *recognizer, const InputMismatchException &e) {
  std::string msg = "mismatched input " + getTokenErrorDisplay(e.getOffendingToken()) +
  " expecting " + e.getExpectedTokens().toString(recognizer->getVocabulary());
  recognizer->notifyErrorListeners(e.getOffendingToken(), msg, std::make_exception_ptr(e));
}

void DefaultErrorStrategy::reportFailedPredicate(Parser *recognizer, const FailedPredicateException &e) {
  const std::string& ruleName = recognizer->getRuleNames()[recognizer->getContext()->getRuleIndex()];
  std::string msg = "rule " + ruleName + " " + e.what();
  recognizer->notifyErrorListeners(e.getOffendingToken(), msg, std::make_exception_ptr(e));
}

void DefaultErrorStrategy::reportUnwantedToken(Parser *recognizer) {
  if (inErrorRecoveryMode(recognizer)) {
    return;
  }

  beginErrorCondition(recognizer);

  Token *t = recognizer->getCurrentToken();
  std::string tokenName = getTokenErrorDisplay(t);
  misc::IntervalSet expecting = getExpectedTokens(recognizer);

  std::string msg = "extraneous input " + tokenName + " expecting " + expecting.toString(recognizer->getVocabulary());
  recognizer->notifyErrorListeners(t, msg, nullptr);
}

void DefaultErrorStrategy::reportMissingToken(Parser *recognizer) {
  if (inErrorRecoveryMode(recognizer)) {
    return;
  }

  beginErrorCondition(recognizer);

  Token *t = recognizer->getCurrentToken();
  misc::IntervalSet expecting = getExpectedTokens(recognizer);
  std::string expectedText = expecting.toString(recognizer->getVocabulary());
  std::string msg = "missing " + expectedText + " at " + getTokenErrorDisplay(t);

  recognizer->notifyErrorListeners(t, msg, nullptr);
}

Token* DefaultErrorStrategy::recoverInline(Parser *recognizer) {
  // Single token deletion.
  Token *matchedSymbol = singleTokenDeletion(recognizer);
  if (matchedSymbol) {
    // We have deleted the extra token.
    // Now, move past ttype token as if all were ok.
    recognizer->consume();
    return matchedSymbol;
  }

  // Single token insertion.
  if (singleTokenInsertion(recognizer)) {
    return getMissingSymbol(recognizer);
  }

  // Even that didn't work; must throw the exception.
  throw InputMismatchException(recognizer);
}

bool DefaultErrorStrategy::singleTokenInsertion(Parser *recognizer) {
  ssize_t currentSymbolType = recognizer->getInputStream()->LA(1);

  // if current token is consistent with what could come after current
  // ATN state, then we know we're missing a token; error recovery
  // is free to conjure up and insert the missing token
  atn::ATNState *currentState = recognizer->getInterpreter<atn::ATNSimulator>()->atn.states[recognizer->getState()];
  atn::ATNState *next = currentState->transitions[0]->target;
  const atn::ATN &atn = recognizer->getInterpreter<atn::ATNSimulator>()->atn;
  misc::IntervalSet expectingAtLL2 = atn.nextTokens(next, recognizer->getContext());
  if (expectingAtLL2.contains(currentSymbolType)) {
    reportMissingToken(recognizer);
    return true;
  }
  return false;
}

Token* DefaultErrorStrategy::singleTokenDeletion(Parser *recognizer) {
  size_t nextTokenType = recognizer->getInputStream()->LA(2);
  misc::IntervalSet expecting = getExpectedTokens(recognizer);
  if (expecting.contains(nextTokenType)) {
    reportUnwantedToken(recognizer);
    recognizer->consume(); // simply delete extra token
                           // we want to return the token we're actually matching
    Token *matchedSymbol = recognizer->getCurrentToken();
    reportMatch(recognizer); // we know current token is correct
    return matchedSymbol;
  }
  return nullptr;
}

Token* DefaultErrorStrategy::getMissingSymbol(Parser *recognizer) {
  Token *currentSymbol = recognizer->getCurrentToken();
  misc::IntervalSet expecting = getExpectedTokens(recognizer);
  size_t expectedTokenType = expecting.getMinElement(); // get any element
  std::string tokenText;
  if (expectedTokenType == Token::EOF) {
    tokenText = "<missing EOF>";
  } else {
    tokenText = "<missing " + recognizer->getVocabulary().getDisplayName(expectedTokenType) + ">";
  }
  Token *current = currentSymbol;
  Token *lookback = recognizer->getTokenStream()->LT(-1);
  if (current->getType() == Token::EOF && lookback != nullptr) {
    current = lookback;
  }

  _errorSymbols.push_back(recognizer->getTokenFactory()->create(
    { current->getTokenSource(), current->getTokenSource()->getInputStream() },
    expectedTokenType, tokenText, Token::DEFAULT_CHANNEL, INVALID_INDEX, INVALID_INDEX,
    current->getLine(), current->getCharPositionInLine()));

  return _errorSymbols.back().get();
}

misc::IntervalSet DefaultErrorStrategy::getExpectedTokens(Parser *recognizer) {
  return recognizer->getExpectedTokens();
}

std::string DefaultErrorStrategy::getTokenErrorDisplay(Token *t) {
  if (t == nullptr) {
    return "<no Token>";
  }
  std::string s = getSymbolText(t);
  if (s == "") {
    if (getSymbolType(t) == Token::EOF) {
      s = "<EOF>";
    } else {
      s = "<" + std::to_string(getSymbolType(t)) + ">";
    }
  }
  return escapeWSAndQuote(s);
}

std::string DefaultErrorStrategy::getSymbolText(Token *symbol) {
  return symbol->getText();
}

size_t DefaultErrorStrategy::getSymbolType(Token *symbol) {
  return symbol->getType();
}

std::string DefaultErrorStrategy::escapeWSAndQuote(const std::string &s) const {
  std::string result = s;
  antlrcpp::replaceAll(result, "\n", "\\n");
  antlrcpp::replaceAll(result, "\r","\\r");
  antlrcpp::replaceAll(result, "\t","\\t");
  return "'" + result + "'";
}

misc::IntervalSet DefaultErrorStrategy::getErrorRecoverySet(Parser *recognizer) {
  const atn::ATN &atn = recognizer->getInterpreter<atn::ATNSimulator>()->atn;
  RuleContext *ctx = recognizer->getContext();
  misc::IntervalSet recoverSet;
  while (ctx->invokingState != ATNState::INVALID_STATE_NUMBER) {
    // compute what follows who invoked us
    atn::ATNState *invokingState = atn.states[ctx->invokingState];
    atn::RuleTransition *rt = dynamic_cast<atn::RuleTransition*>(invokingState->transitions[0]);
    misc::IntervalSet follow = atn.nextTokens(rt->followState);
    recoverSet.addAll(follow);

    if (ctx->parent == nullptr)
      break;
    ctx = static_cast<RuleContext *>(ctx->parent);
  }
  recoverSet.remove(Token::EPSILON);

  return recoverSet;
}

void DefaultErrorStrategy::consumeUntil(Parser *recognizer, const misc::IntervalSet &set) {
  size_t ttype = recognizer->getInputStream()->LA(1);
  while (ttype != Token::EOF && !set.contains(ttype)) {
    recognizer->consume();
    ttype = recognizer->getInputStream()->LA(1);
  }
}

void DefaultErrorStrategy::InitializeInstanceFields() {
  errorRecoveryMode = false;
  lastErrorIndex = -1;
}
