首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >让Bison接受另一个EOF令牌

让Bison接受另一个EOF令牌
EN

Stack Overflow用户
提问于 2017-04-28 20:05:44
回答 2查看 838关注 0票数 1

我正在用C++编写一个ansi-C解析器,其中包含了flex和bison;它非常复杂。

我遇到的问题是编译错误。错误在下面,这是因为yy_terminate返回YY_NULL,定义为( int) 0yylex具有yy::AnsiCParser::symbol_type的返回类型。yy_terminate();是flex生成的扫描仪中<<EOF>>令牌的自动操作。显然,这会导致类型问题。

我的扫描器不会为EOF生成任何特殊的令牌,因为EOF在C语法中没有用途。我可以为<<EOF>>创建一个令牌规则,但是如果忽略它,扫描器就会在yylex中挂起无限循环,在YY_STATE_EOF(INITIAL)的情况下。

编译错误,

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ansi-c.yy.cc: In function ‘yy::AnsiCParser::symbol_type yylex(AnsiCDriver&):
ansi-c.yy.cc:145:17: error: could not convert ‘0’ from ‘int’ to ‘yy::AnsiCParser::symbol_type {aka yy::AnsiCParser::basic_symbol<yy::AnsiCParser::by_type>}’
ansi-c.yy.cc:938:30: note: in expansion of macro ‘YY_NULL’
ansi-c.yy.cc:1583:2: note: in expansion of macro ‘yyterminate’

另外,Bison为我的开始规则(translation_unit)和EOF ($end)生成这个规则。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$accept: translation_unit $end

因此,yylex必须为EOF返回一些东西,否则解析器将永远不会停止等待输入,但是我的语法不能支持EOF令牌。有什么方法可以让Bison在不修改语法的情况下识别0以外的$end条件呢?

或者,我是否可以从扫描仪中的<<EOF>>令牌返回满足Bison $end条件的简单内容?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-04-28 23:23:31

通常,您不会在词法分析器中包含显式EOF规则,这不是因为它没有用途,而是因为缺省值正是您想要做的。(它的目的是表示输入是完整的;否则,解析器将接受某些无效程序的有效前缀。)

不幸的是,C++接口可能会破坏默认EOF操作的简单方便性,即返回0(或NULL)。根据您的问题描述,我假设您已经要求bison使用完全符号生成一个解析器。在这种情况下,您不能简单地从yylex返回0,因为解析器需要一个完整的符号,这是一个比int更复杂的类型(虽然报告EOF的令牌通常没有语义值,但是如果您使用的是本地语言,它确实有一个位置)。对于其他令牌类型,bison将自动生成一个函数,该函数生成一个令牌,名为make_FOO_TOKEN,您将在扫描仪操作中为FOO_TOKEN调用该函数。

虽然C bison解析器确实自动定义文件令牌的结尾(称为END),但C++接口似乎没有。因此,您需要在野牛输入文件中的%token声明中手动定义它:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
%token END 0 "end of file"

(它定义了整数值为0的令牌类型END和人类可读的标签"end of file“)。0是强制性的。)

完成此操作后,可以在flex输入文件中添加显式EOF规则:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<<EOF>> return make_END();

如果您使用的是位置,您还必须给make_END一个位置参数。

票数 1
EN

Stack Overflow用户

发布于 2021-06-12 12:44:01

以下是防止编译器错误的另一种方法-- could not convert 0 from int to ...symbol_type --将yyterminate宏的重新定义放在您重新定义YY_DECL的位置下面

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// change curLocation to the name of the location object used in yylex
// qualify symbol_type with the bison namespace used
#define yyterminate() return symbol_type(YY_NULL, curLocation)

当启用bison位置(例如使用%define locations )时,编译器错误会出现--这使得bison将一个location参数添加到其symbol_type构造函数中,因此构造函数没有位置。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
symbol_type(int tok)

变成这样的地点

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
symbol_type(int tok, location_type l)

呈现不再可能将int转换为symbol_type,这是在不启用野牛位置时,flex中yyterminate的默认定义能够完成的任务。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#define yyterminate() return YY_NULL

有了这个解决方法,就不需要在flex中处理EOF了--如果不需要,就没有必要在野牛中使用多余的END令牌。

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

https://stackoverflow.com/questions/43691665

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文