/*
* 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.runtime;
import java.util.Arrays;
This class provides a default implementation of the Vocabulary
interface. Author: Sam Harwell
/**
* This class provides a default implementation of the {@link Vocabulary}
* interface.
*
* @author Sam Harwell
*/
public class VocabularyImpl implements Vocabulary {
private static final String[] EMPTY_NAMES = new String[0];
Gets an empty Vocabulary
instance. No literal or symbol names are assigned to token types, so getDisplayName(int)
returns the numeric value for all tokens except Token.EOF
.
/**
* Gets an empty {@link Vocabulary} instance.
*
* <p>
* No literal or symbol names are assigned to token types, so
* {@link #getDisplayName(int)} returns the numeric value for all tokens
* except {@link Token#EOF}.</p>
*/
public static final VocabularyImpl EMPTY_VOCABULARY = new VocabularyImpl(EMPTY_NAMES, EMPTY_NAMES, EMPTY_NAMES);
private final String[] literalNames;
private final String[] symbolicNames;
private final String[] displayNames;
private final int maxTokenType;
Constructs a new instance of VocabularyImpl
from the specified literal and symbolic token names. Params: - literalNames – The literal names assigned to tokens, or
null
if no literal names are assigned. - symbolicNames – The symbolic names assigned to tokens, or
null
if no symbolic names are assigned.
See Also:
/**
* Constructs a new instance of {@link VocabularyImpl} from the specified
* literal and symbolic token names.
*
* @param literalNames The literal names assigned to tokens, or {@code null}
* if no literal names are assigned.
* @param symbolicNames The symbolic names assigned to tokens, or
* {@code null} if no symbolic names are assigned.
*
* @see #getLiteralName(int)
* @see #getSymbolicName(int)
*/
public VocabularyImpl(String[] literalNames, String[] symbolicNames) {
this(literalNames, symbolicNames, null);
}
Constructs a new instance of VocabularyImpl
from the specified literal, symbolic, and display token names. Params: - literalNames – The literal names assigned to tokens, or
null
if no literal names are assigned. - symbolicNames – The symbolic names assigned to tokens, or
null
if no symbolic names are assigned. - 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(int)
.
See Also:
/**
* Constructs a new instance of {@link VocabularyImpl} from the specified
* literal, symbolic, and display token names.
*
* @param literalNames The literal names assigned to tokens, or {@code null}
* if no literal names are assigned.
* @param symbolicNames The symbolic names assigned to tokens, or
* {@code null} if no symbolic names are assigned.
* @param displayNames The display names assigned to tokens, or {@code null}
* to use the values in {@code literalNames} and {@code symbolicNames} as
* the source of display names, as described in
* {@link #getDisplayName(int)}.
*
* @see #getLiteralName(int)
* @see #getSymbolicName(int)
* @see #getDisplayName(int)
*/
public VocabularyImpl(String[] literalNames, String[] symbolicNames, String[] displayNames) {
this.literalNames = literalNames != null ? literalNames : EMPTY_NAMES;
this.symbolicNames = symbolicNames != null ? symbolicNames : EMPTY_NAMES;
this.displayNames = displayNames != null ? displayNames : EMPTY_NAMES;
// See note here on -1 part: https://github.com/antlr/antlr4/pull/1146
this.maxTokenType =
Math.max(this.displayNames.length,
Math.max(this.literalNames.length, this.symbolicNames.length)) - 1;
}
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(int)
and getSymbolicName(int)
, and the value from tokenNames
for the display names.
Params: - tokenNames – The token names, or
null
if no token names are available.
Returns: A Vocabulary
instance which uses tokenNames
for the display names of tokens.
/**
* Returns a {@link VocabularyImpl} instance from the specified set of token
* names. This method acts as a compatibility layer for the single
* {@code tokenNames} array generated by previous releases of ANTLR.
*
* <p>The resulting vocabulary instance returns {@code null} for
* {@link #getLiteralName(int)} and {@link #getSymbolicName(int)}, and the
* value from {@code tokenNames} for the display names.</p>
*
* @param tokenNames The token names, or {@code null} if no token names are
* available.
* @return A {@link Vocabulary} instance which uses {@code tokenNames} for
* the display names of tokens.
*/
public static Vocabulary fromTokenNames(String[] tokenNames) {
if (tokenNames == null || tokenNames.length == 0) {
return EMPTY_VOCABULARY;
}
String[] literalNames = Arrays.copyOf(tokenNames, tokenNames.length);
String[] symbolicNames = Arrays.copyOf(tokenNames, tokenNames.length);
for (int i = 0; i < tokenNames.length; i++) {
String tokenName = tokenNames[i];
if (tokenName == null) {
continue;
}
if (!tokenName.isEmpty()) {
char firstChar = tokenName.charAt(0);
if (firstChar == '\'') {
symbolicNames[i] = null;
continue;
}
else if (Character.isUpperCase(firstChar)) {
literalNames[i] = null;
continue;
}
}
// wasn't a literal or symbolic name
literalNames[i] = null;
symbolicNames[i] = null;
}
return new VocabularyImpl(literalNames, symbolicNames, tokenNames);
}
@Override
public int getMaxTokenType() {
return maxTokenType;
}
@Override
public String getLiteralName(int tokenType) {
if (tokenType >= 0 && tokenType < literalNames.length) {
return literalNames[tokenType];
}
return null;
}
@Override
public String getSymbolicName(int tokenType) {
if (tokenType >= 0 && tokenType < symbolicNames.length) {
return symbolicNames[tokenType];
}
if (tokenType == Token.EOF) {
return "EOF";
}
return null;
}
@Override
public String getDisplayName(int tokenType) {
if (tokenType >= 0 && tokenType < displayNames.length) {
String displayName = displayNames[tokenType];
if (displayName != null) {
return displayName;
}
}
String literalName = getLiteralName(tokenType);
if (literalName != null) {
return literalName;
}
String symbolicName = getSymbolicName(tokenType);
if (symbolicName != null) {
return symbolicName;
}
return Integer.toString(tokenType);
}
}