我在示例文件中遇到无关输入的问题。我得到了以下词法分析器:
lexer grammar CtoLexer;
ENUM: 'enum';
NAMESPACE: 'namespace';
LBRACE: '{';
RBRACE: '}';
DOT: '.';
VAR: 'o ';
IDENTIFIER: LetterOrDigit+;
fragment LetterOrDigit
: [a-zA-Z$_] | [0-9];
WS: [ trnu000C]+ -> skip;
。和解析器:
parser grammar CtoParser;
options { tokenVocab=CtoLexer; }
modelUnit
: namespaceDeclaration enumDeclaration* EOF;
namespaceDeclaration
: NAMESPACE IDENTIFIER ('.' IDENTIFIER)*;
enumDeclaration
: ENUM IDENTIFIER '{' enumConstant* '}';
enumConstant
: VAR IDENTIFIER;
这是我的示例 cto 文件:
namespace org.basic.sample
enum FooType {
o FOO
}
enum BarType {
o BAR
}
enum BazType {
o BAZ
}
此示例文件的树如下所示:
(modelUnit
(namespaceDeclaration namespace org . basic . sample)
(enumDeclaration enum FooType { (enumConstant o FOO) })
(enumDeclaration enum BarType { (enumConstant o BAR) })
(enumDeclaration enum BazType { (enumConstant o BAZ) })
<EOF>)
当我将示例中的第一个枚举更改为其他内容时,假设"enum"更改为"enumi",几乎整个树都搞砸了。解析器仅识别命名空间,其余部分似乎是标识符。
(modelUnit
(namespaceDeclaration namespace org . basic . sample)
enumi FooType { o FOO }
enum BarType { o BAR }
enum BazType { o BAZ })
但是,当我对第二个枚举执行相同的操作时,不知何故,只有无效枚举无法识别,其余的都很好。
(modelUnit
(namespaceDeclaration namespace org . basic . sample)
(enumDeclaration enum FooType { (enumConstant o FOO) })
enumi BarType { o BAR }
(enumDeclaration enum BazType { (enumConstant o BAZ) }) <EOF>)
我该怎么办才能跳过第一个错误输入并识别其余输入?我尝试使用新的行标记,但是当我想在命名空间之后引入新声明时,这会导致问题。
据我所知,这是预测引擎的限制。我也看到在像这个MySQL查询这样的情况下:
select * from sakila.actor where
这会将 select
关键字标记为错误,而不是缺少where
表达式。这里发生的情况是,ALL(*) 预测在规则链中看起来太远了。如果出现错误,则不允许将正确的输入解析为该错误,但有时会使整个输入失败。我还没有找到解决这个问题的好方法。这一切似乎都取决于语法结构。