我使用上述正则表达式在Flex中标识多行注释:
[/][*][^*]*[*]+([^*/][^*]*[*]+)*[/] { /* DO NOTHING */ }
但是在我看来,flex / bison没有正确返回线路计数器。例如:
输入:
1 ___bqmu7ftc
2 // _qXnFEgQL9Zsyn8Ohtx7zhToLK68xbu3XRrOvRi
3 /* "{ output 6 = <=W if u7 do nN)T!=$||JN,a9vR)7"
4 -758939
5 -31943.6165480
6 // "RND"
7 '_'
8 */
9 [br _int]
输出:
1 TK_IDENT [___bqmu7ftc]
4 [
4 TK_IDENT [br]
4 TK_IDENT [_int]
4 ]
该行应为9而不是4。
有什么想法吗?
我不知道您如何在问题中生成测试输出,但是这是(几乎)如何使用yylineno
的最小示例。对我来说效果很好:
%{
#define ID 257
%}
%option yylineno
%option noinput nounput noyywrap
%%
[[:space:]]+ { /* DO NOTHING */ }
"//".* { /* DO NOTHING */ }
[/][*][^*]*[*]+([^*/][^*]*[*]+)*[/] { /* DO NOTHING */ }
[[:alpha:]_][[:alnum:]_]* { return ID; }
. { return *yytext; }
%%
int main(int argc, char** argv) {
for (;;) {
int token = yylex();
switch (token) {
case 0: printf("%4d: %s\n", yylineno, "EOF"); return 0;
case ID: printf("%4d: %-4s[%s]\n", yylineno, "ID", yytext); break;
default: printf("%4d: %c\n", yylineno, token); break;
}
}
}
这是我在Flex manual上找到的解决方案
记住在定义范围内声明int comment_caller;
。
%x comment
%x foo
%%
"/*" {comment_caller = INITIAL;
BEGIN(comment);
}
<foo>"/*" {
comment_caller = foo;
BEGIN(comment);
}
<comment>[^*\n]* {}
<comment>"*"+[^*/\n]* {}
<comment>\n {++line_num;}
<comment>"*"+"/" BEGIN(comment_caller);
我在使用flex多行注释时遇到了同样的问题。我使用了this stackoverflow question中建议的正则表达式(与您在此问题中提到的正则表达式相同)
此正则表达式还在多行注释中获得了新行。因此,如果您用\ n计算当前行的数量,则会遇到麻烦。因为可能存在多行注释,并且正则表达式会一次选择整个多行注释。因此,它不允许您计算新行。
因此,我找到了另一种方法来保持行数,即使使用正则表达式也是如此。在下面解释:
[您知道flex将匹配的表达式保留在yytext
变量中。因此,我们可以在多行注释中计算新行的数量,并且该代码与我测试的任何代码均能完美配合。这是我的代码:注意:numberOfCurrentLine
变量是我用来保存当前行号的全局变量。
[/][*][^*]*[*]+([^*/][^*]*[*]+)*[/] {
// The code below, the counts number of occurance of \n and then adds
// the number to the numberOfCurrentLine variable
// to keep the number of current line
char* str = yytext;
int i = 0;
char *pch=strchr(str,'\n');
while (pch!=NULL) {
i++;
pch=strchr(pch+1,'\n');
}
numberOfCurrentLine+=i;
}
此代码计算所选注释中的\ n数,并将其添加到正在计算当前行数的全局变量中。
我上面使用的用于计算char出现次数的代码来自this post。因此,使用上面的代码,我总是可以得到当前行的正确编号,并且代码可以完美运行。