注释的antlr语法和标记之间的纯文本

注释的antlr语法和标记之间的纯文本,antlr,antlr4,Antlr,Antlr4,后续问题: 1.我用了一条规则 COMMENT:START_1_TAG START_COMMENT END_1_TAG.*?开始标记结束注释结束标记->跳过 使用我的lexer跳过任何评论。 但是,当我在标记中留出任何空间时,我会得到一个不匹配的输入 我的Lexer的相关部分是: lexer grammar DemoLexer; START_1_TAG : '<%' -> pushMode(IN_TAG); START_2_TAG : '<<' -> pushMo

后续问题:

1.我用了一条规则

COMMENT:START_1_TAG START_COMMENT END_1_TAG.*?开始标记结束注释结束标记->跳过

使用我的lexer跳过任何评论。 但是,当我在标记中留出任何空间时,我会得到一个不匹配的输入

我的Lexer的相关部分是:

lexer grammar DemoLexer;

START_1_TAG : '<%' -> pushMode(IN_TAG);
START_2_TAG : '<<' -> pushMode(IN_TAG);

COMMENT : START_1_TAG START_COMMENT END_1_TAG .*? START_2_TAG END_COMMENT END_2_TAG  -> skip;

TEXT        : ( ~[<] | '<' ~[<%] )+;

mode IN_TAG;
START_COMMENT : 'startcomment' ;
END_COMMENT : 'endcomment' ;
ID         : [A-Za-z_][A-Za-z0-9_]*;
INT_NUMBER : [0-9]+;
END_1_TAG  : '%>' -> popMode;
END_2_TAG  : '>>' -> popMode;
SPACE      : [ \t\r\n] -> channel(HIDDEN);
在我的字典里

RAW_TAG_START : '<%' 'startraw' '%>' -> pushMode(RAW_MODE);
RAW_TAG_END : '<%' 'endraw' '%>' -> popMode; 
mode RAW_MODE;
  RAW_TEXT : .*? ;
RAW\u标签\u开始:“”->pushMode(RAW\u模式);
原始标签结束:“”->popMode;
模式RAW_模式;
原始文本:*;
出于某种原因,当我尝试用intellij antlr插件解析这个时,每当我尝试匹配rawText规则时,它似乎都会冻结并崩溃

这是正确的处理方法吗

不,我想说不是。在本例中,它不仅仅是一个普通的注释,而是一个表示注释的常规标记。因此,我会将其视为任何其他标记(在解析器中定义,而不是在lexer中定义)

出于某种原因,当我尝试用intellij antlr插件解析这个时,每当我尝试匹配rawText规则时,它似乎都会冻结并崩溃

这可能是因为:
RAW_TEXT:.*

我会这样做:

lexer语法DemoLexer;
开始\u 1 \u标记:“”->popMode;
END_2_标记:'>>'->popMode;
空间:[\t\r\n]->通道(隐藏);
原始模式;
结束\u原始:“”->popMode,popMode;//弹出两次:退出原始和进入标签!
任何原料:.;//没有“+”或“*”,只有一个令牌!
演示解析器:

语法分析器;
选择权{
tokenVocab=解复用器;
}
代码
:代码块*EOF
;
代码块
:文本
|tag1Ops
|tag2Ops
;
tag1Ops
:rawTag
|评论标签
|其他标签
;
罗塔格
:开始\u 1 \u标记开始\u原始任何\u原始*结束\u原始
;
评论标签
:开始\标记开始\注释结束\标记文本开始\标记结束\注释结束\标记
;
其他标签
:开始\u 1_标记开始\u ID结束\u 1_标记文本开始\u 1_标记结束\u ID结束\u 1_标记
;
tag2Ops
:START_2_TAG START_ID END_2_TAG TEXT START_2_TAG END_ID END_2_TAG
;
还有一个小的主类来测试这一切:

import org.antlr.v4.runtime.*;
导入org.antlr.v4.runtime.tree.ParseTree;
公共班机{
公共静态void main(字符串[]args){
String source=“aaa原始”+
“bbb”+
“福”+
“ccc”+
“评论”+
“ddd”;
DemoLexer lexer=新的DemoLexer(CharStreams.fromString(source));
DemoParser=newdemoparser(newcommontokenstream(lexer));
ParseTree=parser.code();
System.out.println(tree.toStringTree(解析器));
}
}
将打印:

(代码
(代码块aaa)
(代码块(tag1Ops(rawTag R A W)))
(代码块bbb)
(代码块(tag1Ops(othertagfoo)))
(代码块ccc)
(代码块(标记1ops(注释标记注释)))
(代码块ddd)
)
(为了清晰起见,我添加了一些手动换行符)

ANTLR IntelliJ插件也可以解决这个问题:

编辑 如果您在lexer中设置了
skip
ping注释(我不会这么做),那么您可以这样做:

lexer语法DemoLexer;
注释:“”。*?“”->跳过
START_1_标记:“popMode,popMode;

SAFE_RAW:(~[我试图在lexer中传递注释的原因是,它可以包含任何内容,包括“嗨,谢谢你的澄清。我在你之前的一个问题答案中读到,lexer规则中的“.”表示单个字符,而解析器规则中的“.”定义一个标记。(或者这是我从你的答案中推测的)因此,根据我的理解,任何原始规则都与任何单个字符匹配,或者我误解了什么吗?
ANY\u RAW:;//没有“+”或“*”,只有一个标记!
而且,从我之前的评论来看,原始标记中的文本内容不应该是单个标记,而不是多个标记吗?不,当lexer位于\u RAW的
中时e> 模式下,它应该匹配原始标记的结尾或单个字符(无论它是什么字符)。然后在解析器中,您“粘合”这些
任何\u raw
标记(它们是单个字符)一起。请注意,当处于原始模式时,lexer总是生成
任何\u raw
标记,因此不需要在解析器中执行
*?
+?
操作。在解析器中执行
任何\u raw*
操作非常简单,如我的示例所示。顺便问一下,这是什么模板语言?[…]或者我误解了什么?”,不,你没有误解。我的印象是,将内容作为单个令牌,比将其作为令牌列表更有效。它类似于Liquid。我也从你的liqp存储库中获取了一些参考。
RAW_TAG_START : '<%' 'startraw' '%>' -> pushMode(RAW_MODE);
RAW_TAG_END : '<%' 'endraw' '%>' -> popMode; 
mode RAW_MODE;
  RAW_TEXT : .*? ;