antlr4-runtime
Version:
JavaScript runtime for ANTLR4
126 lines (112 loc) • 3.38 kB
JavaScript
/* Copyright (c) 2012-2022 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.
*/
import Token from './Token.js';
/**
* If decodeToUnicodeCodePoints is true, the input is treated
* as a series of Unicode code points.
*
* Otherwise, the input is treated as a series of 16-bit UTF-16 code
* units.
*/
export default class CharStream {
constructor(data, decodeToUnicodeCodePoints) {
this.name = "<empty>";
this.strdata = data;
this.decodeToUnicodeCodePoints = decodeToUnicodeCodePoints || false;
// _loadString - Vacuum all input from a string and then treat it like a buffer.
this._index = 0;
this.data = [];
if (this.decodeToUnicodeCodePoints) {
for (let i = 0; i < this.strdata.length; ) {
const codePoint = this.strdata.codePointAt(i);
this.data.push(codePoint);
i += codePoint <= 0xFFFF ? 1 : 2;
}
} else {
this.data = new Array(this.strdata.length);
for (let i = 0; i < this.strdata.length; i++) {
this.data[i] = this.strdata.charCodeAt(i);
}
}
this._size = this.data.length;
}
/**
* Reset the stream so that it's in the same state it was
* when the object was created *except* the data array is not
* touched.
*/
reset() {
this._index = 0;
}
consume() {
if (this._index >= this._size) {
// assert this.LA(1) == Token.EOF
throw ("cannot consume EOF");
}
this._index += 1;
}
LA(offset) {
if (offset === 0) {
return 0; // undefined
}
if (offset < 0) {
offset += 1; // e.g., translate LA(-1) to use offset=0
}
const pos = this._index + offset - 1;
if (pos < 0 || pos >= this._size) { // invalid
return Token.EOF;
}
return this.data[pos];
}
LT(offset) {
return this.LA(offset);
}
// mark/release do nothing; we have entire buffer
mark() {
return -1;
}
release(marker) {
}
/**
* consume() ahead until p==_index; can't just set p=_index as we must
* update line and column. If we seek backwards, just set p
*/
seek(_index) {
if (_index <= this._index) {
this._index = _index; // just jump; don't update stream state (line,
// ...)
return;
}
// seek forward
this._index = Math.min(_index, this._size);
}
getText(start, stop) {
if (stop >= this._size) {
stop = this._size - 1;
}
if (start >= this._size) {
return "";
} else {
if (this.decodeToUnicodeCodePoints) {
let result = "";
for (let i = start; i <= stop; i++) {
result += String.fromCodePoint(this.data[i]);
}
return result;
} else {
return this.strdata.slice(start, stop + 1);
}
}
}
toString() {
return this.strdata;
}
get index(){
return this._index;
}
get size(){
return this._size;
}
}