diff --git a/contributors.txt b/contributors.txt
index fb6040c785..2fab1c79dd 100644
--- a/contributors.txt
+++ b/contributors.txt
@@ -89,3 +89,4 @@ YYYY/MM/DD, github id, Full name, email
2015/12/23, pboyer, Peter Boyer, peter.b.boyer@gmail.com
2015/12/24, dtymon, David Tymon, david.tymon@gmail.com
2016/03/27, beardlybread, Bradley Steinbacher, bradley.j.steinbacher@gmail.com
+2016/03/29, msteiger, Martin Steiger, antlr@martin-steiger.de
diff --git a/runtime/Java/src/org/antlr/v4/runtime/Vocabulary.java b/runtime/Java/src/org/antlr/v4/runtime/Vocabulary.java
index 0b6386c8e8..46c4af1f7b 100644
--- a/runtime/Java/src/org/antlr/v4/runtime/Vocabulary.java
+++ b/runtime/Java/src/org/antlr/v4/runtime/Vocabulary.java
@@ -37,6 +37,14 @@
* @author Sam Harwell
*/
public interface Vocabulary {
+
+ /**
+ * Returns the highest token type value. It can be used to iterate from
+ * zero to that number, thus querying all stored entries.
+ * @return the highest token type value
+ */
+ int getMaxTokenType();
+
/**
* Gets the string literal associated with a token type. The string returned
* by this method, when not {@code null}, can be used unaltered in a parser
@@ -85,7 +93,7 @@ public interface Vocabulary {
*
*
* - Tokens created by lexer rules.
- * - Tokens defined in a {@code tokens{}} block in a lexer or parser
+ *
- Tokens defined in a
tokens{}
block in a lexer or parser
* grammar.
* - The implicitly defined {@code EOF} token, which has the token type
* {@link Token#EOF}.
diff --git a/runtime/Java/src/org/antlr/v4/runtime/VocabularyImpl.java b/runtime/Java/src/org/antlr/v4/runtime/VocabularyImpl.java
index ff5beefe24..75833ec2c9 100644
--- a/runtime/Java/src/org/antlr/v4/runtime/VocabularyImpl.java
+++ b/runtime/Java/src/org/antlr/v4/runtime/VocabularyImpl.java
@@ -57,6 +57,8 @@ public class VocabularyImpl implements Vocabulary {
private final String[] displayNames;
+ private final int maxTokenType;
+
/**
* Constructs a new instance of {@link VocabularyImpl} from the specified
* literal and symbolic token names.
@@ -94,6 +96,8 @@ public VocabularyImpl(String[] literalNames, String[] symbolicNames, String[] di
this.literalNames = literalNames != null ? literalNames : EMPTY_NAMES;
this.symbolicNames = symbolicNames != null ? symbolicNames : EMPTY_NAMES;
this.displayNames = displayNames != null ? displayNames : EMPTY_NAMES;
+ this.maxTokenType = Math.max(this.displayNames.length,
+ Math.max(this.literalNames.length, this.symbolicNames.length));
}
/**
@@ -143,6 +147,11 @@ else if (Character.isUpperCase(firstChar)) {
return new VocabularyImpl(literalNames, symbolicNames, tokenNames);
}
+ @Override
+ public int getMaxTokenType() {
+ return maxTokenType;
+ }
+
@Override
public String getLiteralName(int tokenType) {
if (tokenType >= 0 && tokenType < literalNames.length) {