이전 포스트에서 lex, flex만은 Makefile을 작성하기 무척 쉬웠다. 꽤나 만족스럽다.

하지만 yacc, bison을 함께 하면서 모든게 어긋나기 시작했다.
문제의 발단은 lex도 .c파일을 만들어내고 yacc 또한 .c파일을 만들어내는데서 있다.

이게 왜 문제냐하면 두 소스를 같은 이름으로 못 한다는 것이다.

예로 계산기 소스를 작성하는데 calc.l파일과 calc.y파일을 만들었다고 치자.
bison을 먼저 돌려야 하지만(사실 아직 왜 먼저 돌리는지 모른다...) lex를 먼저 공부했기에 lex의 결과물을 보자.

'flex calc.l' 을 수행한다면 결과물은 lex.yy.c가 된다. 하지만 난 이게 싫어 -o 옵션으로 calc.c로 지정을 했다.
머...이유는 단순히 '.'문자가 두번 있는게 보기 싫어서이다.
이런 상황에서 bison을 돌려야 한다면...'bison -d calc.y' 명령을 사용하겠지만 이 또한 calc.tab.c와 calc.tab.h 파일을 만들어 낼테니 -o 옵션을 사용하려 한다. 하지만 calc.c파일은 이미 flex가 만들어낸 결과물이 있기 때문에 같은 이름을 사용할 수 없다.

젠장...결국 두 소스의 이름을 달리 가거나 두 소스의 컴파일 결과물의 파일이름을 다르게 지정해야한다.
결과적으로 현재는 두 소스의 이름을 별도로 가져갔다. 머가 옳은지 머가 일반적인지 모르겠다.

그래서 만들어진 Makefile

calc : calc.c parser.c
        $(CC) -o $@ $^ -l$(LIBS)

calc.c : calc.l parser.h
        $(LEX) -o $@ $<

parser.c : parser.y
        $(YACC) -o $*.c $<

parser.h : parser.y
        $(YACC) -o $*.c $<

'개발관련 > (Fast)Lex' 카테고리의 다른 글

lex 간단한 예제2  (0) 2013.10.25
lex 시작하기  (0) 2013.10.24
시작하기에 앞서...  (0) 2013.10.24
확장자 규칙의 사용  (0) 2013.10.24
lex를 위한 간단한 Makefile  (0) 2013.10.24

이번에는 enum을 이용한 심볼 테이블을 이용한 예제

%{
enum {
        NONE = 0,
        ONE,
        TWO,
        THREE,
        FOUR,
        FIVE,
        SIX,
        SEVEN
};
int number;
void action();
%}
%%
oneone  { number = SEVEN; action(); }
one |
ONE  { number = ONE; action(); }
two |
TWO  { number = TWO; action(); }
three |
THREE  { number = THREE; action(); }
four |
FOUR  { number = FOUR; action(); }
five |
FIVE  { number = FIVE; action(); }
six |
SIX  { number = SIX;  action(); }
[a-zA-Z]+ { number = NONE; action(); }
%%
void action()
{
        if (number != NONE)
                printf("%s is %d\n", yytext, number);
        else
                printf("%s?? I don't learn it.\n", yytext);
}
 
main()
{
        yylex();
}

문자로 one이나 혹은 six까지 입력을 했을때 enum에서 정의한 숫자와 매치해서 미리 정해둔 문장을 출력한다.

'개발관련 > (Fast)Lex' 카테고리의 다른 글

Yacc, Bison으로 인한 문제  (0) 2013.10.25
lex 시작하기  (0) 2013.10.24
시작하기에 앞서...  (0) 2013.10.24
확장자 규칙의 사용  (0) 2013.10.24
lex를 위한 간단한 Makefile  (0) 2013.10.24

블로깅의 목적이 타인에게 지식을 공유하기 보다는 내 스스로의 지식 저장소로 쓰기 위한 목적이 더 크므로 방문자를 위한 배려가 고려되지 않았다.
그래서 lex가 어떻게 생겨났고 어떻게 쓰이며 어떻게 설치하고 그런 부분은 과감히 생략한다.
아마도 대부분의 linux라면 설치가 되어있으리라 생각한다. 여튼...내가 사용하는 회사 서버에는 설치가 되어있다.

인터넷에서 검색해서 나온대로 컴파일 방법은 아래와 같다

lex [OPTIONS] [FILE]...

머...옵션은 무쟈게 많다. 기껏 버전은 2.5.35인데 머가 이리 많은지...
그리고 버전과 해당 옵션 설명을 대충이라도 보기위해 매뉴얼을 펼쳐본 순간...내 시스템에서 lex는 flex라는 걸 알게되었다;;;

$ ls -al `which lex`
lrwxrwxrwx. 1 root root 4 2012-03-27 05:33 /usr/bin/lex -> flex*

이게 머야...그럼 지금 난 lex를 하고 있는건가 flex를 하고 있는건가...처음부터 혼돈의 카오스가 밀려오는구나...

각설하고 이전 포스팅에서 사용했던 간단한 예제를 컴파일 해보자.

%%
.|\n ECHO;
%%

main()
{
    yylex();
}

