그리고 답변은 아니지만...
lex, yacc 대신 boost의 spirit library를 쓰는 것도 한가지 방법일 듯 합니다. :wink: http://spirit.sf.net
저는 사실 lexy, yacc 공부하다가 포기하고 spirit부터 시작했는데 아주 만족스럽습니다. :)
동아리 홈페이지에 올려놓은건데... 로그인해야 들어가지네요...
그냥 주르륵 긁어서 올려봅니다... :lol:
Quote:
몇번 사용하다보니 좀 귀찮은 작업들이 몇개 있어서
정리해봅니다. (나중에 까먹으면 참고하라구... -.-;)
[준비]
당연히 flex와 bison이 필요합니다. 또한 실행가능한
패스에 설치되어 있어야 하구요. cygwin 설치한 담에
cygwin/bin을 패스에 추가하면 별 문제 없읍니다.
[작성]
렉스 파일과 야크 파일을 만들어야 합니다. 처음부터
완전히 만들 필요까지는 없겠지만 일단 만들어놓고...
VCPP의 프로젝트에 추가합니다. (Workspace의
FileView에서 오른쪽 버튼 눌러 파일 추가하면 됩니다.)
C/CPP/H/RC 등등의 파일이 아니기 때문에 소스 파일이나
헤더 파일 폴더로 안가고 걍 루트에 깔립니다.
[설정]
일단 렉스 파일 설정부터 하겠습니다. 렉스 파일 오른쪽
버튼 눌러 [settings...] 선택합니다. VCPP가 알지 못하는
파일이므로 [Custom Build]가 활성화됩니다. 여기에
Command 항목에 다음을 추가합니다.
>> flex $(InputPath)
Output으로는 당연히
>> lex.yy.c
가 됩니다. 필요하다면 flex에 임의의 옵션을 추가할 수
있습니다.
플렉스 설정 역시 비슷합니다.
Command 항목에는
>> bison -d $(InputPath)
Output으로는
>> $(InputName).tab.c
>> $(InputName).tab.h
를 지정합니다.
그리고 컴파일을 하면 lex.yy.c, $(InputName).tab.c,
$(InputName).tab.h 가 생성됩니다. 이걸 다시 프로젝트에
추가하고 *.c 파일의 [settings...]에서 precompiled header를
사용하지 않도록 설정합니다.
flex와 bison은 CPP output을 낼 수 있는 기능이 있습니다.
이걸 사용하기 위해서는 위 설정보다 해야할 일이 몇가지
더 있습니다.
플렉스 설정은 일단 Command가
>> flex -+ $(InputPath)
로 CPP 형식의 파일을 생성하도록 합니다. Output 파일은
lex.yy.cc가 나옵니다. 하지만 이 파일은 정상적으로 cpp
컴파일러에 의해 컴파일되지 않습니다. 두가지 문제가
있는데요, 첫번재는 헤더파일 FlexLexer.h 의 문제이고
또다른 하나는 소스파일 자체에 한줄의 에러를 포함하기
때문입니다.
우선 FlexLexer.h는 cygwin/usr/include/FlexLexer.h에서
구할 수 있습니다. 내용을 살펴보면
#include <iostream.h>
라는 라인을 볼 수 있습니다. 사실 이게 오류를 내는 것은
아니고 경고를 좀 냅니다. 이에 대한 경고 내용은 CPP 책을
참고하시고, 하여간 이것은
#include <iostream>
using std::istream ;
using std::ostream ;
으로 바꿔줍니다. 뭐 라이브러리 헤더 파일을 고친다고 껄끄
러워 할 필요는 없습니다. FlexLexer.h는 다른 cpp 파일과
연결된게 전혀 없습니다. (장담은 못하지만)
다음은 생성된 lex.yy.cc 파일을 수정해야 합니다.
라인 24: class istream;
라인 25: #include <unistd.h>
이 두 라인이 문제입니다. 첫째 istream은 STL로 선언된 넘으로
템플리트지 class가 아닙니다. 둘째로 VCPP는 unistd.h를 가지고
있지 않습니다. 그래서 다음처럼 바꿔줘야 합니다.
#include <iostream>
usnign namespace std ;
//#include <unistd.h>;
그럼 컴파일할 때마다 플렉스 한번 돌리고 파일 수정하고 저장
해서 다시 컴파일하고... 그럴수는 없습니다. -.-;;
그래서 렉스 파일의 설정에 sed를 사용해서 매번 자동으로
바꿔주도록 설정합니다.
>> flex -+ $(InputPath)
>> sed -f lex-sed lex.yy.cc > lex.yy.cpp
그럼 VCPP가 뭔지 알아듣는 lex.yy.cpp를 생성해주죠.
(*.cc가 C++ 파일이라는 걸 모르는 것 같더군요.)
파일 lex-sed 내용은 다음과 같습니다.
>> 1~1000000 i#include "stdafx.h"
>> s/class istream;/#include <iostream>\nusing namespace std ;/g
>> s/#include <unistd.h>;/\/\/#include <unistd.h>;/g
첫번째 줄은 파일의 처음에 #include "stdafx.h"를 추가하기
위한 명령입니다. 1~1000000 라인 블럭마다 #include... 를
추가하라는 명령인데 원래는 1~$ i#include ...가 되어야
합니다만 제 컴터의 sed가 '$'를 못 알아듣는군요. 그래서
대충 100000000000을 넣어둔겁니다. 너무 작은 수를 지정하면
곤란해집니다. ^^: 2-3라인은 replace 명령입니다.
하여튼 이로써 lex.yy.cpp 파일이 생성됩니다. 이 파일을
Output에 적어주세요.
>> lex.yy.cc
>> lex.yy.cpp
그럼 렉스 파일의 컴파일이 완료된 겁니다.
bison은 lex와 같은 문제점은 없습니다만, 보통 사용하는
*.y라는 확장자를 사용하지 않고 *.ypp 라는 넘을 사용해야
*.cpp를 생성합니다. 문제는 *.h도 *.hpp를 생성한다는거죠.
뭐, 그냥 렉서와 야크 명세서에 #include "*.tab.hpp"로 한줄
고쳐줌으로써 해결될 문제이긴 합니다만. 하여간 Command는
>> bison -d $(InputPath)
Output은
>> $(InputName).tab.cpp
>> $(InputName).tab.hpp
입니다.
한가지 문제점은 *.tab.cpp인데 이넘을 precompiled header를
사용하지 않도록 설정을 바꿔줘야 한다는거죠. 물론 첫 라인에
#include "stdafx.h" 를 추가해주면 되는데 sed는 원본 파일을
수정하지 않기 때문에
sed 1~1000000000 i #include ... >> $(InputName).tab.cpp
하면 문제가 될것 같습니다. 임시 파일로 옮기고 복사하면
되겠습니다만 좀 보기가 안좋아서...
>> sed 1~100000000 i#include \"stdafx.h\" $(InputName).tab.cpp >> temp.cpp
>> mv -f temp.cpp $(InputName).tab.cpp
어떨지 모르겠지만 껄끄럽습니다. -.-;
google에서 찾아보니 몇가지 나오는군요. 상용은 mks가 있고요...
google에서 찾아보니 몇가지 나오는군요. 상용은 mks가 있고요...
free로는
http://people.bu.edu/kalathur/cs568_spring_03/FlexTutorial.html
그리고 답변은 아니지만...
lex, yacc 대신 boost의 spirit library를 쓰는 것도 한가지 방법일 듯 합니다. :wink:
http://spirit.sf.net
저는 사실 lexy, yacc 공부하다가 포기하고 spirit부터 시작했는데 아주 만족스럽습니다. :)
예전에 정리해놓은 거였는데...
동아리 홈페이지에 올려놓은건데... 로그인해야 들어가지네요...
그냥 주르륵 긁어서 올려봅니다... :lol:
다시 읽어보니... 좀 껄끄러운 방법이군요...
그래도 뭐, 그럭저럭 사용했으니... :oops: 귀차니즘 때문에 또다시
필요해지지 않는 이상 고칠것 같지는 않군요... 헐...
--------------------------------------
재미없는 일은 하지 말자는 인간 쓰레기.
-.-;
댓글 달기