1

我的逻辑运算符有问题

在我的 .y 文件中,我有:

expr: expr oper1 expr { $$=insert_expression($2, $1, $3); }
     | expr oper2 expr { $$=insert_expression($2, $1, $3); }
     ;

在我的 .l 文件中,我确定 oper1 和 oper2 是:

"<" | ">" | "=" | "<>" | "<=" | ">=" { return oper1; }
"AND" | "OR" { return oper2; }

然后我有一个结构可以将值放入:

typedef struct _Expression
{
    char *oper;
    struct _Expression *ex1;
    struct _Expression *ex2;
} is_expression;

并将值放入:

is_expression* insert_expression(char* oper, is_expression *expr1, is_expression *expr2)
{
    is_expression* e = (is_expression*)malloc(sizeof(is_expression));

    e->ex1 = expr1;
    e->ex2 = expr2;
    e->oper = oper;

    return e;
}

最后向他们展示:

void show_expression(is_expression *e)
{
    show_expression(e->ex1);
    printf("%s", e->oper);
    show_expression(e->ex2);
}

但是每次我使用 expr oper expr 时都会出现分段错误:

Program received signal SIGSEGV, Segmentation Fault

关于我做错了什么的任何想法?

谢谢

4

3 回答 3

1

让我们来看看:

void show_expression(is_expression *e)
{
    show_expression(e->ex1);
    printf("%s", e->oper);
    show_expression(e->ex2);
}

递归必须有方法终止!

一个重要的线索是你只有一个printf打印操作符的。但是树中除了操作符之外还有其他东西:即操作数!

在您的表达式树中,这些操作数是叶节点。他们是如何代表的?ex1他们可能对and有空指针ex2,对吧?(希望不是垃圾:你所有的解析器规则都有$$一定的价值,对吧?)

此外,您的 yacc 文件还必须包含更多内容。您所显示的规则expr不能单独存在,因为它不能简化为一系列终端符号。

于 2012-04-11T18:36:36.260 回答
0

所有标记的默认类型是int. 如果你没有

%union {
    char *oper1
    char *oper2
}

会有问题。实际上,您正在混合指针和整数。这会导致您的程序尝试访问任意内存,从而导致段错误。

编辑:

好吧,然后在 gdb 或我喜欢的cgdb中启动那个东西。

cgdb yourCompiledParser
> r (add necessary command line switches)
when it segfaults
> backtrace

这将为您提供失败的大致位置,并向您显示需要断点的位置。有关 gdb/cgdb 调试提示,请查看这篇文章

于 2012-04-11T18:35:44.200 回答
0

为了获得合理的值$n,您需要一个%union指令来指定所有可能的类型,然后您需要在%token/%type指令中使用这些类型:

%union {
    is_expression  *exp;
    char           *str;
}

%token<str> oper1 oper2
%type<exp> expr

然后,您还需要确保在 .l 文件中正确设置值:

"<" | ">" | "=" | "<>" | "<=" | ">=" { yylval.str = strdup(yytext); return oper1; }
"AND" | "OR" { yylval.str = strdup(yytext); return oper2; }

否则,您会将随机垃圾作为第一个操作数传递给insert_expression,然后在您尝试使用任何操作时崩溃oper(因为它指向随机垃圾)

于 2012-04-12T00:22:53.867 回答