如何在 ANTLR4 中创建带有可选部分的词法规则
How to create lexical rules with optional part in ANTLR4
我正在尝试创建一个语法来使用 ANTLR4 定义布尔文字。它可以采用 "BOOL#TRUE" 或 "TRUE" 的形式。
如果我将它定义为这样的词法规则:
Bool_Literal : ( 'BOOL' '#' )? ( 'FALSE' | 'TRUE' );
Antlr 无法匹配输入:
isHigh := FALSE;
错误是 "mismatched input 'FALSE' expecting Bool_Literal"。
但如果我将其更改为语法规则:
bool_literal : ( 'BOOL' '#' )? ( 'FALSE' | 'TRUE' );
它可以正确拾取 "BOOL#FALSE" 或 "FALSE"。
词法规则似乎无法检测到以可选部分开头的标记,有人知道为什么吗?
谢谢!
韦恩
这是我的语法:
grammar TT;
pou
: assignment +
;
assignment : Identifier ':=' expression ';' ;
expression : primary_expr ;
primary_expr : Bool_Literal;
//bool_literal : ( 'BOOL' '#' )? ( 'FALSE' | 'TRUE' );
// lexical
fragment Letter : [a-zA-Z]|'_' ;
fragment Digit : [0-9];
fragment Bit : [0-1];
fragment Octal_Digit : [0-7];
fragment Hex_Digit : [0-9a-fA-F];
Identifier : Letter (Letter|Digit)*;
Bool_Literal : ( 'BOOL' '#' )? ( 'FALSE' | 'TRUE' );
WS : [ \n\r\t]+ -> channel(HIDDEN) ;
Comment : '//' .*? '\n' -> channel(HIDDEN); // channel COMMENTS) //
EOL : '\n';
我的测试输入:
isLow := BOOL#TRUE;
isLow2 := BOOL#FALSE;
isHigh := FALSE;
Antlr 与大多数词法扫描器生成器一样,优先考虑与标记匹配的第一条规则,以防最长可能的标记可以被两个或更多规则匹配。
在您的语法中,TRUE
和 FALSE
可以作为标识符或布尔文字进行匹配。由于标识符规则在语法中较早出现,因此它将获胜,因此 FALSE
将成为标识符。
所以把 Bool_literal
规则放在 bool_literal
规则出现的地方——或者至少在 identifier
规则之前——然后它就会取而代之。
参见 this Antlr4 FAQ 中的问题 "Why are my keywords being treated as identifiers?"。
我正在尝试创建一个语法来使用 ANTLR4 定义布尔文字。它可以采用 "BOOL#TRUE" 或 "TRUE" 的形式。
如果我将它定义为这样的词法规则:
Bool_Literal : ( 'BOOL' '#' )? ( 'FALSE' | 'TRUE' );
Antlr 无法匹配输入:
isHigh := FALSE;
错误是 "mismatched input 'FALSE' expecting Bool_Literal"。
但如果我将其更改为语法规则:
bool_literal : ( 'BOOL' '#' )? ( 'FALSE' | 'TRUE' );
它可以正确拾取 "BOOL#FALSE" 或 "FALSE"。
词法规则似乎无法检测到以可选部分开头的标记,有人知道为什么吗?
谢谢!
韦恩
这是我的语法:
grammar TT;
pou
: assignment +
;
assignment : Identifier ':=' expression ';' ;
expression : primary_expr ;
primary_expr : Bool_Literal;
//bool_literal : ( 'BOOL' '#' )? ( 'FALSE' | 'TRUE' );
// lexical
fragment Letter : [a-zA-Z]|'_' ;
fragment Digit : [0-9];
fragment Bit : [0-1];
fragment Octal_Digit : [0-7];
fragment Hex_Digit : [0-9a-fA-F];
Identifier : Letter (Letter|Digit)*;
Bool_Literal : ( 'BOOL' '#' )? ( 'FALSE' | 'TRUE' );
WS : [ \n\r\t]+ -> channel(HIDDEN) ;
Comment : '//' .*? '\n' -> channel(HIDDEN); // channel COMMENTS) //
EOL : '\n';
我的测试输入:
isLow := BOOL#TRUE;
isLow2 := BOOL#FALSE;
isHigh := FALSE;
Antlr 与大多数词法扫描器生成器一样,优先考虑与标记匹配的第一条规则,以防最长可能的标记可以被两个或更多规则匹配。
在您的语法中,TRUE
和 FALSE
可以作为标识符或布尔文字进行匹配。由于标识符规则在语法中较早出现,因此它将获胜,因此 FALSE
将成为标识符。
所以把 Bool_literal
规则放在 bool_literal
规则出现的地方——或者至少在 identifier
规则之前——然后它就会取而代之。
参见 this Antlr4 FAQ 中的问题 "Why are my keywords being treated as identifiers?"。