mike-lischke / antlr4ng

Next Generation TypeScript runtime for ANTLR4
Other
64 stars 11 forks source link

[Feature Request] Cancellable Parsing #78

Open SSlinky opened 1 week ago

SSlinky commented 1 week ago

It would be really useful to be able to cancel a parse that is being executed. I've janked it in by modifying the node module, but that's not really the best solution. Below as an example in the walk method.

    /**
     * Performs a walk on the given parse tree starting at the root and going down recursively
     * with depth-first search. On each node, {@link ParseTreeWalker.enterRule} is called before
     * recursively walking down into child nodes, then
     * {@link ParseTreeWalker.exitRule} is called after the recursive call to wind up.
     *
     * @param listener The listener used by the walker to process grammar rules
     * @param t The parse tree to be walked on
     */
    public walk<T extends ParseTreeListener>(listener: T, t: ParseTree, token?: {isCancellationRequested: boolean}): void {
        // Don't bother continuing if we don't need to.
        if (token?.isCancellationRequested) {
            return;
        }

        const errorNode = t instanceof ErrorNode;
        if (errorNode) {
            listener.visitErrorNode(t);
        } else if (t instanceof TerminalNode) {
            listener.visitTerminal(t);
        } else {
            const r = t as ParserRuleContext;
            this.enterRule(listener, r);
            for (let i = 0; i < t.getChildCount(); i++) {
                this.walk(listener, t.getChild(i)!);
            }
            this.exitRule(listener, r);

            // Don't bother running the exit rules if we don't need to.
            if (!token?.isCancellationRequested) {
                this.exitRule(listener, r);;
            }
        }
    }
mike-lischke commented 1 week ago

Can't you just throw an error in your visitor to stop walking?

SSlinky commented 4 days ago

I would have thought, yeah. But I haven't been able to catch it sucessfully. I have written a vscode language client/server throwing seems to be caught by the package and reported to the client as the server experienced an unhandled error. Too many and it stops restarting it.

I'm open to the fact that it's likely my own lack of knowledge here.

mike-lischke commented 2 days ago

A top level try/catch should do the job. For the exception you can use ParseCancellationException which is specifically designed for use in early-out scenarios.