在 ANTLR4 中括号周围至少有一个 Space

Atleast ONE Space around Parenthesis in ANTLR4

我想要 space 在 括号 周围 IF 条件 。至少需要一个 space。但是当我在语法中使用 Space 时它会抛出错误, 当我使用 Else 块时 。请帮助我,如何完成它,我看到了很多例子,但 none 与它有关。 我只需要在 If condition.

Parenthesis 周围 spaces
prog: stat_block EOF;

stat_block: OBRACE block CBRACE;

block: (stat (stat)*)?;

stat: expr ';'
 | IF  condition_block (ELSE  stat_block)?
 ;

expr
 : expr SPACE ('*' | '/') SPACE expr
 | ID
 | INT
 | STRING
 ;

 exprList: expr (',' expr)*;

 condition_block: SPACE OPAR SPACE expr SPACE CPAR SPACE stat_block;
 IF:      'IF';
 ELSE:    'ELSE';
 OPAR:    '(';
 CPAR:    ')';
 OBRACE:  '{';
 CBRACE:  '}';
 SPACE: SINGLE_SPACE+;
 SINGLE_SPACE: ' ';
 ID:      [a-zA-Z]+;
 INT:     [0-9]+;
 NEWLINE: '\r'? '\n'  -> skip;
 WS:      [ \t]+     -> skip;

需要解析的输入

IF ( 3 ) { } ELSE { }

当前输入

At least one space is required.

那么你要么:

  • 不能 -> skip WS 规则,这将导致 所有 space 和选项卡成为标记并需要您的解析器处理它们正确(这可能会在您的解析器规则中变得一团糟!),或者
  • 你让 WS -> skip 保持原样,但在你的 PAREN 规则中包含一个 space:OPAR : ' ( '; CPAR: ' ) ';(如果可能的话,也可以使用制表符)

几乎所有语言都忽略空格是有原因的。如果您不忽略它,那么您必须处理它可能存在于令牌流中的任何地方,无论它是否存在于您的所有解析器规则中。

可以尝试在 Lexer 规则中包含您想要用空格包裹的标记的空格,但仍然可能会发现意外。

建议:如果 -> skip; 用于您的 WS 规则,请使用 -> channel(HIDDEN); 这会将标记保留在标记流中,以便您可以在代码中查找它们,但“隐藏" 来自解析器规则的空白标记。这也允许 ANTLR 对您的输入进行正确的解释,并构建一个正确表示它的解析树。

如果您真的 想要坚持使用空格 before/after,您可以在监听器中编写代码,让 before/after 看起来是输入流中的标记查看您是否有空格,并生成您自己的错误(可以非常具体地说明您的要求)。