gpt4 book ai didi

c++ - 如何处理 flex 中的嵌套注释

转载 作者:太空宇宙 更新时间:2023-11-03 10:41:48 26 4
gpt4 key购买 nike

我正在为一种支持嵌套注释的语言编写一个 flex 扫描器:

/*
/**/
*/

我曾经在支持递归调用 lex 扫描器的 ocaml/ocamllex 上工作,非常优雅。但是我现在切换到c++/flex,如何处理这样的嵌套注释?

最佳答案

假设只有评论可以嵌套在评论中,堆栈是一个非常昂贵的解决方案,可以用一个简单的计数器来实现。例如:

%x SC_COMMENT

%%
int comment_nesting = 0; /* Line 4 */

"/*" { BEGIN(SC_COMMENT); }
<SC_COMMENT>{
"/*" { ++comment_nesting; }
"*"+"/" { if (comment_nesting) --comment_nesting;
else BEGIN(INITIAL); }
"*"+ ; /* Line 11 */
[^/*\n]+ ; /* Line 12 */
[/] ; /* Line 13 */
\n ; /* Line 14 */
}

一些解释:

第 4 行:第一条规则之前的缩进行被插入到 yylex 函数的顶部,它们可用于声明和初始化局部变量。我们使用它在每次调用 yylex 时将注释嵌套深度初始化为 0。必须保持不变的是 comment_nestingINITIAL 状态下始终为 0。

第 11-13 行:一个更简单的解决方案是单一模式 .|\n。 ,但这会导致每个注释字符都被视为一个单独的子标记。即使相应的 Action 什么都不做,这也会导致扫描循环被中断,并为每个字符执行 Action 切换语句。因此,通常最好同时尝试匹配多个字符。

不过,我们需要注意 /* 字符;我们只能忽略那些我们确定不属于终止(可能嵌套)注释的 */ 的星号。因此第 11 行和第 12 行。(第 12 行不会匹配后跟 / 的星号序列,因为它们已经与上面的第 9 行的模式匹配。)我们需要如果后面没有 *,则忽略 /。因此第 13 行。

第 14 行:但是,匹配太大的标记也可能是次优的。

首先,flex 并未针对大型标记进行优化,评论可能非常大。如果 flex 需要在 token 中间重新填充其缓冲区,它将在新缓冲区中保留打开的 token ,然后从 token 的开头重新扫描。

其次,柔性扫描仪可以自动跟踪当前行号,而且效率相对较高。扫描器仅在与可能匹配换行符的模式匹配的标记中检查换行符。但是需要扫描整场比赛。

我们通过将评论中的换行符匹配为单独的标记来减少这两个问题的影响。 (第 14 行,另见第 12 行)这将 yylineno 扫描限制为单个字符,并且还限制了内部注释标记的预期长度。评论本身可能非常大,但每行可能会限制在合理的长度内,从而避免在缓冲区重新填充时潜在的二次重新扫描。

关于c++ - 如何处理 flex 中的嵌套注释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34493467/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com