ANTLR4如何等待处理所有规则?

ANTLR4 how to wait for processing all rules?

我已经使用语言服务器协议创建了自己的基于 Xtext 的 DSL 和基于 vscode 的编辑器。我用 antlr4ts 从当前 TextDocument 解析模型。下面是监听器的代码片段

class TreeShapeListener implements DebugInternalModelListener {

  public async enterRuleElem1(ctx: RuleElem1Context): Promise<void> {
    ...
    // by the time the response is received, 'walk' function returns
    var resp = await this.client.sendRequest(vscode_languageserver_protocol_1.DefinitionRequest.type,
            this.client.code2ProtocolConverter.asTextDocumentPositionParams(this.document, position))
                .then(this.client.protocol2CodeConverter.asDefinitionResult, (error) => {
                    return this.client.handleFailedRequest(vscode_languageserver_protocol_1.DefinitionRequest.type, error, null);
            });
    ...
    this.model.addElem1(elem1);
  }

  public async enterRuleElem2(ctx: RuleElem2Context): void {
    ...
    this.model.addElem2(elem2);
  }

在这里我创建了解析器和树遍历器。

  // Create the lexer and parser
  let inputStream = antlr4ts.CharStreams.fromString(document.getText());
  let lexer = new DebugInternaModelLexer(inputStream);
  let tokenStream = new antlr4ts.CommonTokenStream(lexer);
  let parser = new DebugInternalModelParser(tokenStream);
    
  parser.buildParseTree = true;
  let tree = parser.ruleModel();

  let model = new Model();
  ParseTreeWalker.DEFAULT.walk(new TreeShapeListener(model, client, document) as ParseTreeListener, tree);
  console.log(model);
 

问题是在处理其中一条规则 (enterRuleElem1) 时,我有一个异步函数 (client.sendRequest),它在 ParseTreeWalker.DEFAULT.walk returns 之后返回。如何让 walk 等到所有规则完成?

编辑 1: 不确定 walk 函数是否是这样工作的,但尝试使用下面的最少代码重新创建上述场景

function setTimeoutPromise(delay) {
    return new Promise((resolve, reject) => {
      if (delay < 0) return reject("Delay must be greater than 0")
  
      setTimeout(() => {
        resolve(`You waited ${delay} milliseconds`)
      }, delay)
    })
}

async function enterRuleBlah() {
    let resp = await setTimeoutPromise(2500);
    console.log(resp);
}

function enterRuleBlub() {
    console.log('entered blub');
}

function walk() {
    enterRuleBlah();
    enterRuleBlub();
}

walk();

console.log('finished parsing');

输出为

entered blub
finished parsing
You waited 2500 milliseconds

编辑 2: 我尝试了答案中的建议,现在可以了!我的解决方案如下:

    public async doStuff() {
        ...
        return new Promise((resolve)=> {
            resolve(0);
        })
    }

    let listener = new TreeShapeListener(model, client, document);
    ParseTreeWalker.DEFAULT.walk(listener as ParseTreeListener, tree);

    await listener.doStuff();

树遍历是完全同步的,无论您是否将 listener/visitor 规则设为异步。最好将请求与步行分开,步行应该只收集所有需要知道要发送什么的信息,after 处理此收集并实际发送请求,然后您可以等待。