ANTLR4 - 使 space 在标记之间可选
ANTLR4 - Make space optional between tokens
我有以下语法:
grammar Hello;
prog: stat+ EOF;
stat: DELIMITER_OPEN expr DELIMITER_CLOSE;
expr: NOTES COMMA value=VAR_VALUE #delim_body;
VAR_VALUE: ANBang*;
NOTES: WS* 'notes' WS*;
COMMA: ',';
DELIMITER_OPEN: '<<!';
DELIMITER_CLOSE: '!>>';
fragment ANBang: AlphaNum | Bang;
fragment AlphaNum: [a-zA-Z0-9];
fragment Bang: '!';
WS : [ \t\r\n]+ -> skip ;
正在解析以下作品:
<<! notes, Test !>>
并且变量值为 "Test",但是,当我删除 DELIMITER_OPEN 和注释之间的 space 时,解析器失败:
<<!notes, Test !>>
line 1:3 mismatched input 'notes' expecting NOTES
这是 又一个 词法分析器规则排序不当的案例。
当词法分析器扫描下一个标记时,它首先尝试找到匹配最长标记的规则。如果多个规则匹配,它将通过选择定义顺序中的 第一个 来消除歧义。
<<! notes, Test !>>
将被标记为:
DELIMITER_OPEN
NOTES
COMMA
VAR_VALUE
WS
DELIMITER_CLOSE
这是因为 NOTES
规则可以匹配以下内容:
<<! notes, Test !>>
\____/
其中 包括 空格。如果删除它:
<<!notes, Test !>>
那么NOTES
和VAR_VALUE
规则都可以匹配文本notes
,并且,VAR_VALUE
定义在前在语法中,所以它获得优先权。标记化是:
DELIMITER_OPEN
VAR_VALUE
COMMA
VAR_VALUE
WS
DELIMITER_CLOSE
它不符合您的 expr
规则。
像这样更改您的规则以解决问题:
NOTES: 'notes';
VAR_VALUE: ANBang+;
将 WS*
添加到其他规则没有多大意义,因为 WS
被跳过了。并且将标记声明为具有可能的零宽度 *
也是没有意义的,因此请改用 +
。最后,重新排序 规则,以便最具体的匹配拳头。
这样,notes
就变成了语法中的 关键字 。如果您不希望它成为关键字,请完全删除 NOTES
规则,并使用带有谓词的 VAR_VALUE
规则。或者,您可以使用词法分析器模式。
我有以下语法:
grammar Hello;
prog: stat+ EOF;
stat: DELIMITER_OPEN expr DELIMITER_CLOSE;
expr: NOTES COMMA value=VAR_VALUE #delim_body;
VAR_VALUE: ANBang*;
NOTES: WS* 'notes' WS*;
COMMA: ',';
DELIMITER_OPEN: '<<!';
DELIMITER_CLOSE: '!>>';
fragment ANBang: AlphaNum | Bang;
fragment AlphaNum: [a-zA-Z0-9];
fragment Bang: '!';
WS : [ \t\r\n]+ -> skip ;
正在解析以下作品:
<<! notes, Test !>>
并且变量值为 "Test",但是,当我删除 DELIMITER_OPEN 和注释之间的 space 时,解析器失败:
<<!notes, Test !>>
line 1:3 mismatched input 'notes' expecting NOTES
这是 又一个 词法分析器规则排序不当的案例。
当词法分析器扫描下一个标记时,它首先尝试找到匹配最长标记的规则。如果多个规则匹配,它将通过选择定义顺序中的 第一个 来消除歧义。
<<! notes, Test !>>
将被标记为:
DELIMITER_OPEN
NOTES
COMMA
VAR_VALUE
WS
DELIMITER_CLOSE
这是因为 NOTES
规则可以匹配以下内容:
<<! notes, Test !>>
\____/
其中 包括 空格。如果删除它:
<<!notes, Test !>>
那么NOTES
和VAR_VALUE
规则都可以匹配文本notes
,并且,VAR_VALUE
定义在前在语法中,所以它获得优先权。标记化是:
DELIMITER_OPEN
VAR_VALUE
COMMA
VAR_VALUE
WS
DELIMITER_CLOSE
它不符合您的 expr
规则。
像这样更改您的规则以解决问题:
NOTES: 'notes';
VAR_VALUE: ANBang+;
将 WS*
添加到其他规则没有多大意义,因为 WS
被跳过了。并且将标记声明为具有可能的零宽度 *
也是没有意义的,因此请改用 +
。最后,重新排序 规则,以便最具体的匹配拳头。
这样,notes
就变成了语法中的 关键字 。如果您不希望它成为关键字,请完全删除 NOTES
规则,并使用带有谓词的 VAR_VALUE
规则。或者,您可以使用词法分析器模式。