티스토리 뷰

앞의 글에서 렉스의 설치와 실행 방법을 살펴보았다. 이번에는 좀더 본격적인 lex 사용 사례를 살펴보겠다.

%option noyywrap
%{ 
	int lineno = 0;
%}
digit	[0-9] 
number	{digit}+ 
float 	{number}(\.{number})? 
newline \n 
%%
{number}	{int n = atoi(yytext); 
		 printf("[%2d] %5d\n", lineno+1, n);} 
{float}		{float n = atof(yytext);
		 printf("[%2d] %f\n", lineno+1, n);} 
{newline}	{lineno++;} 
. 		;
%%
int main()
{
	yylex();
	return 0;
}

이 예제에서는 룰 부분(%%와 %% 사이)의 앞에 들어가는 두 가지 부분을 보여준다.

%{ ... %}는 생성되는 코드에 삽입될 부분이다. 기본 인클루드 파일 이외에 필요한 #include나 #define 또는 전역변수의 선언이나 함수 전방선언 등이 들어가게 된다. 이것은 생성되는 코드에셔 실행부가 나오기 전에 끼워 넣어진다.

다음은 %% 앞에 들어간 digit, number 등의 정의부가 나온다. 여기는 토큰 규칙부에서 사용할 이름을 정의할 수 있다. 이 정의부에서 정의된 이름은 보통 정규표현식 부분을 가지는 일종의 매크로(그대로 끼워넣기)라고 생각할 수 있다. 이러한 정의된 이름은 규칙부에서 집합괄호({...})로 둘러싸인 이름으로 사용된 것을 볼 수 있다.

토큰의 액션부에서는 앞에서 선언한 전역변수를 사용할 수 있으며 이 코드의 뒤나 다른 소스 파일에 나오는 함수도 전방선언을 해두었다면 쓸 수 있다. 액션부에서 전역변수 lineno를 사용하고 있음을 확인할 수 있다.

토큰 규칙부에서 중요한 점은 토큰이 규칙에 매치되는 방식을 이해해야 한다.

먼저 토큰은 규칙에서 나온 순서대로 매치된다. 이 경우 number가 먼저 매치되고 float가 매치된다. 그런데 float 토큰은 number에 의해 매치되는 부분을 포함한다. 소수점 이하가 생략될 수 있으므로 이 경우 float 규칙이 먼저 나오고 number 규칙이 나오면 number 규칙이 매치될 수 없다는 오류 메시지가 나오게 된다. 그러므로 더 큰 언어 집합을 가지는 토큰은 나중에 나와야 한다. 앞에서 매치되지 않은 경우만 그 규칙에 매치된다. (여기서는 소수점이 없으면 number에 매치되고 소수점이 있는 숫자만 float에 매치된다)

두번째 규칙은 토큰을 최대한 크게 매치하려고 한다는 점이다. 위의 예에서 소수점 수가 나올 때 number가 먼저 정수부에 매치되어 버리면 소수점 수는 매치될 수 없을 것이다. 이 때 적용되는 규칙은 longest match 규칙이어서 number가 인식된 후에 더 긴 토큰을 가지는 규칙이 아래쪽에 있으면 그것을 시도하게 된다. 이때 그것이 매치가 되지 않으면 일종의 백트랙 방식으로 number가 다시 매치될 것이다.

이러한 규칙의 매치 방식은 처음에는 주의하지 않으면 이해하기 어려운 부분이다. 또한 렉스를 사용할 때 미리 이해하고 있지 못하면 문제를 찾기가 어려워지는 부분이라고 할 수 있다.

다음은 좀더 복잡한 예제를 살펴보자.

digit	[0-9] 
number	{digit}+ 
newline	\n 
letter	[a-zA-Z0-9_] 
id	{letter}+ 
email	{letter}+@{letter}+\.({letter}+\.)?(ac.kr|com|or.kr|org|net) 
%% 
{number}	{
			int n = atoi(yytext);
			printf("%5d %5d (NUM)\n", lineno, n);
		} 
{email}		{
			printf("%5d  %s (EMAIL)\n", lineno, yytext);
		} 
{id}		{
			printf("%5d  %s (ID)\n", lineno, yytext);
		} 
{newline}	{ lineno++; }

여기서는 특별하게 새로 나오는 내용은 별로 없다. id와 email이라는 토큰이 추가되었다. 

여기서도 주의해야 될 점은 토큰간의 포함관계다. id는 number를 포함하고 있으며, email은 앞부분이 id와 같다. 이 경우 해당하는 토큰을 찾는대로 출력하는 액션을 가지고 있다. 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함