컴파일러 HW#2

LEX & YACC 을 이용한 구문 분석기 구현

목차
1	개요
2	결과화면 및 설명
3	syntex diagram
4	EBNF 표현식
5	소스코드

과목
과목명	컴파일러
담당교수님	김학수
제출자
학번	20021558
성명	경규성

1. 개요. LEX&YACC을 이용한 구문 분석기 구현

다음과 같은 기능을 갖는 언어를 고안하고자 한다.

1) 정수형과 실수형 자료형이 존재한다.

2) 변수 선언부가 존재햐며, 선언되지 않은 변수는 사용할 수 없다.

3) +, -, *, / 오퍼레이터가 존재한다.

4) 변수값을 출력할 수 있는 함수가 존재한다.

5) 라인별로 커멘트를 달 수 있다.

6) 새로운 자료형이나 오퍼레이터 추가 시 추가점.

7) 구문 규칙마다 번호를 부여하고 우파스와 실행결과를 동시에 출력하는 구문분석기를 구현하시오.

2. 결과화면 및 설명

5. 소스코드

SCANNER(LEX) 파일 calc.l

%{

#include "calc.tab.h"

#include <math.h>

#include <string.h>

typedef struct{

double val;

char type;

char name[20];

}ST;

extern	ST sym_table[26];

extern	int sym_count;

extern	char cur_name[20];

%}

L [a-zA-Z]

D [0-9]

N [1-9]

%%

{D}*	{ yylval.value = atoi(yytext); return INT; }

{D}+"."{D}+	{ yylval.value = atof(yytext); return FLOAT; }

"int"|"INT"	{return TINT;}

"float"|"FLOAT"	{return TFLOAT;}

"print:"	{return TPNT;}

"bye"	{return TEND;}

"+="	{return TADD;}

"-="	{return TSUB;}

"*="	{return TMUL;}

"/="	{return TDIV;}

"//".*	{return TCMT;}

({L}|"$")({L}|{D}|"$")*	{

if(sym_count >= 26){

printf("too many variable (under 26)\n");

return 0;

}

strcpy(cur_name, yytext);

//printf("yytext: %s\n", yytext);

if(is_there() == 1){

yylval.var_no = get_index();

return IDEN;

}

else{

yylval.var_no = sym_count;

return IDEN;

}

}

[ \t]	;

\n|.	{return yytext[0];}

%%

void yyerror(char *s)

{

printf(": %s at %s\n", s, yytext);

}

PARSER(YACC) 파일 calc.y

%{

#include <math.h>

#define MAX 26

typedef struct{

double val;

char type;

char name[20];

}ST;

ST sym_table[MAX];

int sym_count;

char cur_name[20];

%}

%union {

double value;

int var_no;

}

%token TCMT

%token TEND

%token <var_no> IDEN

%token <value> INT

%token <value> FLOAT

%token TINT

%token TFLOAT

%token TPNT

%token TADD TSUB TMUL TDIV

%right '='

%left '+' '-'

%left '*' '/'

%right '^'

%nonassoc UMINUS

%type <var_no> type

%type <value> expr

%type <var_no> AOP

%%

stm_list: stm '\n' {printf("(node1)\n");} | stm_list stm '\n' {printf("(node2)\n");} ;

stm:

type IDEN { // type and IDEN : variable declare

if(is_there() == 1){// there is same name

printf("[Ignore] aleady declared(DECLARE)\n");

cl_curname();

}

else{	// insert new IDEN inform into symbol table

sym_count++;

sym_table[sym_count].type = $1; // type save

strcpy(sym_table[sym_count].name, cur_name); // name save

}

printf("(node3)");

} |

type IDEN '=' expr { // type and assign : declaer variable and assign

if(is_there() == 1){// there is same name

printf("[Ignore] aleady declared(DELCLARE ASSIGN)\n");

cl_curname();

}

else{	// insert new IDEN inform into symbol table

sym_count++;

sym_table[sym_count].type = $1; // type save

strcpy(sym_table[sym_count].name, cur_name); // name save

sym_table[sym_count].val = $4; // value save

}

printf("(node4)");

} |

