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



我已经用语言服务器协议创建了我自己的基于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)时,我有一个async函数(client.sendRequest),在ParseTreeWalker.DEFAULT.walk返回后返回。如何让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();

无论您是否将侦听器/访问者规则设置为异步,树遍历都是完全同步的。最好将请求从walk中分离出来,walk应该只收集所有需要知道发送什么和之后的的信息。处理此集合并实际发送请求,然后您可以等待。

最新更新