+ /**
+ * Attempts to cache terminator search result.
+ */
+ public Terminator getOrFindTokenTerminator() {
+ if (currentIndex == cachedTerminatorIndex)
+ return cachedTerminator;
+
+ cachedTerminatorIndex = currentIndex;
+ cachedTerminator = findTokenTerminator();
+ return cachedTerminator;
+ }
+
+ private Terminator findTokenTerminator() {
+ for (Terminator terminator : terminators)
+ if (terminator.matches(source, currentIndex))
+ return terminator;
+ return null;
+ }
+
+ public boolean consumeIfNextToken(final String token) throws InvalidSyntaxException {
+ if (token.equals(getNextToken().token))
+ return true;
+
+ unreadToken();
+ return false;
+ }
+
+ public TokenizerMatch peekNextToken() throws InvalidSyntaxException {
+ TokenizerMatch result = getNextToken();
+ unreadToken();
+ return result;
+ }
+
+ public boolean peekIsOneOf(String ... possibilities) throws InvalidSyntaxException {
+ String nextToken = peekNextToken().token;
+ return Stream.of(possibilities).anyMatch(possibility -> possibility.equals(nextToken));
+ }
+
+ public void peekExpectNoneOf(String ... possibilities) throws InvalidSyntaxException {
+ if (peekIsOneOf(possibilities))
+ throw new InvalidSyntaxException("Not expected \"" + peekNextToken().token + "\" here.");
+ }
+