Nitrate
Nitrate

Reputation: 359

flex yacc (bison) segmentation fault while building the parsing tree

I'm having a problem in logical operators

In my .y file i have:

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

In my .l file i determined that oper1 and oper2 are:

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

Then i have a structure to put the values in:

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

and put the values in:

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;
}

and finally show them:

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

but then i get a segmentation fault everytime i use a expr oper expr:

Program received signal SIGSEGV, Segmentation Fault

Any ideas about what i'm doing wrong?

Thanks

Upvotes: 1

Views: 1735

Answers (3)

Chris Dodd
Chris Dodd

Reputation: 126536

In order to have sane values for $n, you need a %union directive to specify all the possible types, and then you need to use those types in %token/%type directives:

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

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

Then you ALSO need to make sure you set the values properly in your .l file:

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

Otherwise, you'll be passing random garbage as the first operand to insert_expression, and then crashing when you try to do anything with oper (as it points at random garbage)

Upvotes: 0

Spencer Rathbun
Spencer Rathbun

Reputation: 14910

The default type for all tokens is int. If you don't have

%union {
    char *oper1
    char *oper2
}

There will be problems. As it is, you are mixing pointers and ints. This causes you're program to attempt to access arbitrary memory, causing the segfault.

Edit:

Alright, then fire that thing up in gdb or my preferred cgdb.

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

That will get you the approximate location it's failing at, and show you where you need break points. For gdb/cgdb debugging tips, check out this article.

Upvotes: 0

Kaz
Kaz

Reputation: 58667

Let's see:

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

Recursion must have a way to terminate!

A big clue is that you have just one printf which prints the operator. But the tree has stuff in it other than just operators: namely, operands!

In your expression tree, these operands are leaf nodes. How are they represented? They probably have null pointers for ex1 and ex2, right? (Hopefully not garbage: all your parser rules do $$ to some value, right?)

Also, there must be much more to your yacc file than that. The rule for expr you have shown cannot exist by itself because it is not reducible to a sequence of terminal symbols.

Upvotes: 1

Related Questions