2012-03-15 2 views
2

나는 Bison을 처음 사용했습니다. 파서를 구현하려고합니다. 내가 직면 한 주된 문제는 파스 트리이다. 내가 제거 할 수없는 나무와 관련된 오류가 나타납니다. 그것은 "unknown type name 'tree'"라고 말합니다. 여기에 내 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은 0 이상 object을 생성합니다. objectfield 인 경우 제로가됩니다. 그리고 나서 필드는 더 많은 것을 생성하려고합니다 field.

이 의미는 file이 실제로는 field의 시퀀스라는 것입니다. 복수 field -s의 시퀀싱은 이미 처리되었으며 하나의 레벨에서만 처리되어야합니다. 필드는 더 생산할 필요가 없습니다 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); } |/* empty */{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