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: 0.0.18
Show newest version
/*
 * 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)
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy