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

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

There is a newer version: 1.0.1
Show newest version
// 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 kotlin.jvm.JvmField
import kotlin.math.max

/**
 * This class provides a default implementation of the [Vocabulary]
 * interface.
 *
 * @param literalNames The literal names assigned to tokens, or `null`
 *   if no literal names are assigned
 * @param symbolicNames The symbolic names assigned to tokens, or
 *   `null` if no symbolic names are assigned
 * @param displayNames The display names assigned to tokens, or `null`
 *   to use the values in [literalNames] and [symbolicNames] as
 *   the source of display names, as described in [getDisplayName]
 *
 * @author Sam Harwell
 */
@Suppress("MemberVisibilityCanBePrivate")
public class VocabularyImpl(
  literalNames: Array?,
  symbolicNames: Array?,
  displayNames: Array? = null,
) : Vocabulary {
  public companion object {
    private val EMPTY_NAMES = arrayOfNulls(0)

    /**
     * An empty [Vocabulary] instance.
     *
     * No literal or symbol names are assigned to token types, so
     * [getDisplayName] returns the numeric value for all tokens
     * except [Token.EOF].
     */
    @JvmField
    public val EMPTY_VOCABULARY: Vocabulary = VocabularyImpl(EMPTY_NAMES, EMPTY_NAMES, EMPTY_NAMES)

    /**
     * Returns a [VocabularyImpl] instance from the specified set of token
     * names. This method acts as a compatibility layer for the single
     * [tokenNames] array generated by previous releases of ANTLR.
     *
     * The resulting vocabulary instance returns `null` for
     * [getLiteralName] and [getSymbolicName], and the
     * value from [tokenNames] for the display names.
     *
     * @param tokenNames The token names, or `null` if no token names are available
     * @return A [Vocabulary] instance which uses [tokenNames] for the display names of tokens
     */
    public fun fromTokenNames(tokenNames: Array?): Vocabulary {
      if (tokenNames.isNullOrEmpty()) {
        return EMPTY_VOCABULARY
      }

      val literalNames = tokenNames.copyOf(tokenNames.size)
      val symbolicNames = tokenNames.copyOf(tokenNames.size)

      for (i in tokenNames.indices) {
        val tokenName = tokenNames[i]

        if (tokenName.isNotEmpty()) {
          val firstChar = tokenName[0]

          if (firstChar == '\'') {
            symbolicNames[i] = null
            continue
          } else if (firstChar.isUpperCase()) {
            literalNames[i] = null
            continue
          }
        }

        // Wasn't a literal or symbolic name
        literalNames[i] = null
        symbolicNames[i] = null
      }

      @Suppress("UNCHECKED_CAST")
      return VocabularyImpl(literalNames, symbolicNames, tokenNames as Array)
    }
  }

  public val literalNames: Array = literalNames ?: EMPTY_NAMES
  public val symbolicNames: Array = symbolicNames ?: EMPTY_NAMES
  public val displayNames: Array = displayNames ?: EMPTY_NAMES

  // See note here on -1 part: https://github.com/antlr/antlr4/pull/1146
  override val maxTokenType: Int =
    max(this.displayNames.size, max(this.literalNames.size, this.symbolicNames.size)) - 1

  override fun getLiteralName(tokenType: Int): String? =
    if (tokenType in literalNames.indices) {
      literalNames[tokenType]
    } else {
      null
    }

  override fun getSymbolicName(tokenType: Int): String? {
    if (tokenType in symbolicNames.indices) {
      return symbolicNames[tokenType]
    }

    return if (tokenType == Token.EOF) "EOF" else null
  }

  override fun getDisplayName(tokenType: Int): String {
    if (tokenType in displayNames.indices) {
      val displayName = displayNames[tokenType]

      if (displayName != null) {
        return displayName
      }
    }

    val literalName = getLiteralName(tokenType)

    if (literalName != null) {
      return literalName
    }

    val symbolicName = getSymbolicName(tokenType)
    return symbolicName ?: tokenType.toString()
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy