All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.org.antlr.v4.kotlinruntime.Recognizer.kt Maven / Gradle / Ivy

// Copyright 2017-present Strumenta and contributors, licensed under Apache 2.0.
// Copyright 2024-present Strumenta and contributors, licensed under BSD 3-Clause.

package org.antlr.v4.kotlinruntime

import com.strumenta.antlrkotlin.runtime.CopyOnWriteArrayList
import com.strumenta.antlrkotlin.runtime.WeakHashMap
import com.strumenta.antlrkotlin.runtime.synchronized
import org.antlr.v4.kotlinruntime.atn.ATN
import org.antlr.v4.kotlinruntime.atn.ATNSimulator
import org.antlr.v4.kotlinruntime.atn.DecisionInfo
import org.antlr.v4.kotlinruntime.atn.ParseInfo
import org.antlr.v4.kotlinruntime.misc.Utils

@Suppress("MemberVisibilityCanBePrivate")
public abstract class Recognizer {
  public companion object {
    public const val EOF: Int = -1

    private val tokenTypeMapCache = WeakHashMap>()
    private val ruleIndexMapCache = WeakHashMap, Map>()
  }

  private val _listeners = CopyOnWriteArrayList(listOf(ConsoleErrorListener.INSTANCE))

  /**
   * Indicate that the recognizer has changed internal state that is
   * consistent with the ATN state passed in. This way we always know
   * where we are in the ATN as the parser goes along. The rule
   * context objects form a stack that lets us see the stack of
   * invoking rules. Combine this and we have complete ATN
   * configuration information.
   */
  public var state: Int = -1

  /**
   * The ATN interpreter used by the recognizer for prediction.
   */
  public abstract var interpreter: ATNInterpreter

  /**
   * Used to print out token names like ID during debugging and error reporting.
   *
   * The generated parsers implement a method that overrides this to point
   * to their `Array` [tokenNames].
   */
  @Deprecated("Use vocabulary instead", ReplaceWith("vocabulary"))
  public abstract val tokenNames: Array

  public abstract val ruleNames: Array

  /**
   * The vocabulary used by the recognizer.
   */
  @Suppress("DEPRECATION")
  public open val vocabulary: Vocabulary
    get() = VocabularyImpl.fromTokenNames(tokenNames)

  /**
   * Get a map from token names to token types.
   *
   * Used for `XPath` and tree pattern compilation.
   */
  public val tokenTypeMap: Map
    get() {
      val tempVocabulary = vocabulary

      synchronized(tokenTypeMapCache) {
        var result = tokenTypeMapCache[tempVocabulary]

        if (result == null) {
          val tmp = HashMap()

          for (i in 0..atn.maxTokenType) {
            val literalName = tempVocabulary.getLiteralName(i)

            if (literalName != null) {
              tmp[literalName] = i
            }

            val symbolicName = tempVocabulary.getSymbolicName(i)

            if (symbolicName != null) {
              tmp[symbolicName] = i
            }
          }

          tmp["EOF"] = Token.EOF
          result = tmp
          tokenTypeMapCache[tempVocabulary] = result
        }

        return result
      }
    }

  /**
   * Get a map from rule names to rule indexes.
   *
   * Used for `XPath` and tree pattern compilation.
   */
  public val ruleIndexMap: Map
    get() {
      val ruleNames = ruleNames

      synchronized(ruleIndexMapCache) {
        var result = ruleIndexMapCache[ruleNames]

        if (result == null) {
          result = Utils.toMap(ruleNames)
          ruleIndexMapCache[ruleNames] = result
        }

        return result
      }
    }

  /**
   * If this recognizer was generated, it will have a serialized ATN
   * representation of the grammar.
   *
   * For interpreters, we don't know their serialized ATN despite having
   * created the interpreter from it.
   */
  public open val serializedATN: String
    get() = throw UnsupportedOperationException("there is no serialized ATN")

  /**
   * For debugging and other purposes, might want the grammar name.
   *
   * Have ANTLR generate an implementation for this method.
   */
  public abstract val grammarFileName: String

  /**
   * The [ATN] used by the recognizer for prediction.
   */
  public abstract val atn: ATN

  /**
   * If profiling during the parse/lex, this will return [DecisionInfo] records
   * for each decision in recognizer in a [ParseInfo] object.
   *
   * @since 4.3
   */
  public open val parseInfo: ParseInfo?
    get() = null

  public val errorListeners: List
    get() = _listeners

  public val errorListenerDispatch: ANTLRErrorListener
    get() = ProxyErrorListener(errorListeners)

  public abstract var tokenFactory: TokenFactory<*>

  public fun getTokenType(tokenName: String): Int {
    val ttype = tokenTypeMap[tokenName]
    return ttype ?: Token.INVALID_TYPE
  }

  /**
   * What is the error header, normally line/character position information?
   */
  public fun getErrorHeader(e: RecognitionException): String {
    val offendingToken = e.offendingToken!!
    val line = offendingToken.line
    val charPositionInLine = offendingToken.charPositionInLine
    return "line $line:$charPositionInLine"
  }

  /**
   * How should a token be displayed in an error message?
   *
   * The default is to display just the text, but during development you might
   * want to have a lot of information spit out. Override in that case
   * to use `t.toString()` (which, for [CommonToken], dumps everything about
   * the token).
   *
   * This is better than forcing you to override a method in your token
   * objects because you don't have to go modify your lexer so that it
   * creates a new Java type.
   *
   * **Deprecated**: this method is not called by the ANTLR 4 Runtime.
   * Specific implementations of [ANTLRErrorStrategy] may provide a similar
   * feature when necessary. For example, see [DefaultErrorStrategy.getTokenErrorDisplay].
   */
  @Deprecated("This method is not called by the ANTLR 4 Runtime")
  public fun getTokenErrorDisplay(t: Token?): String {
    if (t == null) {
      return ""
    }

    var s = t.text

    if (s == null) {
      s = if (t.type == Token.EOF) {
        ""
      } else {
        "<" + t.type + ">"
      }
    }

    s = s.replace("\n", "\\n")
    s = s.replace("\r", "\\r")
    s = s.replace("\t", "\\t")
    return "'$s'"
  }

  public fun addErrorListener(listener: ANTLRErrorListener) {
    _listeners.add(listener)
  }

  public fun removeErrorListener(listener: ANTLRErrorListener) {
    _listeners.remove(listener)
  }

  public fun removeErrorListeners() {
    _listeners.clear()
  }

  // Subclass needs to override these if there are sempreds or actions
  // that the ATN interp needs to execute
  public open fun sempred(
    @Suppress("LocalVariableName") _localctx: RuleContext?,
    ruleIndex: Int,
    predIndex: Int,
  ): Boolean =
    true

  public open fun precpred(localctx: RuleContext, precedence: Int): Boolean =
    true

  public open fun action(
    @Suppress("LocalVariableName") _localctx: RuleContext?,
    ruleIndex: Int,
    actionIndex: Int,
  ) {
    // Noop
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy