Spaces:
Build error
Build error
# | |
# 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. | |
# | |
# | |
# Provides an implementation of {@link TokenSource} as a wrapper around a list | |
# of {@link Token} objects. | |
# | |
# <p>If the final token in the list is an {@link Token#EOF} token, it will be used | |
# as the EOF token for every call to {@link #nextToken} after the end of the | |
# list is reached. Otherwise, an EOF token will be created.</p> | |
# | |
from antlr4.CommonTokenFactory import CommonTokenFactory | |
from antlr4.Lexer import TokenSource | |
from antlr4.Token import Token | |
class ListTokenSource(TokenSource): | |
__slots__ = ('tokens', 'sourceName', 'pos', 'eofToken', '_factory') | |
# Constructs a new {@link ListTokenSource} instance from the specified | |
# collection of {@link Token} objects and source name. | |
# | |
# @param tokens The collection of {@link Token} objects to provide as a | |
# {@link TokenSource}. | |
# @param sourceName The name of the {@link TokenSource}. If this value is | |
# {@code null}, {@link #getSourceName} will attempt to infer the name from | |
# the next {@link Token} (or the previous token if the end of the input has | |
# been reached). | |
# | |
# @exception NullPointerException if {@code tokens} is {@code null} | |
# | |
def __init__(self, tokens:list, sourceName:str=None): | |
if tokens is None: | |
raise ReferenceError("tokens cannot be null") | |
self.tokens = tokens | |
self.sourceName = sourceName | |
# The index into {@link #tokens} of token to return by the next call to | |
# {@link #nextToken}. The end of the input is indicated by this value | |
# being greater than or equal to the number of items in {@link #tokens}. | |
self.pos = 0 | |
# This field caches the EOF token for the token source. | |
self.eofToken = None | |
# This is the backing field for {@link #getTokenFactory} and | |
self._factory = CommonTokenFactory.DEFAULT | |
# | |
# {@inheritDoc} | |
# | |
def column(self): | |
if self.pos < len(self.tokens): | |
return self.tokens[self.pos].column | |
elif self.eofToken is not None: | |
return self.eofToken.column | |
elif len(self.tokens) > 0: | |
# have to calculate the result from the line/column of the previous | |
# token, along with the text of the token. | |
lastToken = self.tokens[len(self.tokens) - 1] | |
tokenText = lastToken.text | |
if tokenText is not None: | |
lastNewLine = tokenText.rfind('\n') | |
if lastNewLine >= 0: | |
return len(tokenText) - lastNewLine - 1 | |
return lastToken.column + lastToken.stop - lastToken.start + 1 | |
# only reach this if tokens is empty, meaning EOF occurs at the first | |
# position in the input | |
return 0 | |
# | |
# {@inheritDoc} | |
# | |
def nextToken(self): | |
if self.pos >= len(self.tokens): | |
if self.eofToken is None: | |
start = -1 | |
if len(self.tokens) > 0: | |
previousStop = self.tokens[len(self.tokens) - 1].stop | |
if previousStop != -1: | |
start = previousStop + 1 | |
stop = max(-1, start - 1) | |
self.eofToken = self._factory.create((self, self.getInputStream()), | |
Token.EOF, "EOF", Token.DEFAULT_CHANNEL, start, stop, self.line, self.column) | |
return self.eofToken | |
t = self.tokens[self.pos] | |
if self.pos == len(self.tokens) - 1 and t.type == Token.EOF: | |
self.eofToken = t | |
self.pos += 1 | |
return t | |
# | |
# {@inheritDoc} | |
# | |
def line(self): | |
if self.pos < len(self.tokens): | |
return self.tokens[self.pos].line | |
elif self.eofToken is not None: | |
return self.eofToken.line | |
elif len(self.tokens) > 0: | |
# have to calculate the result from the line/column of the previous | |
# token, along with the text of the token. | |
lastToken = self.tokens[len(self.tokens) - 1] | |
line = lastToken.line | |
tokenText = lastToken.text | |
if tokenText is not None: | |
line += tokenText.count('\n') | |
# if no text is available, assume the token did not contain any newline characters. | |
return line | |
# only reach this if tokens is empty, meaning EOF occurs at the first | |
# position in the input | |
return 1 | |
# | |
# {@inheritDoc} | |
# | |
def getInputStream(self): | |
if self.pos < len(self.tokens): | |
return self.tokens[self.pos].getInputStream() | |
elif self.eofToken is not None: | |
return self.eofToken.getInputStream() | |
elif len(self.tokens) > 0: | |
return self.tokens[len(self.tokens) - 1].getInputStream() | |
else: | |
# no input stream information is available | |
return None | |
# | |
# {@inheritDoc} | |
# | |
def getSourceName(self): | |
if self.sourceName is not None: | |
return self.sourceName | |
inputStream = self.getInputStream() | |
if inputStream is not None: | |
return inputStream.getSourceName() | |
else: | |
return "List" | |