首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >我怎样才能打印我在雅克/野牛身上看到的东西?

我怎样才能打印我在雅克/野牛身上看到的东西?
EN

Stack Overflow用户
提问于 2016-03-07 02:20:32
回答 2查看 3.7K关注 0票数 0

我有一个包含一系列规则的复杂的Yacc文件,其中有些规则很复杂,例如:

代码语言:javascript
运行
复制
start: program
program: extern_list class
class: T_CLASS T_ID T_LCB field_dec_list method_dec_list T_RCB

确切的规则和我对它们采取的操作并不重要,因为我想要做的事情看起来相当简单:只要在源文件中打印出程序,就可以使用我为其他目的定义的规则。但我对这么做有多困难感到惊讶。

首先,我尝试将printf("%s%s", $1, $2)添加到上面的第二条规则中。这就产生了“��@P�”。据我所知,解析的文本也可以作为变量yytext使用。我将printf("%s", yytext)添加到文件中的每个规则中,并将extern char* yytext;添加到文件的顶部。这将根据语言的语法从有效文件中生成(null){void)1133331122222210101010--552222202020202222;;;;||||&&&&;;;;;;;;;;}}}}}}}}。最后,我将extern char* yytext;改为了extern char yytext[],认为这没有什么区别。它所产生的输出差异最好用屏幕截图来显示。

我在Xubuntu 14.04上使用Bison3.0.2。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-03-07 02:47:12

如果您只想在解析时将源回显到某个输出,那么在lexer中这样做是最简单的。您并没有说您对lexer使用了什么,但是您提到了yytext,它是由lex/flex使用的,所以我将假设这一点。

当您使用flex识别令牌时,变量yytext引用了内部缓冲区flex用于识别令牌的方法。在令牌的操作中,它可以用于获取令牌的文本,但只能暂时使用--一旦操作完成并读取下一个令牌,它将不再有效。

所以,如果你有一个灵活的规则,比如:

代码语言:javascript
运行
复制
[a-zA-Z_][a-zA-Z_0-9]*    { yylval.str = yytext, return T_ID; }

这很可能根本不起作用,因为你的程序中会有悬空的指针在运行;可能是你看到的随机输出的来源。相反,你需要复制一份。如果您还想不修改地输出输入,也可以在这里这样做:

代码语言:javascript
运行
复制
[a-zA-Z_][a-zA-Z_0-9]*    { yylval.str = strdup(yytext); ECHO; return T_ID; }

这使用了flex宏ECHO,大致相当于fputs(yytext, yyout) --将输入复制到名为yyout (默认为stdout)的FILE *中。

票数 2
EN

Stack Overflow用户

发布于 2016-03-07 02:48:41

如果对应的右手侧的第一个符号是终端,那么bison操作中的$1意味着“扫描仪返回与该终端对应的令牌时产生的yylval值。如果该符号是非终端,则它指在评估减少该非终端的动作时分配给$$的值。如果没有这样的操作,那么默认的$$ = $1将被执行,因此它将通过第一个符号的语义值来减少该非终端。”

如果所有这些都很明显的话,我很抱歉,但是你的片段不足以显示:

  • 每个非终端的语义类型是什么;
  • 每个终端的语义类型是什么;
  • 在扫描仪操作中,给yylval分配了哪些值,如果有的话;
  • 在野牛操作中,如果有什么值分配给$$

如果这些语义类型实际上不是字符串,那么printf显然会产生垃圾。(如果用-Wall编译生成的代码,gcc可能会对此提出警告。尽管在使用旧版本的flex/bison时可能会出现虚假警告,但我认为使用-Wall编译并仔细阅读所产生的警告始终是值得的。

在野牛操作中使用yytext是有问题的,因为它将引用所扫描的最后一个令牌的文本,通常是前瞻性令牌。特别是,在输入的末尾,yytext将是NULL,这就是在输入结束时发生的任何缩减中将得到的内容。glibc的printf实现足够好,可以打印(null)而不是分段错误,当您将(char*)0提供给形成为%s的参数时,但我认为依赖于此并不是一个好主意。

最后,如果您确实有一个char*语义值,并且指定了yylval = yytext (或者如果您使用的是联合),那么您将遇到另一个问题,即yytext指向扫描仪拥有的临时缓冲区,当您使用地址时,该缓冲区的内容可能完全不同。因此,如果要将yytext传递给解析器,则始终需要创建它的副本。

如果您真正想要做的是查看解析器正在做什么,我建议您启用bison的 parser-trace feature。它将为您提供许多有用的信息,而无需将printf插入到您的野牛操作中。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35835192

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档