UNPKG

cm-tarnation

Version:

An alternative parser for CodeMirror 6

103 lines 3.67 kB
/* 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 { TreeBuffer } from "@lezer/common"; import { CHUNK_ARRAY_INTERVAL } from "../constants"; export class Chunk { constructor(pos, state) { this.from = pos; this.to = pos; this.length = 0; this.state = state; this.tokens = new Int16Array(CHUNK_ARRAY_INTERVAL); this.size = 0; this.open = null; this.close = null; } offset(offset) { this.from += offset; this.to = this.from + this.length; } add(id, from, to) { this.tree = undefined; if (to > this.to) { this.to = to; this.length = to - this.from; } // make token relative to chunk position from -= this.from; to -= this.from; if (id !== null) { // resize token array if needed if (this.size * 3 + 3 > this.tokens.length) { const old = this.tokens; this.tokens = new Int16Array(this.tokens.length + CHUNK_ARRAY_INTERVAL); this.tokens.set(old); } const idx = this.size * 3; this.tokens[idx] = id; this.tokens[idx + 1] = from; this.tokens[idx + 2] = to; this.size++; } } pushOpen(...ids) { this.tree = undefined; this.open ??= []; this.open.push(...ids); } pushClose(...ids) { this.tree = undefined; this.close ??= []; this.close.push(...ids); } tryForTree(nodeSet) { if (this.tree) return this.tree; if (this.size <= 1) return null; if (this.open || this.close) { if (!(this.open && this.close)) return null; if (this.open.length !== this.close.length) return null; const open = this.open.slice().reverse(); const close = this.close; for (let i = 0; i < open.length; i++) { if (open[i] !== close[i]) return null; } } // if we're here, we can make a tree buffer out of this chunk const buffer = []; const total = this.size * 4 + (this.open?.length ?? 0) * 4; if (this.open) { for (let i = this.open.length - 1; i >= 0; i--) { buffer.push(this.open[i], 0, this.length, total); } } for (let i = 0; i < this.size; i++) { buffer.push(this.tokens[i * 3], this.tokens[i * 3 + 1], this.tokens[i * 3 + 2], buffer.length + 4); } const tree = new TreeBuffer(new Uint16Array(buffer), this.length, nodeSet); this.tree = tree; return tree; } /** * 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.from + offset !== pos) return false; if (!state.equals(this.state)) return false; return true; } } //# sourceMappingURL=chunk.js.map