Search code examples
c++compiler-constructionbisonflex-lexerbisonc++

passing value from flex to bison


I am trying to print token value in bison sent from flex but for some reason the value printed is garbage in some cases.

lex code:

\".*\" {
std::string* s1 = new std::string(yytext);
    std::string s2 = *s1;
    std::string s3 = s2.substr(1,s2.size() - 2);
    yylval.s = &s3;

    return VARIABLE;
}

bison code:

    %union{
            std::string *s;
    };

%type <s> expr

expr : VARIABLE { caps($1); }

void caps(std::string *str){
    std::string str1 = *str;

    for(std::string::size_type i=0;i<str1.length();i++)
            std::cout << str1[i];
}

If i input a string with length less than 15 characters it outputs fine but if the length goes beyond it garbage is printed.

If i isolate the c++ code and running it works fine i am not getting why is it happening so can someone find the mistake in it.


Solution

  • The following is Undefined Behaviour:

    std::string* s1 = new std::string(yytext);
    std::string s2 = *s1;
    std::string s3 = s2.substr(1,s2.size() - 2);
    yylval.s = &s3;
    return VARIABLE;
    

    s3 is a local variable but you are attempting to return a pointer to it. Since s3 will be destructed as soon as the return statement is executed, the pointer will be left dangling into unallocated memory, and attempting to use it later will have unpredictable consequences.

    In any event, the sequence is unnecessary. Flex sets the variable yyleng to the length of the token, so you can simply use that to construct the string you actually want:

    yylval.s = new std::string(yytext + 1, yyleng - 2);
    return VARIABLE;