commonMain.org.antlr.v4.kotlinruntime.VocabularyImpl.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of antlr-kotlin-runtime-jvm Show documentation
Show all versions of antlr-kotlin-runtime-jvm Show documentation
Kotlin multiplatform port of ANTLR
/*
* 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.
*/
package org.antlr.v4.kotlinruntime
import com.strumenta.kotlinmultiplatform.Math
import com.strumenta.kotlinmultiplatform.isCharUppercase
/**
* This class provides a default implementation of the [Vocabulary]
* interface.
*
* @author Sam Harwell
*/
class VocabularyImpl
/**
* Constructs a new instance of [VocabularyImpl] from the specified
* literal, symbolic, and display token names.
*
* @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].
*
* @see .getLiteralName
* @see .getSymbolicName
* @see .getDisplayName
*/
constructor(literalNames: Array?, symbolicNames: Array?, displayNames: Array? = null) : Vocabulary {
private val literalNames: Array
private val symbolicNames: Array
private val displayNames: Array
override val maxTokenType: Int
init {
this.literalNames = literalNames ?: EMPTY_NAMES
this.symbolicNames = symbolicNames ?: EMPTY_NAMES
this.displayNames = displayNames ?: EMPTY_NAMES
// See note here on -1 part: https://github.com/antlr/antlr4/pull/1146
this.maxTokenType = Math.max(this.displayNames.size,
Math.max(this.literalNames.size, this.symbolicNames.size)) - 1
}
override fun getLiteralName(tokenType: Int): String? {
return if (tokenType >= 0 && tokenType < literalNames.size) {
literalNames[tokenType]
} else null
}
override fun getSymbolicName(tokenType: Int): String? {
if (tokenType >= 0 && tokenType < symbolicNames.size) {
return symbolicNames[tokenType]
}
return if (tokenType == Token.EOF) {
"EOF"
} else null
}
override fun getDisplayName(tokenType: Int): String {
if (tokenType >= 0 && tokenType < displayNames.size) {
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()
}
companion object {
private val EMPTY_NAMES = arrayOfNulls(0)
/**
* Gets 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].
*/
val EMPTY_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.
*/
fun fromTokenNames(tokenNames: Array?): Vocabulary {
if (tokenNames == null || tokenNames.isEmpty()) {
return EMPTY_VOCABULARY
}
val literalNames: Array = tokenNames.copyOf(tokenNames.size)
val symbolicNames: Array = tokenNames.copyOf(tokenNames.size)
for (i in tokenNames.indices) {
val tokenName = tokenNames[i] ?: continue
if (!tokenName.isEmpty()) {
val firstChar = tokenName[0]
if (firstChar == '\'') {
symbolicNames[i] = null
continue
} else if (isCharUppercase(firstChar)) {
literalNames[i] = null
continue
}
}
// wasn't a literal or symbolic name
literalNames[i] = null
symbolicNames[i] = null
}
return VocabularyImpl(literalNames, symbolicNames, tokenNames)
}
}
}