2012-04-11 8 views
1

を構築しながら:私は判断私.LファイルでフレックスYACC(バイソン)セグメンテーションフォールト私は私の.Yファイルでは、私は論理演算子で</p> <p>で問題を抱えている構文解析ツリー

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

そのOPER1とoper2は、次のとおりです。

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

その後、私は内の値を配置する構造を持っている:

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

とに値を入れる:

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

が、その後、私は式exprにはoper exprを使用してセグメンテーションフォールトを毎回取得:

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

、最終的にはそれらを表示

Program received signal SIGSEGV, Segmentation Fault 

私が間違っていることについてのアイデアはありますか?すべてのトークンの

おかげ

+0

最初のスニペットに波括弧がありません。 –

+0

をクリアすると、 '| expr oper2 expr $$ = insert_expression($ 2、$ 1、$ 3); } 'は' 'でなければなりません。 expr oper2 expr {$$ = insert_expression($ 2、$ 1、$ 3); } ' – gbulmer

+0

申し訳ありません、コピー&ペーストエラー:-(元のコードには中かっこはありません(少なくともyファイル:-)) – Nitrate

答えて

0

デフォルトのタイプはintです。あなたは持っていない場合

%union { 
    char *oper1 
    char *oper2 
} 

問題があります。それはそのままですが、ポインタとintを混合しています。これにより、プログラムは任意のメモリにアクセスしようとし、segfaultを引き起こします。

編集:

さてさて、その後、GDBにまたは私の好まcgdbその事を起動。

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

これはあなたのおおよその位置を取得し、どこにブレークポイントが必要かを示します。 gdb/cgdbのデバッグのヒントについては、articleを参照してください。

+0

hmm良い点。私はそれを試してみて、それがどうやって行ったのか教えてください – Nitrate

+0

はうまくいきませんでした。まだSegフォールトエラーが発生しました – Nitrate

+0

@Nitrateデバッグ時にセクションを追加したので、segfaultの原因を見つけることができます。 –

1

は見てみましょう:

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

再帰が終了する方法を持っている必要があります!

大きなヒントは、オペレータを印刷するprintfが1つだけあることです。しかし、ツリーには単なる演算子以外のものがあります:つまり、オペランド!

式ツリーでは、これらのオペランドはリーフノードです。彼らはどのように表現されますか?彼らはおそらくex1ex2のヌルポインタを持っていますね。 (うまくいけないことですが、ガーベジではありません。すべてのパーサールールでは、ある程度の値に$$がありますか?)

また、yaccファイルにはそれ以上のものが必要です。表示されているexprのルールは、ターミナルシンボルのシーケンスに還元できないため、単独では存在できません。

+0

ニースキャッチ。私は無限回帰を見ませんでした。 –

+0

コードがかなり大きくなっているので、コードのスニペットを表示しました。再帰はスニペットに存在しますが、実際のコードには存在しません。その – Nitrate

+0

のため申し訳ありませんが私が書いた場合: = B 「」 をEX2と「=」各式についてはoper である彼は、それは「A」と「B値、の印刷されますされ 「b」をEX1されます'それぞれ ここに問題はありません – Nitrate

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で何かしようとすると(ランダムなゴミを指しているので)

+0

申し訳ありません、もう一度私は組合をスキップしました。実際に私はあなたが提案したものを加えました。まだSIGSEGV。私はアイデアがなくなった。何も動作していないようです – Nitrate

関連する問題