IDEN '=' expr { // IDEN and expr : general assign

if(is_there() == 1){// there is same name

sym_table[$1].val = $3;

}

else{

printf("[Ignore] undeclared variable(ASSIGN)\n");

cl_curname();

}

printf("(node5)");

} |

IDEN AOP expr { // IDEN and AOP tokens : operation with assign

if(is_there() == 1){

if($2 == 'a'){

sym_table[$1].val += $3;}

else if($2 == 's'){

sym_table[$1].val -= $3;}

else if($2 == 'm'){

sym_table[$1].val *= $3;}

else if($2 == 'd'){

sym_table[$1].val /= $3;

}

}

else{

printf("[Ignore] undeclared variable(ASSIGN OP)\n");

cl_curname();

}

printf("(node6)");

} |

TPNT IDEN { // print token : print argument

if(is_there() == 1){

if(sym_table[get_index()].type=='i'){

printf("=%d\n", (int)sym_table[get_index()].val);

}

else{

printf("=%g\n", sym_table[get_index()].val);

}

}

else{

printf("[Ignore] undeclaerd variable(TPNT)\n");

cl_curname();

}

printf("(node7)");

} |

/*

TPNT expr { // print expr : print expression

printf("=%g\n", $2);

printf("(node7)");

} |

*/

TCMT {	// comment token : do nothing

printf("(node8)");

} |

TEND {  // end token : exit interpreter

printf("(node9)");

printf("2007 fall, made by 20021558..\n");

return 0;

};

// expression +, -, *, ^, / etc..

expr:	expr '+' expr {$$ = $1 + $3; printf("(node10)");} |

expr '-' expr {$$ = $1 - $3; printf("(node11)");} |

expr '*' expr {$$ = $1 * $3; printf("(node12)");} |

expr '^' expr {$$ = pow($1,$3); printf("(node13)");} |

expr '/' expr

{if($3==0.0) yyerror("divide by zero"); else $$ = $1 / $3; printf("(node14)");} |

'-' expr %prec UMINUS {$$ = -$2; printf("(node15)");} |

'(' expr ')' { $$ = $2; printf("(node16)");} |

INT { $$ = $1; printf("(node17)");}  |

FLOAT { $$ = $1; printf("(node18)");} |

IDEN { $$ = sym_table[get_index()].val;

printf("(node19)");

} ; // pop from sym_table[index]

// assign with operation

AOP:	TADD {$$ = 'a'; printf("(node20)"); } |

TSUB {$$ = 's'; printf("(node21)"); } |

TMUL {$$ = 'm'; printf("(node22)"); } |

TDIV {$$ = 'd'; printf("(node23)"); } ;

// types are int and float only. they return 'i' or 'f'

type: TINT {$$ = 'i'; printf("(node24)");} |

TFLOAT {$$ = 'f'; printf("(node25)");};

%%

// init symbol table and symbol counter

void init_sym_table(){

int i;

for(i=0; i<MAX; i++){

sym_table[i].type = 'n';

}

sym_count = -1;

}

// find tried variable name from symbol table

int is_there(){

int i=0;

while(i <= sym_count){

if(strcmp(sym_table[i].name, cur_name) == 0 ){

return 1;

}

i++;

}

return -1;

}

// get index of variable name from symbol table

int get_index(){

int i=0;

while(i <= sym_count){

if(strcmp(sym_table[i].name, cur_name) == 0 ){

return i;

}

i++;

}

return -1;

}

// cleare current tried variable name buffer

int cl_curname(){

int i=0;

while(cur_name[i] != '\0'){

cur_name[i] == '\0';

i++;

}

//sym_count--;

}

// main fuction

main()

{

printf("+++++++++++++++++++++++++++++++++++++++++\n");

printf(" Compiler HW #2 : Interpreter. 2007 fall \n");

printf(" SID : 20021558, NAME : Kyung kyu-sung   \n");

printf("+++++++++++++++++++++++++++++++++++++++++\n");

printf("\n");

init_sym_table();

yyparse();

}