使用有趣的类型(如 std::string)来保存一些令牌类型

Using interesting types like std::string to hold some token types

本文关键字:类型 string 保存 令牌 std      更新时间:2023-10-16

我有一个用flex和bison编写的很棒的解析器,它成功地用老式语言解析了一个曲折的混淆程序(没有一个移位/移位或移位/减少冲突)。下一步,构建 AST。

现在,我想使用出色的 C++11 资源管理非 POD 类型(如 std::string)将代币从 flex 传递到野牛。问题是,YYSTYPE是一个union

假设我可能会通过std::stringint来获取代币。我可以使用boost::variant或手工制作的版本,但是有没有办法告诉野牛和弹性不要使用工会?

我最近遇到了完全相同的问题。我通过以下方式解决了它:我在联合中使用了 char*(或者更好的是,我用于提高类型安全性的结构),但一旦我将字符串分配给我的数据结构,就会转换为 std::string。

所以我有(代码显着缩短)

 struct parserType
 {
     double number;
     char* string;
     int stringLength;
     // ...
 };

并在解析器.y 文件中

 %define api.value.type {struct parserType}
 %token <string> STRING
 // and maybe...
 %type <string> LatitudeFile
 %type <string> LongitudeFile
 %type <string> HeightFile

 // A simple non-terminal:
 LatitudeFile:
 /* Empty */
 {
      $$ = NULL;
 }
 | LATITUDE '=' STRING
 {
      $$ = ($3);
 }
 ;
 // A structure building rule:
| KEYWORD LatitudeFile LongitudeFile HeightFile GridBaseDatum
{
     ss = new DataObject();
     ss->rs.latShiftFile = ToStdString($2);
     ss->rs.lonShiftFile = ToStdString($3);
     ss->rs.heightShiftFile = ToStdString($4);
     ss->rs.gridBaseDatum = ToStdString($5);            
     $$ = ss;
 }

std::string ToStdString(char* ptr)
{
    std::string ret = (ptr != NULL) ? std::string(ptr + 1, (strlen(ptr) - 2)) : std::string("");
    delete[] ptr; // Delete memory allocated by lexer. 
    return ret;
}

在词法分析器中具有以下内容:

 {STRING}  {
      char* buf = new char[yyleng+1];
      memset(buf, 0, yyleng+1);
      strncpy_s(buf, yyleng +1 , yytext, _TRUNCATE);
      yylval->string = buf;
      yylval->stringLength = yyleng;
      return STRING;
 }

这可能不是最优雅的解决方案,但到目前为止,它似乎完美无缺。如果有人知道如何规避"std::string不能成为工会的一部分"问题,那可能会得到更好的解决方案。

相关文章: