【发布时间】:2015-01-17 04:09:48
【问题描述】:
我想从 Bison/YACC .y 文件中解析语法定义。规则的语法非常简单(我可以忽略语法规则部分之外的所有内容),并且我不需要有关语义操作的信息。但是,即使跳过这些操作似乎也需要解析任意 C 代码片段以确定 {...} 块的结束位置(因为您可以有嵌套块等)。
是否有不需要解析 C 的快捷方式?
我想一种解决方法是让 Bison 自己删除所有回调,并将语法规则留在文件中,这样解析起来就很简单了。
【问题讨论】:
我想从 Bison/YACC .y 文件中解析语法定义。规则的语法非常简单(我可以忽略语法规则部分之外的所有内容),并且我不需要有关语义操作的信息。但是,即使跳过这些操作似乎也需要解析任意 C 代码片段以确定 {...} 块的结束位置(因为您可以有嵌套块等)。
是否有不需要解析 C 的快捷方式?
我想一种解决方法是让 Bison 自己删除所有回调,并将语法规则留在文件中,这样解析起来就很简单了。
【问题讨论】:
如果您使用-v 标志运行bison,它将生成一个名为basename.output 的文件,该文件以语法开头(没有操作)。解析该报告非常容易。 (basename 是输入文件的名称,如果您指定了 --output 选项,则为输出文件的名称,去掉扩展名。)
唯一的另一种方法是准备复制bison的大部分解析,如果没有完全解析,至少涉及lexing C,以及了解如何解析所有bison 的% 命令。
注意:-v 选项生成的语法将中间规则操作转换为右侧为空的非终结符。生成的非终结符具有$@<number> 或@<number> 形式的名称,因此很容易识别。
【讨论】:
在 flex 中识别和跳过带大括号的 C 代码非常简单:
%x cblk cstr cchr ccom cppcom
%%
int brace_depth;
{ brace_depth=0; BEGIN(cblk);
<cblk>{ brace_depth++;
<cblk>} if (!brace_depth--) BEGIN(INITIAL);
<cblk>\" BEGIN(cstr);
<cblk>\' BEGIN(cchr);
<cblk>\/\* BEGIN(ccom);
<cblk>\/\/ BEGIN(ccpcom);
<cstr,cchr>\\. ;
<cstr>\" BEGIN(cblk);
<cchr>\' BEGIN(cblk);
<ccom>\*\/ BEGIN(cblk);
<cppcom>\n BEGIN(cblk);
<cblk,cchr,cstr,ccom,cppcom>.|\n ;
【讨论】:
\\.) 但不处理 cmets。不过,解决这个问题也很容易。