空白处的 ANTLR4 令牌识别

ANTLR4 Token recognition at whitespace

我刚开始使用 ANTLR 解析器。

这是我的语法:

grammar Commands;

file_ : expression EOF;
expression : Command WhiteSpace Shape ;

WhiteSpace : [\t]+ -> skip;
NewLine : ('\r'?'\n'|'\r') -> skip;
Shape : ('square'|'triangle'|'circle'|'hexagon'|'line');
Command : ('fill'|'draw'|'delete');

我正在尝试解析一个句子列表,例如:

draw circle;
draw triangle;
delete circle;

我得到

token recognition error at:' '

谁能告诉我这是什么问题? PS:我在 java 15

工作

更新

file_ : expressions EOF;
expressions 
            : expressions expression
            | expression 
            ;
expression : Command WhiteSpace Shape NewLine ;

WhiteSpace : [\t]+ -> skip;
NewLine : ('\r'?'\n'|'\r') -> skip;
Shape : ('square'|'triangle'|'circle'|'hexagon'|'line');
Command : ('fill'|'draw'|'delete');

添加了对多个表达式的支持。 我遇到了同样的错误。

更新

grammar Commands;

file_ : expressions EOF;
expressions
            : expressions expression
            | expression
            ;
expression : Command Shape;

WhiteSpace : [\t]+ -> skip;
NewLine : ('\r'?'\n'|'\r') -> skip;
Shape : ('square'|'triangle'|'circle'|'hexagon'|'line');
Command : ('fill'|'draw'|'delete');

即使我不包括 WhiteSpace,我也会得到相同的标记识别错误。

你的白色space 令牌规则 WhiteSpace 只允许制表符。添加一个 space 到它。

WhiteSpace : [ \t]+ -> skip;

(通常,白space规则的意义远不止于此,但它应该可以解决您眼前的问题。

你也没有考虑';'在你的输入中。将其添加到规则中,或暂时从您的测试输入中删除。

expression : Command Shape ';' ;

这会解决问题,但似乎它可能不是您真正需要的。

好的,错误:

line 3:6 token recognition error at: ' '
line 3:13 token recognition error at: ';'

意味着词法分析器遇到了一个白色的 space 字符(或分号),但是没有匹配这些字符中的任何一个的词法分析器规则。你必须把它们包括在你的语法中。假设您像这样添加它们(注意:仍然不正确!):

Semi       : ';';
WhiteSpace : [ \t]+ -> skip;

尝试使用上述规则时,您会收到错误消息:

line 1:5 missing WhiteSpace at 'circle'

这意味着解析器无法将规则 expression : Command WhiteSpace Shape ; 匹配到输入 draw circle;。这是因为在词法分析器内部,您 skipping 所有白色 space 字符。这意味着这些标记在解析器规则中不可用。从您的解析器中删除它们。

您还会看到错误:

line 1:11 mismatched input ';' expecting <EOF>

这意味着输入包含一个 Semi 标记,解析器没有预料到这一点。在您的 expression 规则中包含 Semi 标记:

grammar Commands;

file_ : expression EOF;
expression : Command Shape Semi;

Semi : ';';
WhiteSpace : [ \t]+ -> skip;
NewLine : ('\r'?'\n'|'\r') -> skip;
Shape : ('square'|'triangle'|'circle'|'hexagon'|'line');
Command : ('fill'|'draw'|'delete');

上面的语法适用于单个表达式。如果你想匹配多个表达式,你可以这样做:

expressions
            : expressions expression
            | expression
            ;

但考虑到 ANTLR 生成 LL parsers (not LR as the name ANTLR suggests),这样做更容易(并使分析树更容易在以后遍历):

expressions
 : expression+
 ;

如果您要跳过所有白色 space 字符,您不妨删除 NewLine 规则并执行以下操作:

WhiteSpace : [ \t\r\n]+ -> skip;

还有一件事,词法分析器现在创建 ShapeCommand 标记,它们都具有相同的类型。我会做这样的事情:

shape    : Square | Triangle | ...;

Square   : 'square';
Triangle : 'triangle';
...

当您想评估输入时(如果这是您要做的),这将使您在遍历解析树时更轻松。

我会选择这样的东西:

grammar Commands;

file_       : expressions EOF;
expressions : expression+;
expression  : command shape Semi;
shape       : Square | Traingle | Circle | Hexagon | Line;
command     : Fill | Draw | Delete;

Semi        : ';';
WhiteSpace  : [ \t\r\n]+ -> skip;
Square      : 'square';
Traingle    : 'triangle';
Circle      : 'circle';
Hexagon     : 'hexagon';
Line        : 'line';
Fill        : 'fill';
Draw        : 'draw';
Delete      : 'delete';