[질문] bison 관련 질문입니다.

ddangkyoung의 이미지

원인 없는 버그는 없다지만
이런 버그가 정말 제일 싫습니다.
바이손에서 제공하는 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: 
첨부파일 크기
Image icon 없음.jpg128.05 KB
cinsk의 이미지

sql2의 이미지

컴파일에러가 나면 컴파일메시지를 잘 확인해보시요.

왠지 캐스팅문제일 것 같네요. 확인해보세요.

그리고, flex 소스를 보면 nPtr 쓰지도 않는데 굳이 union 에 넣어 놓으신 이유가 있나요?

%union {
	int iValue;
	char *resName;
	nodeType *nPtr;
 
};

그리고, ID의 시작은 숫자가 안되지만 "_" 은 되지 않던가요?

lovewar의 이미지

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"   
%}

-- 덧붙이는글 --
해결되었을것이라 생각합니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.