繁体   English   中英

如何在我自己的解析器中使用flex?

[英]How to use flex with my own parser?

我想将词法分析留给词法分析,但自己开发解析器。

我制作了一个token.h标头,其中包含令牌类型的枚举和简单的类层次结构,

对于lex规则:

[0-9]+ {yylval = new NumToken(std::stoi(yytext));return NUM;}

如何从解析器代码中获取NumToken指针? 假设我只想打印出令牌。

while(true)
{
    auto t = yylex();
    //std::cout <<yylval.data<<std::endl; // What goes here ?
}

我可以使用yacc / bison进行此操作,但是找不到有关如何手动执行此操作的任何文档或示例。

在传统的bison / flex解析器中, yylval是在bison生成的解析器中定义的全局变量,并在bison生成的头文件中声明(应在包含在生成的扫描器中#include)。 因此,一个简单的解决方案就是复制它:在token.h声明yylval (作为全局token.h并在解析器中的某个位置定义它。

但是现代编程风格已经从使用全局变量转变了(有充分的理由),实际上,如果需要,甚至flex也会生成不依赖于全局状态的扫描程序。 要请求这样的扫描仪,请指定

%option reentrant

在您的扫描仪定义中。 默认情况下,这会将yylex的原型更改为:

int yylex(yyscan_t yyscanner);

其中yyscan_t是不透明的指针。 (这是C,所以意味着它是一个void* 。)您可以在Flex手册中阅读有关细节; 最重要的要点是,您可以要求flex还生成一个头文件(带有%option header-file ),以便其他翻译单元可以引用各种函数来创建,销毁和操作yyscan_t ,并且您需要最少创建一个,以便yylex在某处存储其状态。 (理想情况下,您也将其销毁。)[注1]。

使用扫描仪折返从预期的方式bison是启用%option bison-bridge (和%option bison-location ,如果你的词法分析器每个令牌生成源位置信息)。 这将为yylex原型添加一个附加参数:

int yylex(YYSTYPE *yylval_param, yyscan_t scanner);

使用`%option bison-locations',添加了两个参数:

int yylex(YYSTYPE *yylval_param,
          YYLTYPE *yylloc_param,
          yyscan_t scanner);

flex生成的代码声明语义类型YYSTYPE和位置类型YYLTYPE 它们必须出现在您#include到扫描仪中的token.h标头中。

野牛桥参数的目的是提供一种将语义值yylval返回给调用方(即解析器)的机制。 由于yylval实际上与参数yylval_param [注2]相同,因此它将是指向实际语义值的指针 ,因此您需要在flex动作中编写(例如) yylval->data = ...

所以这是做到这一点的一种方法。

替代bison-bridge一种可能更简单的选择是仅提供您自己的yylex原型,您可以使用宏YY_DECL 例如,您可以执行以下操作(如果YYSTYPE很简单):

#define YY_DECL std::pair<int, YYSTYPE> yylex(yyscan_t yyscanner)

然后一条规则可以返回该对:

[0-9]+ {return std::make_pair(NUM, new NumToken(std::stoi(yytext));}

显然,此主题有很多变体。


笔记

  1. 不幸的是,生成的标头包含很多不必要的包,,包括一堆用于标准“全局变量”的宏定义,这些宏定义将不起作用,因为在可重入的扫描器中,这些变量只能在flex动作中使用。

  2. bison-bridge生成的扫描器将yylval定义为一个宏,该宏引用不透明状态结构中的一个字段,并将yylval_param存储到该字段中。 yyget_lvalyyset_lval函数是为了从yylex外部获取或设置此字段。 我不知道为什么; 似乎介于不必要和危险之间,因为状态将包含指向 yylex调用中提供的值的指针,一旦调用返回,它很可能是悬空的指针。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM