0

我正在尝试解析逻辑 BNF 语句,并尝试对它们应用括号。

例如: 我正在尝试将语句a=>b<=>c&d解析为((a)=>(b))<=>((c)&(d))以及类似的语句。

面临的问题:有些陈述工作正常,而有些则不然。上面提供的示例不起作用,解决方案打印为 ((c)&(d))<=>((c)&(d)) 第二个 expr 似乎覆盖了第一个。

有效的条件:虽然其他简单的例子,如 a<=>b , a|(b&c) 工作正常。

我想我在我的代码中犯了一些基本错误,我无法弄清楚。

这是我的代码

文件

letters [a-zA-Z]
identifier {letters}+
operator (?:<=>|=>|\||&|!)
separator [\(\)]    

%%
{identifier} {
    yylval.s = strdup(yytext);
    return IDENTIFIER; }
{operator} { return *yytext; }
{separator} { return *yytext; }
[\n] { return *yytext; }
%%

yacc 文件

%start program
%union  {char* s;}
%type <s> program expr IDENTIFIER
%token IDENTIFIER
%left '<=>'
%left '=>'
%left '|' 
%left '&'
%right '!'
%left '(' ')'

%%
program : expr '\n'     
          { 
            cout<<$$;
            exit(0);
          }
     ;
    
expr : IDENTIFIER  {  
        cout<<" Atom ";
        cout<<$1<<endl;
        string s1 = string($1);
        cout<<$$<<endl;
        
    }
     | expr '<=>' expr   {
        cout<<"Inside <=>\n";
        string s1 = string($1); 
        string s2 = string($3); 
        string s3 = "(" + s1 +")" +"<=>"+"(" + s2 +")";
        $$ = (char *    )s3.c_str();
        cout<<s3<<endl;
     }
     | expr '=>' expr   {
        cout<<"Inside =>\n";
        string s1 = string($1);
        string s2 = string($3); 
        string s3 = "(" + s1 +")" +"=>"+"(" + s2 +")";
        $$ = (char *)s3.c_str();
        cout<<$$<<endl;
     }
     | expr '|' expr    { 
 
        cout<<"Inside |\n";
        string s1 = string($1);
        string s2 = string($3); 
        string s3 = "(" + s1 +")" +"|"+"(" + s2 +")";
        $$ = (char *)s3.c_str();
        cout<<$$<<endl;
     }
     | expr '&' expr    {

        cout<<"Inside &\n";
        string s1 = string($1);
        string s2 = string($3); 
        string s3 = "(" + s1 +")" +"&"+"(" + s2 +")";
        $$ = (char *)s3.c_str();
        cout<<$$<<endl;
     }
     | '!' expr {      

        cout<<"Inside !\n"; 
        string s1 = string($2);
        cout<<s1<<endl;
        string s2 = "!" + s1;
        $$ = (char *)s2.c_str();
        cout<<$$<<endl;
     }
     | '(' expr ')'         {  $$ = $2; cout<<"INSIDE BRACKETS"; }
     ;
%%


请让我知道我犯的错误。

谢谢

4

1 回答 1

1

您遇到的基本问题是您将返回的指针保存在string::c_str()yacc 值堆栈中,但是在操作完成并且string对象被销毁后,该指针不再有效。

要解决此问题,您需要根本不使用std::string,或者将您的更改%union{ std::string *s; }(而不是char *)。无论哪种情况,您都会遇到内存泄漏问题。如果您使用的是 Linux,则前者非常简单。你的行为会变成这样:

     | expr '<=>' expr   {
        cout<<"Inside <=>\n";
        asprintf(&$$, "(%s)<=>(%s)", $1, $3);
        cout<<$$<<endl;
        free($1);
        free($3);
     }

对于后者,操作如下所示:

     | expr '<=>' expr   {
        cout<<"Inside <=>\n";
        $$ = new string("(" + *$1 +")" +"<=>"+"(" + *$2 +")");
        cout<<$$<<endl;
        delete $1;
        delete $3;
     }
于 2021-10-15T17:29:51.153 回答