diff --git a/services/web/frontend/js/features/source-editor/languages/latex/debug-print.ts b/services/web/frontend/js/features/source-editor/languages/latex/debug-print.ts deleted file mode 100644 index 77b7b9fe3a..0000000000 --- a/services/web/frontend/js/features/source-editor/languages/latex/debug-print.ts +++ /dev/null @@ -1,283 +0,0 @@ -// from https://gist.github.com/msteen/e4828fbf25d6efef73576fc43ac479d2 -// https://discuss.codemirror.net/t/whats-the-best-to-test-and-debug-grammars/2542/5 - -// MIT License -// -// Copyright (c) 2021 Matthijs Steen -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -import { Text } from '@codemirror/state' -import { Input, NodeType, SyntaxNode, Tree, TreeCursor } from '@lezer/common' -import { debugConsole } from '@/utils/debugging' - -class StringInput implements Input { - private input: string - - constructor(input: string) { - this.input = input - } - - get length() { - return this.input.length - } - - chunk(from: number): string { - return this.input.slice(from) - } - - lineChunks = false - - read(from: number, to: number): string { - return this.input.slice(from, to) - } -} - -export function sliceType( - cursor: TreeCursor, - input: Input, - type: number -): string | null { - if (cursor.type.id === type) { - const s = input.read(cursor.from, cursor.to) - cursor.nextSibling() - return s - } - return null -} - -export function isType(cursor: TreeCursor, type: number): boolean { - const cond = cursor.type.id === type - if (cond) cursor.nextSibling() - return cond -} - -export type CursorNode = { - type: NodeType - from: number - to: number - isLeaf: boolean -} - -function cursorNode( - { type, from, to }: TreeCursor, - isLeaf = false -): CursorNode { - return { type, from, to, isLeaf } -} - -export type TreeTraversal = { - beforeEnter?: (cursor: TreeCursor) => void - onEnter: (node: CursorNode) => false | void - onLeave?: (node: CursorNode) => false | void -} - -type TreeTraversalOptions = { - from?: number - to?: number - includeParents?: boolean -} & TreeTraversal - -export function traverseTree( - cursor: TreeCursor | Tree | SyntaxNode, - { - from = -Infinity, - to = Infinity, - includeParents = false, - beforeEnter, - onEnter, - onLeave, - }: TreeTraversalOptions -): void { - if (!(cursor instanceof TreeCursor)) - cursor = cursor instanceof Tree ? cursor.cursor() : cursor.cursor() - for (;;) { - let node = cursorNode(cursor) - let leave = false - if (node.from <= to && node.to >= from) { - const enter = - !node.type.isAnonymous && - (includeParents || (node.from >= from && node.to <= to)) - if (enter && beforeEnter) beforeEnter(cursor) - node.isLeaf = !cursor.firstChild() - if (enter) { - leave = true - if (onEnter(node) === false) return - } - if (!node.isLeaf) continue - } - for (;;) { - node = cursorNode(cursor, node.isLeaf) - if (leave && onLeave) if (onLeave(node) === false) return - leave = cursor.type.isAnonymous - node.isLeaf = false - if (cursor.nextSibling()) break - if (!cursor.parent()) return - leave = true - } - } -} - -function isChildOf(child: CursorNode, parent: CursorNode): boolean { - return ( - child.from >= parent.from && - child.from <= parent.to && - child.to <= parent.to && - child.to >= parent.from - ) -} - -export function validatorTraversal( - input: Input | string, - { fullMatch = true }: { fullMatch?: boolean } = {} -) { - if (typeof input === 'string') input = new StringInput(input) - const state = { - valid: true, - parentNodes: [] as CursorNode[], - lastLeafTo: 0, - } - return { - state, - traversal: { - onEnter(node) { - state.valid = true - if (!node.isLeaf) state.parentNodes.unshift(node) - if (node.from > node.to || node.from < state.lastLeafTo) { - state.valid = false - } else if (node.isLeaf) { - if ( - state.parentNodes.length && - !isChildOf(node, state.parentNodes[0]) - ) - state.valid = false - state.lastLeafTo = node.to - } else { - if (state.parentNodes.length) { - if (!isChildOf(node, state.parentNodes[0])) state.valid = false - } else if ( - fullMatch && - (node.from !== 0 || node.to !== input.length) - ) { - state.valid = false - } - } - }, - onLeave(node) { - if (!node.isLeaf) state.parentNodes.shift() - }, - } as TreeTraversal, - } -} - -export function validateTree( - tree: TreeCursor | Tree | SyntaxNode, - input: Input | string, - options?: { fullMatch?: boolean } -): boolean { - const { state, traversal } = validatorTraversal(input, options) - traverseTree(tree, traversal) - return state.valid -} - -function colorize(value: any): string { - return '' + value -} - -type PrintTreeOptions = { - from?: number - to?: number - start?: number - includeParents?: boolean -} - -export function printTree( - cursor: TreeCursor | Tree | SyntaxNode, - input: Input | string, - { from, to, start = 0, includeParents }: PrintTreeOptions = {} -): string { - const inp = typeof input === 'string' ? new StringInput(input) : input - const text = Text.of(inp.read(0, inp.length).split('\n')) - const state = { - output: '', - prefixes: [] as string[], - hasNextSibling: false, - } - const validator = validatorTraversal(inp) - traverseTree(cursor, { - from, - to, - includeParents, - beforeEnter(cursor) { - state.hasNextSibling = cursor.nextSibling() && cursor.prevSibling() - }, - onEnter(node) { - validator.traversal.onEnter(node) - const isTop = state.output === '' - const hasPrefix = !isTop || node.from > 0 - if (hasPrefix) { - state.output += (!isTop ? '\n' : '') + state.prefixes.join('') - if (state.hasNextSibling) { - state.output += ' ├─ ' - state.prefixes.push(' │ ') - } else { - state.output += ' └─ ' - state.prefixes.push(' ') - } - } - const hasRange = node.from !== node.to - state.output += - (node.type.isError || !validator.state.valid - ? colorize('ERROR ' + node.type.name) - : node.type.name) + - ' ' + - (hasRange - ? '[' + - colorize(locAt(text, start + node.from)) + - '..' + - colorize(locAt(text, start + node.to)) + - ']' - : colorize(locAt(text, start + node.from))) - if (hasRange && node.isLeaf) { - state.output += - ': ' + colorize(JSON.stringify(inp.read(node.from, node.to))) - } - }, - onLeave(node) { - if (validator.traversal.onLeave) { - validator.traversal.onLeave(node) - } - state.prefixes.pop() - }, - }) - return state.output -} - -function locAt(text: Text, pos: number): string { - const line = text.lineAt(pos) - return line.number + ':' + (pos - line.from) -} - -export function logTree( - tree: TreeCursor | Tree | SyntaxNode, - input: string, - options?: PrintTreeOptions -): void { - debugConsole.warn(printTree(tree, input, options)) -} diff --git a/services/web/frontend/js/features/source-editor/lezer-latex/print-tree.mjs b/services/web/scripts/lezer-latex/print-tree.mjs similarity index 98% rename from services/web/frontend/js/features/source-editor/lezer-latex/print-tree.mjs rename to services/web/scripts/lezer-latex/print-tree.mjs index a1caf9e9be..ac6a24eb1f 100644 --- a/services/web/frontend/js/features/source-editor/lezer-latex/print-tree.mjs +++ b/services/web/scripts/lezer-latex/print-tree.mjs @@ -23,7 +23,6 @@ // SOFTWARE. import { Text } from '@codemirror/state' import { Tree, TreeCursor } from '@lezer/common' -import { debugConsole } from '@/utils/debugging' class StringInput { constructor(input) { @@ -212,5 +211,5 @@ function locAt(text, pos) { } export function logTree(tree, input, options) { - debugConsole.warn(printTree(tree, input, options)) + console.warn(printTree(tree, input, options)) } diff --git a/services/web/scripts/lezer-latex/run.mjs b/services/web/scripts/lezer-latex/run.mjs index 5d78f5b67e..bda582e29b 100644 --- a/services/web/scripts/lezer-latex/run.mjs +++ b/services/web/scripts/lezer-latex/run.mjs @@ -1,5 +1,5 @@ import { readFileSync } from 'fs' -import { logTree } from '../../frontend/js/features/source-editor/lezer-latex/print-tree.mjs' +import { logTree } from './print-tree.mjs' import { parser as LaTeXParser } from '../../frontend/js/features/source-editor/lezer-latex/latex.mjs' import { parser as BibTeXParser } from '../../frontend/js/features/source-editor/lezer-bibtex/bibtex.mjs'