위 예제는 입력을 그대로 화면에 출력해 주는 예제이다. 기본적으로 입력받은 그대로 echo 해주는 것 같음.
그리고 글을 쓰고 있는 지금도 yylex();가 무엇을 의미하는지 모르겠다.
모르겠다고 해놓고 지나가려다 보니 궁금해서 한번 뒤져봤더니 아래와 같단다.

// Call yylex with new input/output sources.
int yylex( FLEX_STD istream* new_in, FLEX_STD ostream* new_out = 0 )
    {
    switch_streams( new_in, new_out );
    return yylex();
    }

// Switch to new input/output streams.  A nil stream pointer
// indicates "keep the current one".
virtual void switch_streams( FLEX_STD istream* new_in = 0,
                FLEX_STD ostream* new_out = 0 ) = 0;

이번에는 간단한 파싱이 들어간 예제이다

%{
        /*
         * My favorite...
         */
%}
%%
[\t ]+  ;
rain |
rose            { printf("%s!! That is my favorite.\n", yytext); }
love |
story           { printf("%s!! I like a love story. ^_~\n", yytext); }
"potato chip" |
potato |
chip  { printf("%s...!! now and then, I have a potato chip.\n", yytext); }
 
[A-Za-z]+ { printf("%s..., what is that?\n", yytext); }
 
.|\n    { ECHO; }
 
%%
main()
{
        yylex();
}

rain, rose, love, story, ptato chip, potato, chip에 대한 패턴 처리가 들어있다. lex에서도 | 문자는 or와 같은 의미로 쓰이나보다.
7번 라인의 구문은 먼지 모르겠다;;

[\t ]+  ;

 

'개발관련 > (Fast)Lex' 카테고리의 다른 글

Yacc, Bison으로 인한 문제  (0) 2013.10.25
lex 간단한 예제2  (0) 2013.10.25
시작하기에 앞서...  (0) 2013.10.24
확장자 규칙의 사용  (0) 2013.10.24
lex를 위한 간단한 Makefile  (0) 2013.10.24

회사 내에서 프로젝트를 진행하며 SQL Parser(이하 파서)가 필요했다.
물론 회사에서 개발을 이제 막 시작한 내게 제대로 된 파서를 기대하진 않을테지만, 아마도 최소한 회사는 내가 파서를 공부하면서 관련 정보를 얻고 지식을 습득하기는 바랄것이다.

무작정 정보의 바다에서 SQL 파서에 관한 정보를 얻다보니 가장 처음 Lex&Yacc를 알게 되었다.
그리고 Plex&Bison에 대해서도...또, Lemon에 대해서도 알게 되었다.
Lex를 보다 보니 Plex가 더 좋다는 글이 눈에 띄고 또 Lemon의 장점을 기술해 놓은 자료를 보면 첨부터 Lemon으로 공부해야하나 싶었지만...
결국 지금 난 Lex를 보고 있다.(이머병....)

처음엔 블로그에 Lex를 따로 구분하지 않고 기타나 개발관련으로 포스팅 하려 했는데 지금...거창하게도 따로 분류하여 포스팅을 하려 한다.
얼마나 갈지는 모르겠지만...
후에도 이 글이 남아있다면 어느정도 Lex를 알게 되고 블로그에 정보를 남긴 모습이리라...

'개발관련 > (Fast)Lex' 카테고리의 다른 글

Yacc, Bison으로 인한 문제  (0) 2013.10.25
lex 간단한 예제2  (0) 2013.10.25
lex 시작하기  (0) 2013.10.24
확장자 규칙의 사용  (0) 2013.10.24
lex를 위한 간단한 Makefile  (0) 2013.10.24

이전 포스트에서 lex를 컴파일 하기 위해 간단하게 Makefile을 작성했다.
lex를 위한 간단한 Makefile

참고로 난 개발자 입문자라고 하기에도 부족한 4년재 대학생만도 못한 실력을 지녔기에,
예제 소스를 하나 추가할 때 마다 일일히 추가해 줘야하는 번거로움이 있었다.
물론 단지 4줄에 불과하지만...먼가 방법이 있지 않을까 하고 생각했다.

기존 소스를 보자.

test : test.c
        $(CC) -o $@ $< -ll

test.c : test.l
        $(LEX) -o $@ $<

test2 : test2.c
        $(CC) -o $@ $< -ll

test2.c: test2.l
        $(LEX) -o $@ $<

number : number.c
        $(CC) -o $@ $< -ll

number.c: number.l
        $(LEX) -o $@ $<

다른 개발자 분들이 쓰는 Makefile을 참고하여 아래와 같이 추가하니 2줄이 줄어드는 기적을 낳으셨다.
이는 .c와 대응 되는 .l은 아래 규칙으로 수행하라는 의미가 된다. 이렇게 추가한 경우 .c에 대한 명령을 일일히 추가할 필요가 없어진 것이다.

.SUFFIXES : .c .l
.l.c :
        $(LEX) -o $@ $<

'개발관련 > (Fast)Lex' 카테고리의 다른 글

Yacc, Bison으로 인한 문제  (0) 2013.10.25
lex 간단한 예제2  (0) 2013.10.25
lex 시작하기  (0) 2013.10.24
시작하기에 앞서...  (0) 2013.10.24
lex를 위한 간단한 Makefile  (0) 2013.10.24