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 处理此收集并实际发送请求,然后您可以等待。
我已经使用语言服务器协议创建了自己的基于 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 处理此收集并实际发送请求,然后您可以等待。