cm-tarnation
Version:
An alternative parser for CodeMirror 6
96 lines • 3.29 kB
JavaScript
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import { Token } from "../token";
/**
* A `Chunk` stores tokens emitted by the tokenization into discrete, well,
* chunks. Chunks store their token positions (as in, position in the
* document) relative to the chunk's own "position". This allows the chunk
* to be moved anywhere in the document, and have the tokens follow. What
* this means is that a chunk can be adjusted slightly forward or back as
* the document changes, allowing for them to be reused when tokenizing.
*/
export class Chunk {
/**
* @param pos - Position of this chunk.
* @param state - The state for the start of this chunk.
* @param tokens - The grammar tokens to store in this chunk.
*/
constructor(pos, state, tokens = []) {
this._pos = pos;
this.state = state;
this._max = 0;
this.parsed = null;
this.setTokens(tokens);
}
/** The chunk's starting position. */
get pos() {
return this._pos;
}
/** The chunk's starting position. */
set pos(pos) {
this.parsed = null;
this._pos = pos;
}
/** The chunk's maximum extent, as determined from the positions of its tokens. */
get max() {
return this._max + this._pos;
}
/**
* Adds a token to the chunk.
*
* @param token - The token to add.
*/
add(token) {
this.parsed = null;
// make token relative to chunk position
const from = token[1] - this._pos;
const to = token[2] - this._pos;
if (to > this._max)
this._max = to;
this.tokens.push(new Token(token[0], from, to, token[3], token[4]));
}
/**
* Sets the chunk's tokens.
*
* @param tokens - The tokens to add.
*/
setTokens(tokens) {
this.parsed = null;
this.tokens = [];
this._max = 0;
for (let idx = 0; idx < tokens.length; idx++) {
this.add(tokens[idx]);
}
}
/**
* Returns a deep clone of the chunk.
*
* @param withTokens - If false, the tokens will be omitted. Defaults to true.
*/
clone(withTokens = true) {
const chunk = new Chunk(this.pos, this.state.clone());
if (withTokens) {
chunk.tokens = this.tokens.slice();
chunk._max = this._max;
}
return chunk;
}
/**
* Determines if a grammar's state (and parse position) is compatible
* with reusing this node. This is only a safe determination if it is
* made _after_ the changed range of the document.
*
* @param state - The state to compare against.
* @param pos - The position to compare against.
* @param offset - The edit offset, to correct for chunk position differences.
*/
isReusable(state, pos, offset = 0) {
if (this._pos + offset !== pos)
return false;
if (!state.equals(this.state))
return false;
return true;
}
}
//# sourceMappingURL=chunk.js.map