이전 포스트에서 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