使用像std :: string这样的有趣类型来保存一些令牌类型

时间:2014-03-01 15:49:08

标签: c++ c++11 bison flex-lexer

我有一个用flex和bison编写的精彩解析器,用复古语言成功解析曲折的混淆程序(没有单班/班次或班次/减少混乱)。下一步,构建AST。

现在,我想使用精彩的C ++ 11资源管理非POD类型(如std::string)将标记从flex传递到bison。问题是,YYSTYPEunion

假设我可以传递std::stringint代币。我可以使用boost::variant或手工制作的版本,但是有没有办法告诉野牛和屈服不使用工会?

1 个答案:

答案 0 :(得分:1)

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

所以我(代码明显缩短)

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

在parser.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不能成为联盟的一部分”问题,那么这可能会得到一个更好的解决方案。