[질문] 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:
| 첨부 | 파일 크기 |
|---|---|
| 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 에 넣어 놓으신 이유가 있나요?
%union { int iValue; char *resName; nodeType *nPtr; };그리고, ID의 시작은 숫자가 안되지만 "_" 은 되지 않던가요?
헤더선언를 포함하고 있지 않아서 발생한 오류입니다.
pl.yy(?) 또는 lex.yy(?) 파일에서 헤더파일을 추가한(?) 부분에 오류가 있습니다.
%{ #include <stdio.h> #include <string.h> #include "pl.tab.h" /* 이 해더파일이 분석될때 %union내 객체의 자료선언이 미존재하여 발생한 문제입니다 */ //#include "pl.h" //주석 첨가해줘야해!! %}다음과 같이 변경하면 해결될 수 있을것 같습니다.
%{ #include <stdio.h> #include <string.h> #include "pl.h" /* 이 파일이 재정의된 자료형 nodeType을 포함하는 헤더파일로 보입니다. */ #include "pl.tab.h" %}-- 덧붙이는글 --
해결되었을것이라 생각합니다.
댓글 달기