【问题标题】:Bison, interfacing with flex in c++Bison,在 C++ 中与 flex 交互
【发布时间】:2018-06-05 16:41:43
【问题描述】:

我尝试编写一个编译器,并使用 flex/bison 进行扫描和解析。 我的问题是关于这 2 个如何通信,以便 lex 传递一个标记类型和(如果需要)一个语义值。

问题是我发现了不同的(冲突的?)文档。

例如here,他们提到使用 yylval 子字段作为语义值,并返回令牌类型(可能是整数)。

[0-9]+ {
   yylval->build<int> () = text_to_int (yytext);
   return yy::parser::token::INTEGER;
}
[a-z]+ {
   yylval->build<std::string> () = yytext;
   return yy::parser::token::IDENTIFIER;
 }

但是,我看到(也在官方文档中)this

"-"      return yy::calcxx_parser::make_MINUS  (loc);
"+"      return yy::calcxx_parser::make_PLUS   (loc);
"*"      return yy::calcxx_parser::make_STAR   (loc);
"/"      return yy::calcxx_parser::make_SLASH  (loc);
"("      return yy::calcxx_parser::make_LPAREN (loc);
")"      return yy::calcxx_parser::make_RPAREN (loc);
":="     return yy::calcxx_parser::make_ASSIGN (loc);

{int}      {
  errno = 0;
  long n = strtol (yytext, NULL, 10);
  if (! (INT_MIN <= n && n <= INT_MAX && errno != ERANGE))
    driver.error (loc, "integer is out of range");
  return yy::calcxx_parser::make_NUMBER (n, loc);
}
{id}       return yy::calcxx_parser::make_IDENTIFIER (yytext, loc);
.          driver.error (loc, "invalid character");
<<EOF>>    return yy::calcxx_parser::make_END (loc);

这里根本没有提到yylval,我们返回的是一些奇怪的make_???函数,我不明白它们是在哪里定义的,它们接受什么参数以及它们返回什么。

有人可以向我澄清这两种方法之间的区别吗?如果我应该使用第二种方法,请简要解释一下那些神秘的make_???方法?

提前致谢!

【问题讨论】:

    标签: c++ bison flex-lexer


    【解决方案1】:

    您链接到的文档部分是描述 alternative API 的两个部分中的第一个。最好从beginning开始阅读,那里解释说:

    yylex 的实际接口取决于您使用联合还是变体。

    您引用的示例使用了变体,因此使用了complete symbols 接口,其中定义了make_* 方法。 (这些不是标准库或 Boost 变体;它们是由 bison 框架定义的简单的可区分联合类。)

    您使用哪些 API 完全取决于您;它们都有优点和缺点。

    还有第三种选择:使用 C 接口构建解析器和词法分析器。这不会阻止您使用 C++ 数据类型,但您不能将它们直接放入解析器堆栈;您需要使用指针,这使得内存管理更加手动。 (实际上,也有两种不同的 C API:传统的一种,其中解析器在需要令牌时自动调用扫描器,以及“推送”接口,扫描器使用每个令牌调用解析器。)

    【讨论】:

    • 我想我现在明白了。非常感谢您的回答!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-19
    • 2012-09-27
    相关资源
    最近更新 更多