UNPKG

antlr4-runtime

Version:

JavaScript runtime for ANTLR4

126 lines (112 loc) 3.38 kB
/* 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; } }