Parsing ANTLR4中上下文相关的空白处理
我试图在ANTLR4中实现一种表达式/公式语言,但在处理空白方面遇到了问题。在大多数情况下,我不关心空白,所以我有“标准”lexer规则将其发送到隐藏通道,即Parsing ANTLR4中上下文相关的空白处理,parsing,antlr,antlr4,Parsing,Antlr,Antlr4,我试图在ANTLR4中实现一种表达式/公式语言,但在处理空白方面遇到了问题。在大多数情况下,我不关心空白,所以我有“标准”lexer规则将其发送到隐藏通道,即 // Whitespace WS : ( ' ' | '\t' |'\r' | '\n' ) -> channel(HIDDEN) ; 但是,我有一个操作符,它在之前或之后都不允许空白,如果不更改WS-lexer规则,将空白保留在默认通道中,并且在我的所有其他解析器规则中都有显式的WS?术语,我看不到如何处理这
// Whitespace
WS
: ( ' ' | '\t' |'\r' | '\n' ) -> channel(HIDDEN)
;
但是,我有一个操作符,它在之前或之后都不允许空白,如果不更改WS-lexer规则,将空白保留在默认通道中,并且在我的所有其他解析器规则中都有显式的WS?
术语,我看不到如何处理这种情况(有很多)
作为一个简化的示例,我为一种虚构的谓词语言创建了以下语法:
grammar Logik;
/*
* Parser Rules
*/
ruleExpression
: orExpression
;
orExpression
: andExpression ( 'OR' andExpression)*
;
andExpression
: primaryExpression ( 'AND' primaryExpression)*
;
primaryExpression
: variableExpression
| '(' ruleExpression ')'
;
variableExpression
: IDENTIFIER ( '.' IDENTIFIER )*
;
/*
* Lexer Rules
*/
IDENTIFIER
: LETTER LETTERORDIGIT*
;
fragment LETTER : [a-zA-Z_];
fragment LETTERORDIGIT : [a-zA-Z0-9_];
// Whitespace
WS
: ( ' ' | '\t' |'\r' | '\n' ) -> channel(HIDDEN)
;
目前,它成功地解析了
A或B和C.D
以及A或B和C.D
——我需要的是
操作符不允许空白,这样第二个表达式就无效了。您可以使用lexer谓词来执行前向(和后向)和为“.”创建专用标记。在您的示例中,它如下所示:
grammar Logik;
/*
* Parser Rules
*/
ruleExpression
: orExpression
;
orExpression
: andExpression ( 'OR' andExpression)*
;
andExpression
: primaryExpression ( 'AND' primaryExpression)*
;
primaryExpression
: variableExpression
| '(' ruleExpression ')'
;
variableExpression
: IDENTIFIER ( POINT IDENTIFIER )*
;
/*
* Lexer Rules
*/
POINT : {_input.LA(-1) != ' ' && _input.LA(2) != ' '}? '.';
IDENTIFIER
: LETTER LETTERORDIGIT*
;
fragment LETTER : [a-zA-Z_];
fragment LETTERORDIGIT : [a-zA-Z0-9_];
// Whitespace
WS
: ( ' ' | '\t' |'\r' | '\n' ) -> channel(HIDDEN)
;
variableExpression
: IDENTIFIER ( '.' {_input.get(_input.index() -1).getType() != WS}? IDENTIFIER )*
;
这样,A或B和C.D
就可以了,A或B和C.D
会给出一个错误(如A或B和C.D
)比如:令牌识别错误在:'。…
注
可能有办法在语法规则部分使用
隐藏的\u CHANEL
和语义谓词。但是,如果您多次使用相同的约束,您将不得不在每个语法规则中编写谓词,在这些语法规则中应该启用约束 您可以从其他渠道获得令牌,如下所示:
grammar Logik;
/*
* Parser Rules
*/
ruleExpression
: orExpression
;
orExpression
: andExpression ( 'OR' andExpression)*
;
andExpression
: primaryExpression ( 'AND' primaryExpression)*
;
primaryExpression
: variableExpression
| '(' ruleExpression ')'
;
variableExpression
: IDENTIFIER ( POINT IDENTIFIER )*
;
/*
* Lexer Rules
*/
POINT : {_input.LA(-1) != ' ' && _input.LA(2) != ' '}? '.';
IDENTIFIER
: LETTER LETTERORDIGIT*
;
fragment LETTER : [a-zA-Z_];
fragment LETTERORDIGIT : [a-zA-Z0-9_];
// Whitespace
WS
: ( ' ' | '\t' |'\r' | '\n' ) -> channel(HIDDEN)
;
variableExpression
: IDENTIFIER ( '.' {_input.get(_input.index() -1).getType() != WS}? IDENTIFIER )*
;
A或B和C.D
正常且
A或B和C.D
将打印错误可以找到类似的方法,它不直接读取令牌流,而是使用可启用/禁用空白通道的令牌流。