使用Lex+Yacc解析逻辑表达式加括号时出现值覆盖问题求助
错误1:lex文件多字符运算符识别错误
你当前lex文件中匹配到<=>/=>这类多字符运算符时,直接return *yytext只会返回运算符的第一个字符,比如<=>会被当做'<'返回,完全匹配不到你yacc中定义的<=>/=>规则。
修正方案:
给多字符运算符单独定义token,修改lex文件:
letters [a-zA-Z] identifier {letters}+ separator [\(\)] %% {identifier} { yylval.s = strdup(yytext); return IDENTIFIER; } "<=>" { return EQV; } "=>" { return IMPLY; } "|" { return '|'; } "&" { return '&'; } "!" { return '!'; } {separator} { return *yytext; } [\n] { return '\n'; } %%
同时在yacc文件开头声明新增的token,调整优先级定义:
%token IDENTIFIER EQV IMPLY %left EQV %left IMPLY %left '|' %left '&' %right '!' %left '(' ')'
后续规则里把'<=>'改成EQV,'=>'改成IMPLY即可。
错误2:yacc动作块使用局部std::string的临时指针
你所有规则中构造完字符串后直接用$$ = (char *)s3.c_str()赋值,s3是动作块内的局部std::string变量,动作块执行完成后s3就会被销毁,c_str()返回的指针就变成野指针,后续访问该指针时指向的内存可能被后续构造的字符串复用,就是你遇到的“后面的表达式覆盖前面的表达式”的根因。
错误3:IDENTIFIER规则未给$$赋值
你匹配原子表达式IDENTIFIER的规则中,只构造了临时变量,完全没有给$$赋值,会导致后续依赖该原子值的规则拿到的是随机值。
统一修正方案(yacc规则部分)
所有字符串赋值都用strdup把内容复制到堆内存,避免野指针,同时释放不需要的内存避免泄漏:
expr : IDENTIFIER { $$ = strdup($1); free($1); } | expr EQV expr { string s1($1); string s2($3); string s3 = "(" + s1 +")<=>(" + s2 +")"; $$ = strdup(s3.c_str()); free($1); free($3); } | expr IMPLY expr { string s1($1); string s2($3); string s3 = "(" + s1 +")=>(" + s2 +")"; $$ = strdup(s3.c_str()); free($1); free($3); } | expr '|' expr { string s1($1); string s2($3); string s3 = "(" + s1 +")|(" + s2 +")"; $$ = strdup(s3.c_str()); free($1); free($3); } | expr '&' expr { string s1($1); string s2($3); string s3 = "(" + s1 +")&(" + s2 +")"; $$ = strdup(s3.c_str()); free($1); free($3); } | '!' expr { string s1($2); string s2 = "!" + s1; $$ = strdup(s2.c_str()); free($2); } | '(' expr ')' { $$ = $2; } ;
内容的提问来源于stack exchange,提问作者No Reveal Name
相关产品推荐
相关产品推荐

