본문 바로가기
컴퓨터 지식

[컴파일러 설계] Lex를 이용한 C 어휘분석기 구현

by LiveData 2018. 12. 9.
반응형

컴파일러 설계


1. 개요(목적)


Lex를 이용해서 단어들을 인식하게 만든다. C언어의 명령어들을 인식하게 만들어서 C의 명령어나 심볼들을 출력하게 만든다. 그 외 변수나 숫자(정수, 소수 등) 인식하게 만든다. 함수를 이용해서 C 명령문을 실제로 동작하게 만들어본다. 더 나아가가 따로 Yacc의 함수를 만들어서 숫자들을 인식하여 간단한 사측연산을 할 수 있게 만든다.

 


2. 구현 내용


LEX를 이용해서 값이 오면 인식하고 그 값을 반환하는 것을 구현

.

Symbol : +, -, *, /, \, \n, if, else, while, for, char, int, double, identity(식별자) return 등을 인식하게 만들고 인식이 되면 출력.

(if) (for) (while) ( ) { }


숫자 : DECIMAL [0-9]* 까지의 정수를 통해 {DECIMAL}은 정수를 인식하게 만들었고 {DECIMAL}\.{DECIMAL}은 실수를 인식하게 만들었습니다.

(DEC, 3) (DEC,12) (NUM, 2.126)


연산 : 정수나 실수가 나왔을 시 뒤에 +,-,*,/ 가 나오면 다음 숫자를 연산하여 결과 값 을 출력합니다.

3 + 5 = 8 3.21/1.52=1.69


문자 : 식별자는 LETTER ([A-Za-z]) 로 단일문자와 IDENTIFIER ({LETTER} ({LETTER} | {DECI})*) 의 문자+숫자의 변수 인식할 수 있다.

(ID , a123) (ID , num123)

 



YACC를 이용해서 숫자가 들어오면 전에 나온 숫자 연산 형태와 값을 우선순위 연산을 실행 합니다.

사측연산 : +,-,*,/ *,/가 먼저 계산 한다. cal을 입력 후 계산식을 입력하면 parser() 함수로 yacc 인식기를 동작하게 하여 판별 후 계산한다.

cal 3+5*4; 4.2/3.3+5.7*2.7;



실행

 

# yacc dv y.y y.tab.h y.tab.c생성

# lex Compile.l lex.yy.cc 생성

# cc o a.out y.tab.c lex.yy.c 실행파일 a.out을 만듬

# ./a.out < input > out 입력한 input을 분석기로 변환한 out으로 보냄




실행 결과



 

 

 

 

인식 변수

설명

DECIMAL

정수를 인식. 인식한 값을 yylval로 전달

NUMBER

실수를 인식. 인식한 값을 yylval로 전달

LOWER, UPPER, LETTER

각각 소문자 대문자 혼합을 인식한

IDENTIFIER

문자+숫자의 변수를 인식

“\”.*“\”

각 심볼을 인식

\(, \), \{, \}

중괄호 대괄호를 인식

; , =

; , 값이 오면 그대로 전달하여 출력

+ - * /

연산의 심볼이 오면 인식

\n

엔터를 치면 라인의 line_count 값 올림.

if, else, while, for

char, int, void

double, return

 

명령어들을 인식하면 출력을 해줌

// 차후 lex함수나 yacc로 구현 예정





LEX 코드


 

 

Cal_num(실수 연산)

Cal_dec(정수 연산)

Lex로 만든 2개의 숫자끼리 연산을 해줍니다. 정수나 실수의 숫자가 오면 다음 연산(+,-,*,/) 를 인식하고 다음 나오는 숫자를 인식하여 둘의 연산을 실행합니다.

But lex의 함수만으로 우선순위를 나누기 힘들어서 후에 YACC를 이용하였습니다.

<b>  </b>

결 과

 


 



 

각각의 인자 전달


각각의 인식한 값들을 인식하였다고 전달 받아 print 출력을 해줍니다. 정수나 숫자가 올 경우 전의 cal_dec, cal_num의 함수로 +,-,*,/ 의 연산 심볼이 오는지 확인하여 연산 심볼이 올 경우 연산을 하고 아닐 경우 숫자 인식값을 출력 합니다.

 

YACC 코드




 

./실행

 


 Lex 동작 원리

( 3+2*5 )

 

term(3)


3primary_expr 로 인식하고 term 으로 올라와 */ 가 있는지 확인 후 없으면

다시 expr로 바꾸준 후 shift를 해준다.

 

expr(3)

‘+’

 

그다음 ‘+’ 가 들어오고 어느 상황에 만족하지 않으므로 다음 shift를 한다.

 

expr(3)

‘+’

term(2)

 

+의 연산식이 완성되긴 하나 다음 나올 연산이 *인걸 알기 때문에 shift를 한다.

 

expr(3)

‘+’

term(2)

‘*’

primary_expr(5)

 

{ 이부분이 term MUL priamry_expr과 매칭되어 계산}

 

expr(3)

‘+’

term(10)

 

{ expr ADD term 과 매칭되므로 계산 }

 

expr(13)

 

최종적으로 13의 숫자가 남는다.

=> 우선순위 계산을 쉽게 할 수 있었다.

 

반응형