bitmark-grammar
Version:
221 lines (192 loc) • 6.09 kB
text/typescript
/*!
* Copyright 2016 The ANTLR Project. All rights reserved.
* Licensed under the BSD-3-Clause license. See LICENSE file in the project root for license information.
*/
// ConvertTo-TS run at 2016-10-04T11:26:52.1916955-07:00
import { CharStream } from "./CharStream";
import { CommonTokenFactory } from "./CommonTokenFactory";
import { NotNull, Override } from "./Decorators";
import { Token } from "./Token";
import { TokenFactory } from "./TokenFactory";
import { TokenSource } from "./TokenSource";
/**
* Provides an implementation of {@link TokenSource} as a wrapper around a list
* of {@link Token} objects.
*
* 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.
*/
export class ListTokenSource implements TokenSource {
/**
* The wrapped collection of {@link Token} objects to return.
*/
protected tokens: Token[];
/**
* The name of the input source. If this value is `undefined`, a call to
* {@link #getSourceName} should return the source name used to create the
* the next token in {@link #tokens} (or the previous token if the end of
* the input has been reached).
*/
private _sourceName?: string;
/**
* 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}.
*/
protected i: number = 0;
/**
* This field caches the EOF token for the token source.
*/
protected eofToken?: Token;
/**
* This is the backing field for {@link #getTokenFactory} and
* {@link setTokenFactory}.
*/
private _factory: TokenFactory = CommonTokenFactory.DEFAULT;
/**
* 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
* `undefined`, {@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 `tokens` is `undefined`
*/
constructor( tokens: Token[], sourceName?: string) {
if (tokens == null) {
throw new Error("tokens cannot be null");
}
this.tokens = tokens;
this._sourceName = sourceName;
}
/**
* {@inheritDoc}
*/
get charPositionInLine(): number {
if (this.i < this.tokens.length) {
return this.tokens[this.i].charPositionInLine;
} else if (this.eofToken != null) {
return this.eofToken.charPositionInLine;
} else if (this.tokens.length > 0) {
// have to calculate the result from the line/column of the previous
// token, along with the text of the token.
let lastToken: Token = this.tokens[this.tokens.length - 1];
let tokenText: string | undefined = lastToken.text;
if (tokenText != null) {
let lastNewLine: number = tokenText.lastIndexOf("\n");
if (lastNewLine >= 0) {
return tokenText.length - lastNewLine - 1;
}
}
return lastToken.charPositionInLine + lastToken.stopIndex - lastToken.startIndex + 1;
}
// only reach this if tokens is empty, meaning EOF occurs at the first
// position in the input
return 0;
}
/**
* {@inheritDoc}
*/
public nextToken(): Token {
if (this.i >= this.tokens.length) {
if (this.eofToken == null) {
let start: number = -1;
if (this.tokens.length > 0) {
let previousStop: number = this.tokens[this.tokens.length - 1].stopIndex;
if (previousStop !== -1) {
start = previousStop + 1;
}
}
let stop: number = Math.max(-1, start - 1);
this.eofToken = this._factory.create({ source: this, stream: this.inputStream }, Token.EOF, "EOF", Token.DEFAULT_CHANNEL, start, stop, this.line, this.charPositionInLine);
}
return this.eofToken;
}
let t: Token = this.tokens[this.i];
if (this.i === this.tokens.length - 1 && t.type === Token.EOF) {
this.eofToken = t;
}
this.i++;
return t;
}
/**
* {@inheritDoc}
*/
get line(): number {
if (this.i < this.tokens.length) {
return this.tokens[this.i].line;
} else if (this.eofToken != null) {
return this.eofToken.line;
} else if (this.tokens.length > 0) {
// have to calculate the result from the line/column of the previous
// token, along with the text of the token.
let lastToken: Token = this.tokens[this.tokens.length - 1];
let line: number = lastToken.line;
let tokenText: string | undefined = lastToken.text;
if (tokenText != null) {
for (let i = 0; i < tokenText.length; i++) {
if (tokenText.charAt(i) === "\n") {
line++;
}
}
}
// 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}
*/
get inputStream(): CharStream | undefined {
if (this.i < this.tokens.length) {
return this.tokens[this.i].inputStream;
} else if (this.eofToken != null) {
return this.eofToken.inputStream;
} else if (this.tokens.length > 0) {
return this.tokens[this.tokens.length - 1].inputStream;
}
// no input stream information is available
return undefined;
}
/**
* {@inheritDoc}
*/
get sourceName(): string {
if (this._sourceName) {
return this._sourceName;
}
let inputStream: CharStream | undefined = this.inputStream;
if (inputStream != null) {
return inputStream.sourceName;
}
return "List";
}
/**
* {@inheritDoc}
*/
// @Override
set tokenFactory( factory: TokenFactory) {
this._factory = factory;
}
/**
* {@inheritDoc}
*/
get tokenFactory(): TokenFactory {
return this._factory;
}
}