2012-03-15 79 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中的一些警告。您的最高等级规则缺少针对空案的操作(因此未能分配给$$),另一个规则也没有分配任何内容给$$。即您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产生零个或多个objectobjectfield的零个更多的实例。然后一个字段也想生成更多field

这是什么意思是你的file实际上只是一个field的序列。多个field-s的排序已经处理完毕,只能在一个层次上处理;字段不必产生更多field

+0

我做了你所提出的改变,但是当我尝试编译tab.c文件时仍弹出错误“unknown type name'树'”。这是语法现在的样子: '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; } ;' – 2012-03-20 23:40:56

+0

这个问题在别的地方;看起来像一个关于你的''''''''typedef名字的C编程错误。是否没有更多的错误信息从'yacc'中出来? – Kaz 2012-03-20 23:52:52

+0

您的'tree'类型可能必须在头文件中定义。你在你的Yacc'%union'中使用'tree',Yacc用它来生成'YYSTYPE'解析节点类型。当你运行'yacc -d'时,它会生成一个'y.tab.h'头文件,其中'YYSTYPE'被声明。如果'%union'定义了一个'tree'类型,那么'YYSTYPE'将有一个'tree'类型的成员。无论谁包含'y.tab.h',都必须包含'tree'的定义,否则'YYSTYPE'声明将引用一个未定义的类型。 – Kaz 2012-03-20 23:58:29