ANTLR 3上的ASN.1/SMI注释语法
在ANTLR 2上,注释语法如下所示ANTLR 3上的ASN.1/SMI注释语法,antlr,antlr3,Antlr,Antlr3,在ANTLR 2上,注释语法如下所示 // Single-line comments SL_COMMENT : (options {warnWhenFollowAmbig=false;} : '--'( { LA(2)!='-' }? '-' | ~('-'|'\n'|'\r'))* ( (('\r')? '\n') { newline(); }| '--') ) {$setType(Token.SKIP); } ; 但是,当将其移植到
// Single-line comments
SL_COMMENT
: (options {warnWhenFollowAmbig=false;}
: '--'( { LA(2)!='-' }? '-' | ~('-'|'\n'|'\r'))* ( (('\r')? '\n') { newline(); }| '--') )
{$setType(Token.SKIP); }
;
但是,当将其移植到ANTLR 3时
SL_COMMENT
: (
: '--'( { input.LA(2)!='-' }? '-' | ~('-'|'\n'|'\r'))* ( (('\r')? '\n') | '--') )
{$channel = HIDDEN;}
;
由于没有更多选项{warnWhenFollowAmbig=false;},因此无法正确分析以下注释
-- some comment -- some not comment
那么,为ANTLR 3定义此SL_注释规则的可能方式是什么?我终于找到了一个解决方案 SL_评论 :注释({input.LA(2)!='-'}?'-')=>'-'| ~('-'|'\n'|'\r'))*((('\r')?'\n')|注释) {$channel=HIDDEN;}
; 就我个人而言,我喜欢让语法规则尽可能“空”。在本例中,我将创建一个lexer方法,如果输入中的下两个字符是
“--”
,则该方法将返回true
。只要不是这种情况,请匹配除\r
和\n
以外的任何字符,并重复零次或多次,直到遇到可选的“-”
。请注意,我没有在末尾添加新行,因为末尾不一定有新行(也可能是EOF
)。此外,\r
和\n
很可能会与空间
规则相匹配,该规则放在隐藏
频道上:因此按照我的建议这样做没有害处
演示:
...
@lexer::members {
private boolean endCommentAhead() {
return input.LA(1) == '-' && input.LA(2) == '-';
}
}
...
SL_COMMENT
: '--' ({!endCommentAhead()}?=> ~('\r' | '\n'))* '--'?
;
...
如果您不喜欢lexer members块,只需执行以下操作:
SL_COMMENT
: '--' ({!(input.LA(1) == '-' && input.LA(2) == '-')}?=> ~('\r' | '\n'))* '--'?
;
编辑
一个完整的小演示:
grammar T;
@parser::members {
public static void main(String[] args) throws Exception {
String source = "12 - 34 -- foo - bar -- 42 \n - - 5678 -- more comments 666\n--\n--";
TLexer lexer = new TLexer(new ANTLRStringStream(source));
TParser parser = new TParser(new CommonTokenStream(lexer));
parser.parse();
}
}
@lexer::members {
private boolean endCommentAhead() {
return input.LA(1) == '-' && input.LA(2) == '-';
}
}
parse
: (t=. {System.out.printf("\%-15s\%s\n", tokenNames[$t.type], $t.text);})* EOF
;
SL_COMMENT
: '--' ({!endCommentAhead()}?=> ~('\r' | '\n'))* '--'?
;
MINUS
: '-'
;
INT
: '0'..'9'+
;
SPACE
: (' ' | '\t' | '\r' | '\n') {skip();}
;
在解析输入之后:
12 - 34 -- foo - bar -- 42
- - 5678 -- more comments 666
12-34--foo-bar--42
--5678--更多评论666
将打印:
INT 12
MINUS -
INT 34
SL_COMMENT -- foo - bar --
INT 42
MINUS -
MINUS -
INT 5678
SL_COMMENT -- more comments 666
SL_COMMENT --
SL_COMMENT --
INT 12
减去-
INT 34
SL_注释——foo-bar--
INT 42
减去-
减去-
国际电话5678
SL_评论——更多评论666
SL_评论--
SL_注释——我将检查这是否通过了我很快创建的所有测试用例。不幸的是,这条规则没有通过所有测试用例。例如,如果此行仅包含“---”,则此规则不会将其视为注释。因此,仍然需要使用(((“\r”)?“\n”)|注释)作为结尾。@LexLi,呃,不,这是不正确的。只有
“--”
后跟换行符或EOF
都将标记为SL\u COMMENT
。我编辑了我的答案来展示这个。嗨,巴特,谢谢你再次访问它。我仍然感到奇怪的是,在我的测试中,这个失败了。完整的语法在这里。如果您将SL_注释更改为您的版本,然后使用此文本“bytesAvailAlert TRAP-TYPE\n ENTERPRISE alerts\n--\n::=1”进行测试,并根据“assignment”规则进行测试,“--”部分将阻止此完整规则按预期工作。好吧,我所能说的是,我的建议是正确的,你可以通过运行我发布的演示来验证你自己。您的语法看起来很奇怪:它包含一些额外的冒号(在WS
规则中,以及其他一些规则中),并且您使用了v2关键字protected
,而不是v3片段。不确定这对您的解析器有多大影响。。。