Antlr 如何标记块(注释、字符串等)以及块间(块外的任何字符)?
我需要标记所有“在”任何评论之外的内容,直到行尾。例如:Antlr 如何标记块(注释、字符串等)以及块间(块外的任何字符)?,antlr,antlr4,lexer,Antlr,Antlr4,Lexer,我需要标记所有“在”任何评论之外的内容,直到行尾。例如: take me */ and me /* but not me! */ I'm in! // I'm not... 标记为(STR是“外部”字符串,BC是块注释,LC是单行注释): 以及: 标记为: { BC : " starting with don't take me ", STR: " ...take me..." } 问题是STR可以是除注释之外的任何,并且由于注释开头不是单字符标记,我不能对STR使用否定规则
take me */ and me /* but not me! */ I'm in! // I'm not...
标记为(STR
是“外部”字符串,BC
是块注释,LC
是单行注释):
以及:
标记为:
{
BC : " starting with don't take me ",
STR: " ...take me..."
}
问题是STR
可以是除注释之外的任何,并且由于注释开头不是单字符标记,我不能对STR
使用否定规则
我想也许可以做一些类似的事情:
STR : { IsNextSequenceTerminatesThe_STR_rule(); }?;
但我不知道如何在lexer actions中寻找角色
甚至可以用ANTLR4 lexer实现吗?如果可以,那么如何实现呢?试试下面的方法:
grammar T;
@lexer::members {
// Returns true iff either "//" or "/*" is ahead in the char stream.
boolean startCommentAhead() {
return _input.LA(1) == '/' && (_input.LA(2) == '/' || _input.LA(2) == '*');
}
}
// other rules
STR
: ( {!startCommentAhead()}? . )+
;
是的,可以执行您正在尝试的标记化 基于上述内容,您需要嵌套注释。这些只能在lexer中实现,而无需操作、谓词或任何代码。为了有嵌套的注释,如果不使用贪婪/非贪婪的ANTLR选项,就更容易了。您需要将其指定/编码到lexer语法中。下面是你需要的三条lexer规则。。。使用STR定义 我添加了一个用于测试的解析器规则。我还没有测试过这个,但它应该能做你提到的所有事情。此外,它不仅限于“行尾”,如果需要,您可以进行修改
/*
All 3 COMMENTS are Mutually Exclusive
*/
DOC_COMMENT
: '/**'
( [*]* ~[*/] // Cannot START/END Comment
( DOC_COMMENT
| BLK_COMMENT
| INL_COMMENT
| .
)*?
)?
'*'+ '/' -> channel( DOC_COMMENT )
;
BLK_COMMENT
: '/*'
(
( /* Must never match an '*' in position 3 here, otherwise
there is a conflict with the definition of DOC_COMMENT
*/
[/]? ~[*/] // No START/END Comment
| DOC_COMMENT
| BLK_COMMENT
| INL_COMMENT
)
( DOC_COMMENT
| BLK_COMMENT
| INL_COMMENT
| .
)*?
)?
'*/' -> channel( BLK_COMMENT )
;
INL_COMMENT
: '//'
( ~[\n\r*/] // No NEW_LINE
| INL_COMMENT // Nested Inline Comment
)* -> channel( INL_COMMENT )
;
STR // Consume everthing up to the start of a COMMENT
: ( ~'/' // Any Char not used to START a Comment
| '/' ~[*/] // Cannot START a Comment
)+
;
start
: DOC_COMMENT
| BLK_COMMENT
| INL_COMMENT
| STR
;
grammar T;
@lexer::members {
// Returns true iff either "//" or "/*" is ahead in the char stream.
boolean startCommentAhead() {
return _input.LA(1) == '/' && (_input.LA(2) == '/' || _input.LA(2) == '*');
}
}
// other rules
STR
: ( {!startCommentAhead()}? . )+
;
/*
All 3 COMMENTS are Mutually Exclusive
*/
DOC_COMMENT
: '/**'
( [*]* ~[*/] // Cannot START/END Comment
( DOC_COMMENT
| BLK_COMMENT
| INL_COMMENT
| .
)*?
)?
'*'+ '/' -> channel( DOC_COMMENT )
;
BLK_COMMENT
: '/*'
(
( /* Must never match an '*' in position 3 here, otherwise
there is a conflict with the definition of DOC_COMMENT
*/
[/]? ~[*/] // No START/END Comment
| DOC_COMMENT
| BLK_COMMENT
| INL_COMMENT
)
( DOC_COMMENT
| BLK_COMMENT
| INL_COMMENT
| .
)*?
)?
'*/' -> channel( BLK_COMMENT )
;
INL_COMMENT
: '//'
( ~[\n\r*/] // No NEW_LINE
| INL_COMMENT // Nested Inline Comment
)* -> channel( INL_COMMENT )
;
STR // Consume everthing up to the start of a COMMENT
: ( ~'/' // Any Char not used to START a Comment
| '/' ~[*/] // Cannot START a Comment
)+
;
start
: DOC_COMMENT
| BLK_COMMENT
| INL_COMMENT
| STR
;