解析语句并向其添加括号
Parsing a statement and Adding Paranthesis to them
我正在尝试解析逻辑 BNF 语句,并尝试对它们应用括号。
例如:
我正在尝试将语句 a=>b<=>c&d 解析为 ((a) =>(b))<=>((c)&(d)),以及类似的语句。
面临的问题: 有些语句工作正常,有些则不然。上面提供的示例不起作用,解决方案打印为 ((c)&(d))<=>((c)&(d)) 第二个 expr 似乎覆盖了第一个。
有效的条件: 而像 a<=>b 和 a|(b&c) 这样的其他简单示例则工作正常。
我想我在我的代码中犯了一些我无法弄清楚的基本错误。
这是我的代码
lex 文件
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<<<<endl;
string s1 = string();
cout<<$$<<endl;
}
| expr '<=>' expr {
cout<<"Inside <=>\n";
string s1 = string();
string s2 = string();
string s3 = "(" + s1 +")" +"<=>"+"(" + s2 +")";
$$ = (char * )s3.c_str();
cout<<s3<<endl;
}
| expr '=>' expr {
cout<<"Inside =>\n";
string s1 = string();
string s2 = string();
string s3 = "(" + s1 +")" +"=>"+"(" + s2 +")";
$$ = (char *)s3.c_str();
cout<<$$<<endl;
}
| expr '|' expr {
cout<<"Inside |\n";
string s1 = string();
string s2 = string();
string s3 = "(" + s1 +")" +"|"+"(" + s2 +")";
$$ = (char *)s3.c_str();
cout<<$$<<endl;
}
| expr '&' expr {
cout<<"Inside &\n";
string s1 = string();
string s2 = string();
string s3 = "(" + s1 +")" +"&"+"(" + s2 +")";
$$ = (char *)s3.c_str();
cout<<$$<<endl;
}
| '!' expr {
cout<<"Inside !\n";
string s1 = string();
cout<<s1<<endl;
string s2 = "!" + s1;
$$ = (char *)s2.c_str();
cout<<$$<<endl;
}
| '(' expr ')' { $$ = ; cout<<"INSIDE BRACKETS"; }
;
%%
请让我知道我所犯的错误。
谢谢
您遇到的基本问题是您将 string::c_str()
返回的指针保存在 yacc 值堆栈中,但是在操作完成并且 string
对象被销毁后,该指针不再存在有效。
要解决此问题,您需要根本不使用 std::string
,或者将 %union
更改为 { std::string *s; }
(而不是 char *
)。在任何一种情况下,您都会遇到内存泄漏问题。如果您使用 Linux,前者非常简单。你的行为会变成这样:
| expr '<=>' expr {
cout<<"Inside <=>\n";
asprintf(&$$, "(%s)<=>(%s)", , );
cout<<$$<<endl;
free();
free();
}
对于后者,操作看起来像:
| expr '<=>' expr {
cout<<"Inside <=>\n";
$$ = new string("(" + * +")" +"<=>"+"(" + * +")");
cout<<$$<<endl;
delete ;
delete ;
}
我正在尝试解析逻辑 BNF 语句,并尝试对它们应用括号。
例如: 我正在尝试将语句 a=>b<=>c&d 解析为 ((a) =>(b))<=>((c)&(d)),以及类似的语句。
面临的问题: 有些语句工作正常,有些则不然。上面提供的示例不起作用,解决方案打印为 ((c)&(d))<=>((c)&(d)) 第二个 expr 似乎覆盖了第一个。
有效的条件: 而像 a<=>b 和 a|(b&c) 这样的其他简单示例则工作正常。
我想我在我的代码中犯了一些我无法弄清楚的基本错误。
这是我的代码
lex 文件
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<<<<endl;
string s1 = string();
cout<<$$<<endl;
}
| expr '<=>' expr {
cout<<"Inside <=>\n";
string s1 = string();
string s2 = string();
string s3 = "(" + s1 +")" +"<=>"+"(" + s2 +")";
$$ = (char * )s3.c_str();
cout<<s3<<endl;
}
| expr '=>' expr {
cout<<"Inside =>\n";
string s1 = string();
string s2 = string();
string s3 = "(" + s1 +")" +"=>"+"(" + s2 +")";
$$ = (char *)s3.c_str();
cout<<$$<<endl;
}
| expr '|' expr {
cout<<"Inside |\n";
string s1 = string();
string s2 = string();
string s3 = "(" + s1 +")" +"|"+"(" + s2 +")";
$$ = (char *)s3.c_str();
cout<<$$<<endl;
}
| expr '&' expr {
cout<<"Inside &\n";
string s1 = string();
string s2 = string();
string s3 = "(" + s1 +")" +"&"+"(" + s2 +")";
$$ = (char *)s3.c_str();
cout<<$$<<endl;
}
| '!' expr {
cout<<"Inside !\n";
string s1 = string();
cout<<s1<<endl;
string s2 = "!" + s1;
$$ = (char *)s2.c_str();
cout<<$$<<endl;
}
| '(' expr ')' { $$ = ; cout<<"INSIDE BRACKETS"; }
;
%%
请让我知道我所犯的错误。
谢谢
您遇到的基本问题是您将 string::c_str()
返回的指针保存在 yacc 值堆栈中,但是在操作完成并且 string
对象被销毁后,该指针不再存在有效。
要解决此问题,您需要根本不使用 std::string
,或者将 %union
更改为 { std::string *s; }
(而不是 char *
)。在任何一种情况下,您都会遇到内存泄漏问题。如果您使用 Linux,前者非常简单。你的行为会变成这样:
| expr '<=>' expr {
cout<<"Inside <=>\n";
asprintf(&$$, "(%s)<=>(%s)", , );
cout<<$$<<endl;
free();
free();
}
对于后者,操作看起来像:
| expr '<=>' expr {
cout<<"Inside <=>\n";
$$ = new string("(" + * +")" +"<=>"+"(" + * +")");
cout<<$$<<endl;
delete ;
delete ;
}