代码之家  ›  专栏  ›  技术社区  ›  Alkis Mavridis

BISY与C++中的Flex接口

  •  1
  • Alkis Mavridis  · 技术社区  · 8 年前

    我试图编写一个编译器,并使用flex/bison进行扫描和解析。 我的问题是这两个如何通信,以便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根本没有提到,我们返回的是一些奇怪的构造????函数,我无法理解它们的定义、接受的参数和返回的参数。

    有人能告诉我这两种方法的区别吗?如果我要用第二种方法的话,可以对那些神秘的制造做一个简短的解释吗????方法?

    提前谢谢!

    1 回复  |  直到 8 年前
        1
  •  1
  •   rici    8 年前

    链接到的文档部分是描述 可供替代的 API。最好从 beginning ,其中说明:

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

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

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

    还有第三种选择:使用c接口构建解析器和lexer。这并不能阻止您使用C++数据类型,但不能将它们直接放入解析器堆栈中;您需要使用指针,这使得内存管理更加手动。(实际上,还有两种不同的C API:传统的C API,解析器在需要标记时自动调用scanner;而“推”接口,scanner使用每个标记调用解析器。)