Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] Cancellable Parsing #78

Closed
SSlinky opened this issue Jun 21, 2024 · 3 comments
Closed

[Feature Request] Cancellable Parsing #78

SSlinky opened this issue Jun 21, 2024 · 3 comments
Labels
question Further information is requested

Comments

@SSlinky
Copy link

SSlinky commented Jun 21, 2024

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
Copy link
Owner

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

@SSlinky
Copy link
Author

SSlinky commented Jun 29, 2024

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
Copy link
Owner

mike-lischke commented Jul 1, 2024

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.

@mike-lischke mike-lischke added the question Further information is requested label Jul 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants