我正在尝试为QuickBasic创建一个解析器,这是我尝试获取注释:
grammar QuickBasic;
options
{
language = 'CSharp2';
output = AST;
}
tokens
{
COMMENT;
}
parse
: .* EOF
;
// DOESN'T WORK
Comment
: R E M t=~('\n')* { Text = $t; } -> ^(COMMENT $t)
| Quote t=~('\n')* { Text = $t; } -> ^(COMMENT $t)
;
Space
: (' ' | '\t' | '\r' | '\n' | '\u000C') { Skip(); }
;
fragment Quote : '\'';
fragment E : 'E' | 'e';
fragment M : 'M' | 'm';
fragment R : 'R' | 'r';
即使我只使用令牌COMMENT重写,仅此而且我仍然会遇到同样的错误。
// It DOESN'T WORK EITHER
Comment
: (R E M | Quote) ~('\n')* -> ^(COMMENT)
;
如果我放弃重写,它就有效:
// THIS WORKS
Comment
: (R E M | Quote) ~('\n')*
;
答案 0 :(得分:3)
重写规则仅适用于解析器规则,而不适用于词法分析器规则。并且t=~('\n')*
只会将最后一个非换行符存储在t
- 标签中,因此无论如何都不会有效。
但为什么不一起跳过这些Comment
令牌。如果您将它们留在令牌流中,则需要在所有解析器规则中考虑Comment
令牌(其中Comment
令牌有效):不是您想要的,对吧?
要跳过,只需在规则末尾调用Skip()
:
Comment
: R E M ~('\r' | '\n')* { Skip(); }
| Quote ~('\r' | '\n')* { Skip(); }
;
或更简洁:
Comment
: (Quote | R E M) ~('\r' | '\n')* { Skip(); }
;
但是,如果您真的热衷于在流中留下Comment
令牌并删除"rem"
或评论中的引文,请执行以下操作:
Comment
: (Quote | R E M) t=NonLineBreaks { Text = $t.text; }
;
fragment NonLineBreaks : ~('\r' | '\n')+;
然后,您还可以创建一个解析器规则,以COMMENT
为根创建AST(虽然我没有看到仅仅使用Comment
的好处):
comment
: Comment -> ^(COMMENT Comment)
;