我有一个用flex和bison编写的精彩解析器,用复古语言成功解析曲折的混淆程序(没有单班/班次或班次/减少混乱)。下一步,构建AST。
现在,我想使用精彩的C ++ 11资源管理非POD类型(如std::string
)将标记从flex传递到bison。问题是,YYSTYPE
是union
。
假设我可以传递std::string
或int
代币。我可以使用boost::variant
或手工制作的版本,但是有没有办法告诉野牛和屈服不使用工会?
答案 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不能成为联盟的一部分”问题,那么这可能会得到一个更好的解决方案。