[질문] bison 관련 질문입니다.
글쓴이: ddangkyoung / 작성시간: 화, 2009/11/24 - 2:46오후
원인 없는 버그는 없다지만
이런 버그가 정말 제일 싫습니다.
바이손에서 제공하는 feature인
%union에서 문제가 생긴 것 같습니다.
아래에서 %union 부분에 nodeType* nPtr;
이라는 부분인데
nodeType은 제가 임의로 만든 구조체인데 이걸 구조체로 인식을 못하는 듯 합니다.
첨부한 파일은 에러 화면입니다.
그리고 이게 그 구조체 입니다.
typedef struct nodeTypeTag{ nodeEnum type; /* type of node */ /* union must be last entry in nodeType */ /* because operNodeType may dynamically increase */ union { conNodeType con; /* constants */ idNodeType id; /* identifiers */ oprNodeType opr; /* operators */ }; } nodeType;
아래코드에서 %union 부분을 봐주세요.
%{ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <stdarg.h> #include "pl.h" int yylex(void); void yyerror(char* ); char* addReserve(); FuncPtr createFuntion(FuncPtr funcList, char* funcName, nodeEnum type); FuncPtr findFunction(FuncPtr funcList ,char* funcName, nodeEnum type); nodeType* con(int value); nodeType* id(char* idName); nodeType* opr(int oper, int nops, ...); void freeNode(nodeType* p); int ex(nodeType* p); ClassPtr createClass(ClassPtr classList ,char* className); /* 사용할 함수 선언 부분 */ ClassPtr classList; ClassPtr currentClass; FuncPtr currentFunc; int var; %} %union { int iValue; char *resName; nodeType *nPtr; }; %token <resName> ID %token <iValue> INTEGER %token CLASS PUBLIC STATIC EXTENDS VOID INT BOOLEAN IF ELSE WHILE RETURN Null TRUE FALSE THIS NEW STRING MAIN PRINTLN %token OP_PLUS OP_MINUS OP_MULTIPLY OP_DIVIDE OP_LESS_THAN OP_LESS_EQUAL OP_GREATER_EQUAL OP_GREATER_THAN OP_EQUAL OP_NOT_EQUAL OP_AND OP_OR OP_NOT %token SEMICOLON DOT COMMA ASSIGN S_BRACE1 S_BRACE2 M_BRACE1 M_BRACE2 L_BRACE1 L_BRACE2 %token VARDECL VARDECLASSIGN CLASSDECL MAINCLASSDECL %type <nPtr> Expr Stmt ClassDecl SubClassDecl MainClassDecl %type <iValue> Type %left '-' '+' %left '*' '/' %nonassoc UMINUS %nonassoc UOPPOSITE %% Program : MainClassDecl SubClassDecl{ ex($1); } ; MainClassDecl: CLASS ID M_BRACE1 Stmt PUBLIC STATIC VOID MAIN S_BRACE1 STRING L_BRACE1 L_BRACE2 ID S_BRACE2 M_BRACE1 Stmt M_BRACE2 M_BRACE2 { $$ = opr(MAINCLASSDECL, 3 , $2, $4, $16); } ; SubClassDecl: SubClassDecl ClassDecl { } | ; ClassDecl: CLASS ID { $$ = opr(CLASSDECL, 1, $2); } ; Stmt: Type ID SEMICOLON Stmt { $$ = opr(VARDECL, 2, $1, $2); } | Type ID ASSIGN Expr SEMICOLON Stmt{ $$ = opr(VARDECLASSIGN, 3, $1, $2, $4); } | ID ASSIGN Expr SEMICOLON Stmt { $$ = opr(ASSIGN, 2, $1, $3); } | PRINTLN S_BRACE1 Expr S_BRACE2 SEMICOLON { $$ = opr(PRINTLN, 1, $3); } | ; Type: INT { $$ = typeInt; } ; Expr: INTEGER { $$ = con($1);} | ID { $$ = id($1);} ; %% void yyerror(s) char *s; { fprintf(stderr, "%s\n",s); } char* addReserve(s) char* s; { char* rt; rt = (char*) malloc(strlen(s)+1); strcpy(rt, s); return rt; } #define SIZEOF_NODETYPE ((char *)&p->con - (char *)p) nodeType* con(int value) { nodeType* p; size_t nodeSize; /* allocate node */ nodeSize = SIZEOF_NODETYPE + sizeof(conNodeType); if ((p = malloc(nodeSize)) == NULL) yyerror("out of memory"); /* copy information */ p->type = typeCon; p->con.value = value; return p; } nodeType* id(char* idName) { nodeType* p; size_t nodeSize; /* allocate node */ nodeSize = SIZEOF_NODETYPE + sizeof(idNodeType); if ((p = malloc(nodeSize)) == NULL) yyerror("out of memory"); /* copy information */ p->type = typeID; p->id.name = (char*) malloc(strlen(idName)+1); strcpy(p->id.name, idName); return p; } nodeType* opr(int oper, int nops, ...) { va_list ap; nodeType* p; size_t nodeSize; int i; /* allocate node */ nodeSize = SIZEOF_NODETYPE + sizeof(oprNodeType) + (nops - 1) * sizeof(nodeType*); if ((p = malloc(nodeSize)) == NULL) yyerror("out of memory"); /* copy information */ p->type = typeOpr; p->opr.oper = oper; p->opr.nops = nops; va_start(ap, nops); for (i = 0; i < nops; i++) p->opr.op[i] = va_arg(ap, nodeType*); va_end(ap); return p; } void freeNode(nodeType* p) { int i; if (!p) return; if (p->type == typeOpr) { for (i = 0; i < p->opr.nops; i++) freeNode(p->opr.op[i]); } free (p); } int ex(nodeType* p) { if (!p) return 0; switch(p->type) { case typeCon: return p->con.value; case typeID: return var; //여기에서 변수의 값을 리턴 case typeOpr: switch(p->opr.oper) { case MAINCLASSDECL: ex(p->opr.op[2]); return 0; case WHILE: while(ex(p->opr.op[0])) ex(p->opr.op[1]); return 0; case IF: if (ex(p->opr.op[0])) ex(p->opr.op[1]); else if (p->opr.nops > 2) ex(p->opr.op[2]); return 0; case PRINTLN: printf("%d\n", ex(p->opr.op[0])); return 0; case SEMICOLON: ex(p->opr.op[0]); return ex(p->opr.op[1]); case ASSIGN: return var = ex(p->opr.op[1]); /* 여기에도 변수찾아서 거기에 값넣는 부분이 들어가야함. sym[p->opr.op[0]->id.i] = ex(p->opr.op[1]); */ case UMINUS: return -ex(p->opr.op[0]); case OP_PLUS: return ex(p->opr.op[0]) + ex(p->opr.op[1]); case OP_MINUS: return ex(p->opr.op[0]) - ex(p->opr.op[1]); case OP_MULTIPLY: return ex(p->opr.op[0]) * ex(p->opr.op[1]); case OP_DIVIDE: return ex(p->opr.op[0]) / ex(p->opr.op[1]); case OP_LESS_THAN: return ex(p->opr.op[0]) < ex(p->opr.op[1]); case OP_GREATER_THAN: return ex(p->opr.op[0]) > ex(p->opr.op[1]); case OP_GREATER_EQUAL: return ex(p->opr.op[0]) >= ex(p->opr.op[1]); case OP_LESS_EQUAL: return ex(p->opr.op[0]) <= ex(p->opr.op[1]); case OP_NOT_EQUAL: return ex(p->opr.op[0]) != ex(p->opr.op[1]); case OP_EQUAL: return ex(p->opr.op[0]) == ex(p->opr.op[1]); } } return 0; } FuncPtr createFuntion(FuncPtr funcList ,char* funcName, nodeEnum type) { FuncPtr temp; FuncPtr p = funcList; if ( (temp = (FuncPtr)malloc( sizeof(FuncPtr))) == NULL ) return NULL; temp->name = funcName; temp->returnType = type; temp->nextFunc = NULL; if(funcList == NULL) { funcList = temp; } else { while( p->nextFunc !=NULL ) { p = p->nextFunc; } p->nextFunc = temp; } return funcList; } FuncPtr findFunction(FuncPtr funcList ,char* funcName, nodeEnum type) { FuncPtr p = funcList; if(funcList == NULL) { printf("함수가 하나도 없습니다.\n"); return NULL; } while( p !=NULL ) { if((!strcmp(p->name,funcName)) && p->returnType == type ) return p; p = p->nextFunc; } printf("찾는 함수가 없습니다.\n"); return NULL; } ClassPtr createClass(ClassPtr classList ,char* className) { ClassPtr temp; ClassPtr p = classList; int i=0; if ( (temp = (ClassPtr)malloc( sizeof(ClassPtr))) == NULL ) return NULL; temp->name = (char*) malloc(strlen(className)+1); strcpy(temp->name, className); temp->memberFunc = NULL; temp->mainFunc = NULL; temp->nextClass = NULL; while(i<20) { temp->memberVar[i] = 0; i++; } if(classList == NULL) { classList = temp; } else { while( p->nextClass !=NULL ) { p = p->nextClass; } p->nextClass = temp; } return classList; } extern FILE *yyin; main(argc, argv) int argc; char **argv; { if(argc>1) { FILE *file; file= fopen(argv[1], "r"); if(!file) { fprintf(stderr, "%s 파일을 열수 없습니다\n",argv[1]); exit(1); } yyin = file; } do { yyparse(); }while(!feof(yyin)); }
혹시 몰라 플렉스 파일과 헤더파일도 추가합니다.
%{ #include <stdio.h> #include <string.h> #include "pl.tab.h" //#include "pl.h" //주석 첨가해줘야해!! %} %% class return CLASS; public return PUBLIC; static return STATIC; extends return EXTENDS; void return VOID; int return INT; boolean return BOOLEAN; if return IF; else return ELSE; while return WHILE; return return RETURN; null return Null; true return TRUE; false return FALSE; this return THIS; new return NEW; String return STRING; main return MAIN; System.out.println return PRINTLN; \+ return OP_PLUS; - return OP_MINUS; \* return OP_MULTIPLY; \/ return OP_DIVIDE; \< return OP_LESS_THAN; \<= return OP_LESS_EQUAL; \>= return OP_GREATER_EQUAL; > return OP_GREATER_THAN; == return OP_EQUAL; != return OP_NOT_EQUAL; && return OP_AND; \|\| return OP_OR; ! return OP_NOT; \; return SEMICOLON; \. return DOT; , return COMMA; = return ASSIGN; \( return S_BRACE1; \) return S_BRACE2; \{ return M_BRACE1; \} return M_BRACE2; \[ return L_BRACE1; \] return L_BRACE2; [a-zA-Z]+[0-9]*[a-zA-Z]* { yylval.resName = addReserve(yytext); return ID; } -?[0-9]+ { yylval.iValue = atoi(yytext); return INTEGER; } [ \t\n]+ . ; %%
헤더파일입니다.
typedef enum {typeCon,typeID, typeInt, typeBool, typeVoid, typeOpr} nodeEnum; /* constants */ typedef struct { int value; /* value of constant */ } conNodeType; /* identifiers */ typedef struct { char* name; } idNodeType; /* operators */ typedef struct { int oper; /* operator */ int nops; /* number of operands */ struct nodeTypeTag *op[1]; /* operands (expandable) */ } oprNodeType; typedef struct nodeTypeTag{ nodeEnum type; /* type of node */ /* union must be last entry in nodeType */ /* because operNodeType may dynamically increase */ union { conNodeType con; /* constants */ idNodeType id; /* identifiers */ oprNodeType opr; /* operators */ }; } nodeType; typedef struct Func_list* FuncPtr; typedef struct Func_list{ char* name; nodeEnum returnType; FuncPtr nextFunc; nodeType* stmtList; } funcNode; typedef struct Class_List* ClassPtr; typedef struct Class_List{ char* name; int memberVar[20]; FuncPtr memberFunc; FuncPtr mainFunc; ClassPtr nextClass; } classNode;
이상입니다 도와주세요..
File attachments:
첨부 | 파일 크기 |
---|---|
없음.jpg | 128.05 KB |
Forums:
header에서.. union
header에서.. union 이름이 먼가요?
--
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Korean Ver: http://www.cinsk.org/cfaqs/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Korean Ver: http://cinsk.github.io/cfaqs/
캐스팅문제일수도..
컴파일에러가 나면 컴파일메시지를 잘 확인해보시요.
왠지 캐스팅문제일 것 같네요. 확인해보세요.
그리고, flex 소스를 보면 nPtr 쓰지도 않는데 굳이 union 에 넣어 놓으신 이유가 있나요?
그리고, ID의 시작은 숫자가 안되지만 "_" 은 되지 않던가요?
헤더선언를 포함하고 있지 않아서 발생한 오류입니다.
pl.yy(?) 또는 lex.yy(?) 파일에서 헤더파일을 추가한(?) 부분에 오류가 있습니다.
다음과 같이 변경하면 해결될 수 있을것 같습니다.
-- 덧붙이는글 --
해결되었을것이라 생각합니다.
댓글 달기