I've had the exactly same problem recently. I solved it the following way: I used char* in the union (or better, the struct I used for improved type safety), but then converted to std::string as soon as I assigned the string to my data structure.
So I have (code shortened significantly)
struct parserType
{
double number;
char* string;
int stringLength;
// ...
};
And in the parser.y file
%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;
}
with
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;
}
with the following in the lexer:
{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;
}
This may not be the most elegant solution, but it seems to work flawlessly so far. If anybody knows how one can circumvent the "std::string must not be part of an union" problem, that would probably get a nicer solution.