ade*_*rge 14 c comments multiline bison flex-lexer
我正在尝试在我的flex(.l)文件中解析C风格的多行注释:
%s ML_COMMENT
%%
...
<INITIAL>"/*" BEGIN(ML_COMMENT);
<ML_COMMENT>"*/" BEGIN(INITIAL);
<ML_COMMENT>[.\n]+ { }
Run Code Online (Sandbox Code Playgroud)
我没有返回任何令牌,我的语法(.y)也没有以任何方式处理评论.
当我运行我的可执行文件时,我得到一个解析错误:
$ ./a.out
/*
abc
def
Parse error: parse error
$ echo "/* foo */" | ./a.out
Parse error: parse error
Run Code Online (Sandbox Code Playgroud)
(我的yyerror函数执行printf("解析错误:%s \n"),这是冗余错误消息的前半部分来自).
我可以看到为什么第二个示例失败,因为整个输入是注释,并且由于语法忽略了注释,因此没有语句.因此输入不是有效的程序.但是在我完成评论之前,第一部分抛出了一个解析错误.
同样令人困惑:
$ ./a.out
/* foo */
a = b;
Parse error: parse error
Run Code Online (Sandbox Code Playgroud)
在这种情况下,注释在实际有效输入之前关闭(没有注释,解析就好了).解析"a"后实际发生失败,而不是在尝试解析赋值"a = b;"之后.如果我在自己的行上输入"a",它仍然会抛出错误.
鉴于错误消息是解析器错误而不是扫描程序错误,我的.y文件中是否存在一些至关重要的内容?或者我在扫描器规则中做错了什么传播到解析器端?
编辑: Per @ Rudi的建议,我打开调试,发现:
$ ./a.out
Starting parse
Entering state 0
Reading a token: /*
foo
Next token is 44 (IDENTIFER)
Shifting token 44 (IDENTIFER), Entering state 4
Reducing via rule 5 (line 130), IDENTIFER -> identifier
state stack now 0
Entering state 5
Run Code Online (Sandbox Code Playgroud)
我关闭了调试,发现/* foo */ = bar;确实解析相同foo = bar;.我正在使用flex 2.5.4; 它没有给我任何关于我试图使用的有状态规则的警告.
以这种方式解析注释可能会导致错误,因为:
在我的解析器中,我处理这样的评论.首先为注释的开头定义lex规则,如下所示:
\/\* {
if (!SkipComment())
return(-1);
}
\/\/ {
if (!SkipLine())
return(-1);
}
Run Code Online (Sandbox Code Playgroud)
然后编写SkipComment和SkipLine函数.他们需要消耗所有输入,直到找到注释的结尾(这是相当古老的代码,所以请原谅我有些过时的结构):
bool SkipComment (void)
{
int Key;
Key=!EOF;
while (true)
{
if (Key==EOF)
{
/* yyerror("Unexpected EOF within comment."); */
break;
}
switch ((char)Key)
{
case '*' :
Key=input();
if (char)Key=='/') return true;
else continue;
break;
case '\n' :
++LineNr;
break;
}
Key=input();
}
return false;
}
bool SkipLine (void)
{
int Key;
Key=!EOF;
while (true)
{
if (Key==EOF)
return true;
switch ((char)Key)
{
case '\n' :
unput('\n');
return true;
break;
}
Key=input();
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
我认为您需要将ML_COMMENT启动条件声明为独占启动条件,因此只有ML_COMMENT规则处于活动状态.%x ML_COMMENT代替%s ML_COMMENT
否则,没有开始条件的规则也是活动的.