匹配以开头的注释行的ANTLR语法#

匹配以开头的注释行的ANTLR语法#,antlr,antlr4,Antlr,Antlr4,我试图用ANTLR语法匹配以下文本: ANTLR语法是: grammar header; start : commentBlock EOF; commentBlock : CommentLine+; CommentLine : '#' AsciiChars+; AsciiChars : [a-zA-Z]; fragment CR : '\r'; fragment LF : '\n'; EOL : CR?LF ->skip; fragment Tab : '\t

我试图用ANTLR语法匹配以下文本:

ANTLR语法是:

grammar header;


start : commentBlock
        EOF;

commentBlock : CommentLine+;
CommentLine  : '#' AsciiChars+;
AsciiChars : [a-zA-Z];

fragment CR : '\r';
fragment LF : '\n';
EOL : CR?LF ->skip;

fragment Tab : '\t';
fragment Space : ' ';
TS : (Tab|Space)+ ->skip;
我得到的错误是:

line 1:0 token recognition error at: '# '
line 2:0 token recognition error at: '# '
line 3:0 token recognition error at: '# '
[@0,2:2='a',<AsciiChars>,1:2]
[@1,7:7='b',<AsciiChars>,2:2]
[@2,12:12='c',<AsciiChars>,3:2]
[@3,15:14='<EOF>',<EOF>,4:0]
line 1:2 mismatched input 'a' expecting CommentLine
但实际上我想放弃所有的注释行。如果必须是解析器规则,我不能使用
->skip
放弃它

加2 我想我现在可以解释了

需要记住的关键事项是:

  • lexer阶段发生在解析器阶段之前
  • 如果跳过的标记T1被另一个lexer规则引用,比如标记T2,那么标记T2中的标记T1部分将不被跳过
让我用一个简明的例子来解释:

要匹配的文档:

#   abc
语法1:

grammar test;

t : T2;
p : t
    EOF;

Char : [a-z];

T2 : '#' T1+ Char+; // <<<< Here T2 reference the so-skipped T1.

fragment Tab : '\t';
fragment Space : ' ';
T1 : (Tab|Space)+ ->skip; //<<<<< T1 is to be skipped.
语法测试;
t:T2;
p:t
EOF;
字符:[a-z];

T2:“#”T1+Char+;// 您的语法在注释中不包含空格,但注释中包含空格


编辑:您是否尝试过
commentLine:“#”的AsciiChars作为注释规则?

也许您正在寻找:

grammar Header;

start : CommentLine+ EOF;

CommentLine  : '#' ' ' AsciiChars+;
AsciiChars : [a-zA-Z];

fragment CR : '\r';
fragment LF : '\n';
EOL : CR?LF ->skip;

fragment Tab : '\t';
fragment Space : ' ';
TS : (Tab|Space)+ ->skip; 
现在这个只使用了一个lexer规则

忽略评论 这将完全忽略这些逗号,并且实际上会给出一个编写时的错误,因为规则
的start
需要一个
注释行,该注释行现在被丢弃。因此,如果您想忽略并丢弃注释,请使用类似于第二个注释的内容,不要在解析器规则中提及
CommentLine
,只需让lexer去掉它们即可。或者,如果要保留注释,可以使用上一个注释

重新路由评论 最后一个想法是将评论重新路由到另一个频道:

grammar Header;

start : other EOF;
other: AsciiChars;
CommentLine  : '#' ' ' AsciiChars+ -> channel(2);
AsciiChars : [a-zA-Z]+;

fragment CR : '\r';
fragment LF : '\n';
EOL : CR?LF ->skip;

fragment Tab : '\t';
fragment Space : ' ';
TS : (Tab|Space)+ ->skip;
在这种语法中,注释仍然是经过词法分析的,但会被路由到另一个通道进行可能的处理。我在中添加了另一条规则
开始
这样就有了可匹配的内容:

# a
# b
something
# c

[@0,0:2='# a',<CommentLine>,channel=2,1:0]
[@1,5:7='# b',<CommentLine>,channel=2,2:0]
[@2,10:18='something',<AsciiChars>,3:0]
[@3,21:23='# c',<CommentLine>,channel=2,4:0]
[@4,26:25='<EOF>',<EOF>,5:0]
#a
#b
某物
#c
[@0,0:2='#a',channel=2,1:0]
[@1,5:7='#b',channel=2,2:0]
[@2,10:18='something',3:0]
[@3,21:23='#c',channel=2,4:0]
[@4,26:25='',,5:0]

这些选项中的一个肯定会为您带来好处;)

试试看:您的注释似乎与普通单行注释相同,将
'.
替换为
'/'
。如果散列后需要空格,请使用:
“#”
。如果您要求散列在第1列中,请使用:
[\n\r]'.\35;'~[\ n\r]
。从示例来看,这应该涵盖所有可能的选项

COMMENT_LINE
    : '#'  ~[\n\r]* ->( skip )
    ;

谢谢,但我确实用
TS
匹配了所有空格,并用
->skip
转储了它们。这发生在语法分析器阶段之前的词法阶段。因此,我认为我不需要在解析器规则中指定空格。您的注释规则是后跟ASCII字符的
,而
TS
规则不包括在内。ANTLR将
“#”
(a
#
和一个空格)声明为错误。我尝试了。错误更改为
缺少TS
。我想这是因为我在词汇阶段把它们甩了。所以解析器阶段不会看到它。将
TS
规则放在注释规则前面。您还可以在注释规则
commentLine:'#'[A-Za-z]*中包含空格,这应该允许在注释中使用空格。我想这应该可以。但我不知道为什么将lexer规则
CommentLine
更改为解析器规则
CommentLine
可以让它工作?实际上我想放弃所有的评论。如果必须是解析器规则,我不能使用
->skip
。您不必使用匹配的解析器规则。您可以在侦听器或访问者中忽略它。不过,还有其他方法可以做到这一点,请给我一分钟时间。请务必查看我在下面建议的许多选项。当然,在某个地方有一个“接受”——我还可以帮助您获得接受;)
grammar Header;

start : CommentLine+ EOF;

CommentLine  : '#' ' ' AsciiChars+ -> skip;
AsciiChars : [a-zA-Z];

fragment CR : '\r';
fragment LF : '\n';
EOL : CR?LF ->skip;

fragment Tab : '\t';
fragment Space : ' ';
TS : (Tab|Space)+ ->skip;
grammar Header;

start : other EOF;
other: AsciiChars;
CommentLine  : '#' ' ' AsciiChars+ -> channel(2);
AsciiChars : [a-zA-Z]+;

fragment CR : '\r';
fragment LF : '\n';
EOL : CR?LF ->skip;

fragment Tab : '\t';
fragment Space : ' ';
TS : (Tab|Space)+ ->skip;
# a
# b
something
# c

[@0,0:2='# a',<CommentLine>,channel=2,1:0]
[@1,5:7='# b',<CommentLine>,channel=2,2:0]
[@2,10:18='something',<AsciiChars>,3:0]
[@3,21:23='# c',<CommentLine>,channel=2,4:0]
[@4,26:25='<EOF>',<EOF>,5:0]
COMMENT_LINE
    : '#'  ~[\n\r]* ->( skip )
    ;