2012-04-11 4 views
1

Ich habe ein Problem in logischen Operatoren mitflex yacc (Bison) Segmentierungsfehler, während der Baum Parsing Gebäude

In meiner .y Datei ich habe:

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

In meiner .l Datei bestimmt i dass oper1 und oper2 sind:

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

Dann i eine Struktur haben, die Werte setzen in:

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

und setzen die Werte 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; 
} 

und schließlich zeigen sie:

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

aber dann bekomme ich einen Segmentation Fault jedes Mal wenn ich eine ausdr oper ausdr verwenden:

Program received signal SIGSEGV, Segmentation Fault 

Irgendwelche Ideen darüber, was ich falsch mache?

Dank

+0

Sie vermissen eine geschweifte Klammer in Ihrem ersten Ausschnitt. –

+0

um klar zu sein, '| expr oper2 expr $$ = Einfügeausdruck ($ 2, $ 1, $ 3); } 'sollte' | sein expr oper2 expr {$$ = Einfügeausdruck ($ 2, $ 1, $ 3); } ' – gbulmer

+0

Sorry, kopieren & einfügen Fehler :-(Der ursprüngliche Code hat keine geschweiften Klammern fehlen (zumindest in y-Datei :-)) – Nitrate

Antwort

0

Der Standardtyp für alle Token int ist. Wenn Sie nicht haben

%union { 
    char *oper1 
    char *oper2 
} 

Es wird Probleme geben. Wie es ist, mischen Sie Zeiger und Ints. Dies hat zur Folge, dass Ihr Programm versucht, auf beliebigen Speicher zuzugreifen und den Segfault verursacht.

Edit:

In Ordnung, dann Feuer, das Ding in GDB oder mein cgdb bevorzugt.

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

Damit erhalten Sie den ungefähren Standort, an dem es scheitert, und zeigen Ihnen, wo Sie Breakpoints benötigen. Tipps zum Debuggen von gdb/cgdb finden Sie unter article.

+0

hmm guten Punkt. Ich werde das versuchen und Sie wissen lassen, wie es ging – Nitrate

+0

hat nicht funktioniert. immer noch seg Fehler – Nitrate

+0

@Nitrate Ich habe einen Abschnitt zum Debuggen hinzugefügt, so dass Sie herausfinden können, was den segfault verursacht. –

1

Mal sehen:

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

Rekursion müssen eine Möglichkeit haben, zu beenden!

Ein großer Hinweis ist, dass Sie nur eine printf haben, die den Operator druckt. Aber der Baum hat andere Dinge als nur Operatoren: nämlich Operanden!

In Ihrem Ausdrucksbaum sind diese Operanden Blattknoten. Wie sind sie vertreten? Sie haben wahrscheinlich Nullzeiger für ex1 und ex2, richtig? (Hoffentlich nicht Müll: alle Ihre Parser-Regeln tun $$ zu einem gewissen Wert, oder?)

Außerdem muss es viel mehr zu Ihrer yacc-Datei als das. Die von Ihnen gezeigte Regel für expr kann nicht von selbst existieren, da sie nicht auf eine Folge von Terminalsymbolen reduziert werden kann.

+0

Nizza Fang. Ich habe die unendliche Rekursion nicht gesehen. –

+0

Ich habe gerade einen Ausschnitt des Codes gezeigt, weil er ziemlich groß wird. Die Rekursion existiert im Snippet, aber nicht im echten Code. Sorry für die – Nitrate

+0

wenn ich schreibe: a = b ‚a‘ ist ex1 ‚b‘ ist EX2 und ‚=‘ ist oper Für jeden Ausdruck wird er drucken, es ist Wert, der ‚a‘ und ‚b ' so keine Probleme hier – Nitrate

0

Damit $n vernünftige Werte haben, benötigen Sie eine %union Richtlinie alle möglichen Arten zu spezifizieren, und dann müssen Sie diese Typen in %token/%type Richtlinien verwenden:

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

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

Dann müssen Sie auch um sicherzustellen, dass Sie die Werte richtig in Ihrer .l-Datei festgelegt:

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

Andernfalls werden Sie zufälligen Müll als erster Operanden zu insert_expression, werden vorbei und dann abstürzt Wenn Sie versuchen, irgendetwas mit oper zu tun (da es zufällig Müll zeigt)

+0

Sorry, noch einmal habe ich die Union übersprungen. In der Tat habe ich hinzugefügt, was Sie vorgeschlagen haben. Immer noch SIGSEGV. Mir sind die Ideen ausgegangen. Nichts scheint zu funktionieren – Nitrate

Verwandte Themen