在 Mathematica 中,注释以 (*
开头并以 *)
结尾并且注释可以嵌套。我目前使用 JFlex 扫描评论的方法包含以下代码
%xstate IN_COMMENT
"(*" { yypushstate(IN_COMMENT); return MathematicaElementTypes.COMMENT;}
<IN_COMMENT> {
"(*" {yypushstate(IN_COMMENT); return MathematicaElementTypes.COMMENT;}
[^\*\)\(]* {return MathematicaElementTypes.COMMENT;}
"*)" {yypopstate(); return MathematicaElementTypes.COMMENT;}
[\*\)\(] {return MathematicaElementTypes.COMMENT;}
. {return MathematicaElementTypes.BAD_CHARACTER;}
}
其中方法
yypushstate
和
yypopstate
被定义为
private final LinkedList<Integer> states = new LinkedList();
private void yypushstate(int state) {
states.addFirst(yystate());
yybegin(state);
}
private void yypopstate() {
final int state = states.removeFirst();
yybegin(state);
}
让我有机会跟踪我正在处理的评论的嵌套级别。
不幸的是,这导致了几个
COMMENT
一个评论的标记,因为我必须匹配嵌套的评论开始和评论结束。
问题: JFlex 是否可以将其 API 与
yypushback
之类的方法一起使用?或
advance()
等在整个评论范围内只返回一个标记,即使评论是嵌套的?
请您参考如下方法:
赏金似乎是不必要的,因为解决方案非常简单,我只是没有考虑。让我解释。扫描简单的嵌套注释时
(* (*..*) *)
我必须跟踪我看到了多少个开始评论标记,以便我最终在最后一个真正的结束评论上可以将整个评论作为一个标记返回。
我没有意识到的是,当 JFlex 匹配某些内容时,不需要告诉它前进到下一部分。仔细查看后发现这是 explained here但有点隐藏在我不关心的部分:
Because we do not yet return a value to the parser, our scanner proceeds immediately.
因此,
flex
中的规则像这样的文件
[^\(\*\)]+ { }
读取所有字符,除了那些可能是注释开始/结束并且什么都不做的字符 但它前进到下一个 token .
这意味着我可以简单地执行以下操作。在
YYINITIAL
状态,我有一个匹配开始注释的规则,但它什么都不做,然后将词法分析器切换到
IN_COMMENT
状态。特别是,它不返回任何 token :
{CommentStart} { yypushstate(IN_COMMENT);}
现在,我们在
IN_COMMENT
州和那里,我也这样做。我吃光了所有字符,但从不返回 token 。当我找到一个新的开场评论时,我小心地将它插入堆栈但什么也不做。只有当我点击
时最后 结束评论,我知道我要离开
IN_COMMENT
状态,这是我最后返回 token 的唯一点。我们来看看规则:
<IN_COMMENT> {
{CommentStart} { yypushstate(IN_COMMENT);}
[^\(\*\)]+ { }
{CommentEnd} { yypopstate();
if(yystate() != IN_COMMENT)
return MathematicaElementTypes.COMMENT_CONTENT;
}
[\*\)\(] { }
. { return MathematicaElementTypes.BAD_CHARACTER; }
}
就是这样。现在,无论您的评论嵌套多深,您总会得到一个包含整个评论的标记。
现在,我很尴尬,很抱歉问这么简单的问题。
最后说明
如果你正在做这样的事情,你必须记住你只有在你点击正确的结束“字符”时才返回一个标记。因此,您绝对应该制定一个捕获文件末尾的规则。在 IDEA 中,默认行为只是返回注释标记,因此您需要另一行(有用与否,我想优雅地结束):
<<EOF>> { yyclearstack(); yybegin(YYINITIAL);
return MathematicaElementTypes.COMMENT;}