我正在编写一种类似 SQL 的语言。假设正确的语法是
USE foo;
SELECT * FROM bar;
但我把它输入
US foo;
SELECT * FROM bar;
默认行为是 Antlr 将停止解析并且我丢失了语法高亮和大纲视图。错误消息是Missing EOF at 'US'
。我将 IParser 重新绑定到 RuntimeModule 中的自定义解析器
@Override
public Class<? extends org.eclipse.xtext.parser.IParser> bindIParser() {
return CustomCqlParser.class;
}
覆盖createParser
方法Parser
@Override
protected InternalCqlParser createParser(XtextTokenStream stream) {
return new CustomInternalCqlParser(stream, getGrammarAccess());
}
并覆盖处理此部分的方法recoverFromMismatchedToken
以消耗所有令牌直到分号
@Override
protected Object recoverFromMismatchedToken(IntStream input, int ttype, BitSet follow) throws RecognitionException {
Object out = super.recoverFromMismatchedToken(input, ttype, follow);
if (out == null) {
beginResync();
consumeUntil(input, RULE_T_SEMICOLON);
input.consume();
endResync();
Object matchedSymbol = getCurrentInputSymbol(input);
System.out.println(matchedSymbol);
return matchedSymbol;
}
return out;
}
在此之后,但语法高亮仍然消失并且 antlr 停止解析matchedSymbol
。SELECT
我怎样才能实现我的目标?
============编辑===================================
我复制super.recoverFromMismatchToken
到我的自定义类并将其添加到原始源代码中。
if (ttype != EOF) {
beginResync();
consumeUntil(input, RULE_T_SEMICOLON);
input.consume();
endResync();
Object matchedSymbol = getCurrentInputSymbol(input);
input.consume(); // move past ttype token as if all were ok
return matchedSymbol;
}
如果令牌错误不是在开始时发生并且不是no viable alternative
异常,这将保持语法突出显示。但它仍然会认为它仍在使用相同的解析规则,而不是开始一个新的。此外,如果我在开始时输入了错误的标记,那么预期的标记将是EOF
. 这将使我的“使用所有令牌直到分号”也失败。
========================编辑========================= ================
跟踪InternalCqlParser.java
,我发现如果错字发生在语句的第一个关键字中,它会得到一个ID
并返回。之后我添加了一个代码片段
if (LA1_0 == RULE_IDENT) {
beginResync();
consumeUntil(input, RULE_T_SEMICOLON);
input.consume();
endResync();
continue;
}
解析会继续,并且语法高亮在错误语句之后仍然存在。但是,错误行不会有任何错误标记,并且在该行之后我丢失了内容帮助。触发内容辅助的类是Statement
,但它不再起作用。