我想定义一种语法,其中标识符ID
的lexer规则只有在有效的情况下才能成功匹配。这样的标识符以集合的形式提供给lexer。
基于这个答案,我提出了以下解决方案。我添加了另一个lexer构造函数,传入一组有效的标识符。然后,我在ID
标记规则之后添加了一个谓词,以便在找不到匹配的文本时禁用它。lexer将匹配UNKNOWN
令牌(相同的规则(,我希望强制使用NoViableAltException
,因为expr
没有包含UNKNOWN
的规则。相反,我得到了MismatchedInputExceptions
,这可能很好,但不再报告以下所有语法错误。
grammar T;
@lexer::members {
private java.util.Set<String> identifiers = new java.util.HashSet<>();
public TLexer(CharStream input, java.util.Set<String> s) {
this(input);
this.identifiers = s;
}
public boolean hasIdentifier(String s) {
return identifiers.contains(s);
}
}
prog: expr;
expr
: expr ('AND' | 'OR') expr
| ID '=' STRING
| ID ('=' | '<' | '>') INT
;
INT: ...
STRING: ...
ID: [a-z][a-zA-Z0-9]* {hasIdentifier(getText())}?;
UNKNOWN: [a-z][a-zA-Z0-9]*;
WS: [ rnt] -> skip();
有没有更好的方法可以将任何无效标识符报告为实际语法错误?
只有当解析器能够从第一个错误中恢复时,才会出现其他语法错误。这种能力在很大程度上取决于语法。如果无法重新同步,解析器最终将放弃,并且永远不会报告更多错误。
因此,我不会试图得到更多的错误。相反,向用户报告一个,并让他在继续出现更多错误之前修复它。