2012-03-15 15 views
2

私はBisonを初めて使っています。私はパーサーを実装しようとしています。私が直面している主な問題は、解析ツリーです。私は削除することができないツリーに関連するエラーを取得しています。それは "未知の型名"ツリー "と言います。ここにyファイルがあります。誰かがこれを整理するのを手伝ってくれたら嬉しいです。私は非常に悪いパーサーが必要です。前もって感謝します。Bisonを使った構文解析木

%{ 
#include <stdio.h> 
#include <string.h> 

void yyerror(const char *str) 
{ 
    fprintf(stderr,"error FAIL: %s\n",str); 
} 

int yywrap() 
{ 
    return 1; 
} 

enum treetype {operator_node, variable_node}; 
typedef struct tree { 
enum treetype nodetype; 
union { 
struct {struct tree *left, *right; char operator;} an_operator; 
    char *a_variable; 
} body; 
} tree; 
static tree *make_op (tree *l, char o, tree *r) { 
tree *result= (tree*) malloc (sizeof(tree)); 
result->nodetype= operator_node; 
result->body.an_operator.left= l; 
result->body.an_operator.operator= o; 
result->body.an_operator.right= r; 
return result; 
} 
static void printtree (tree *t, int level) { 
#define step 4 
if (t) 
switch (t->nodetype) 
{ 
    case operator_node: 
    printtree (t->body.an_operator.right, level+step); 
    printf ("%*c%c\n", level, ' ', t->body.an_operator.operator); 
    printtree (t->body.an_operator.left, level+step); 
    break; 
    case variable_node: 
    printf ("%*c%c\n", level, ' ', t->body.a_variable); 
} 
} 

%} 

%union { 
char* a_variable; 
tree* a_tree; 
} 

%start file 
%token <a_variable> TOKDIGIT TOKFLOAT TOKID TOKSEMICOLON TOLCOLON TOKCOMMA TOKUNRECOG TOKCOMMENT TOKDOT TOKMINUS TOKCOLON 
%type <a_tree> field object file ID 
%right TOKMINUS 

%% 

file :  
    | object file { printtree($1, 1); } 
    ; 
object :  field object {$$ = make_op($1, '', $2);} 
    | field {$$ = $1 ; } 
    ; 
field : ID TOKCOLON field {$$ = make_op ($1, ':', $3); } 
    | ID TOKCOMMA field {$$ = make_op ($1, ',', $3); } 
    | ID TOKSEMICOLON field {$$ = make_op ($1, ';', $3); } 
    ; 
ID  : TOKID { $$ = $1; } 
     ;  

%% 

答えて

2

次のパッチをコードに適用して、Bisonからいくつかの警告を修正しました。あなたのトップレベルのルールには、空の場合のアクションがありませんでした(したがって、$$に割り当てられません)。もう1つのルールでは、$$に何も割り当てられていませんでした。私。あなたのfileルールは、マスタツリーにオブジェクトを蓄積していない、ので、あなたのyyparse機能は、ツリーを返しません。

Index: test/test.y 
=================================================================== 
--- test.orig/test.y 2012-03-15 16:34:31.992021757 -0700 
+++ test/test.y 2012-03-15 17:00:27.666596757 -0700 
@@ -57,8 +57,9 @@ 

%% 

-file :  
- | object file { printtree($1, 1); } 
+file : /* empty */ { return NULL; } 
+ | object file { printtree($1, 1); return NULL; } 
+  /* TODO: gather the objects into a tree and return */ 
    ; 
object :  field object {$$ = make_op($1, '', $2);} 
    | field {$$ = $1 ; } 

は今、あなたは文法で問題を抱えています。主なものは、あなたのfieldプロダクションが終了しないことです。彼らは無限の文を生成する。 fieldのプロダクションのすべてがfieldで終わるものを生成します。文法の拡張が終了する方法はありません。

主な問題は、展開が行われている文法や、同じものを上回る場所が多すぎることです。 fileには0以上のobjectが生成されます。 objectは、fieldのゼロ個以上のインスタンスです。そして、フィールドはさらにfieldを生成したいと考えています。

これは、お客様のfileが実際にはfieldのシーケンスであることを意味します。複数のfield -sのシーケンシングはすでに処理されており、1つのレベルでのみ処理する必要があります。フィールドは、より多くを生産する必要はありませんfield

+0

私はあなたから提案された変更を行いましたが、tab.cファイルをコンパイルしようとすると "unknown type name 'tree'というエラーが表示されます。文法は今のようになります: 'file:/ * empty */{return NULL; } |フィールドファイル{printtree($ 1、1); NULLを返します。 } ; フィールド:ID TOKCOLONフィールド{$$ = make_op($ 1、 ':'、$ 3); } | ID TOKCOMMAフィールド{$$ = make_op($ 1、 '、'、$ 3); } | ID TOKSEMICOLONフィールド{$$ = make_op($ 1、 ';'、$ 3); } |/*空の*/{NULLを返します。 } ; ID:TOKID {$$ = $ 1; } ; ' –

+0

問題は別の場所です。あなたの 'tree' typedef名に関するCプログラミングエラーのように見えます。 'yacc'からエラーメッセージが出ることはありませんか? – Kaz

+0

あなたの 'tree'型はおそらくヘッダファイルで定義されなければなりません。 Yaccが 'YYSTYPE'解析ノード型を生成するために使うYacc'%union'に 'tree'を使います。 'yacc -d'を実行すると、' YYSTYPE'が宣言された 'y.tab.h'ヘッダファイルが生成されます。 '%union'が' tree'型を定義している場合、 'YYSTYPE'は' tree'型のメンバを持ちます。 'y.tab.h'をインクルードする人は' tree'の定義をどこかからインクルードする必要があります。そうでなければ 'YYSTYPE'宣言は未定義の型を参照します。 – Kaz