티스토리 뷰
1. lex란 무엇인가?
어휘분석기 코드를 생성하는 도구인 렉스는 어휘(토큰)를 정의해 주면 그것을 인식하여 하나씩 돌려주는 어휘분석기 C 함수 코드를 생성해 준다. 다음 그림과 같이 렉스의 입력 파일(확장자 .l)을 작성하여 렉스를 실행하면 어휘분석기 C 코드가 생성된다. 이것을 컴파일하면 어휘분석기 실행파일 exe가 얻어진다.
어휘분석기는 여러 가지 일을 할 수 있지만 기본적으로는 토큰을 차례로 한개씩 인식해 주는 역할을 한다. 다음 실행 화면은 숫자와 문자열 토큰을 인식하는 실행프로그램의 예를 보여준다.
2. 렉스의 설치
http://techapple.net/2014/07/flex-windows-lex-and-yaccflex-and-bison-installer-for-windows-xp788-1/
이 페이지의 중간에 있는 Download 링크를 눌러 flex Windows(lex&yacc) 프로그램이 설치된다.
시스템 환경설정에서 path에 다음 항목이 추가되었는지 확인 C:\Flex Windows\gcc\bin
바탕화면 시작의 검색창에 "cmd" 입력하여 g++ 명령이 인식되는지 확인해 본다. 윈도우 환경에서는 g++ 명령의 패스가 잡히지 않으면 GNU c++ 컴파일러를 설치하는 단계가 추가로 필요하다. 그리고 에디트플러스의 툴 설정에서 컴파일러를 수정해 주어야 한다. 이것은 여기를 참고하기 바랍니다. 툴설정에서 cpp 대신 g++로 바꿈. ( [원 출처] iit 사이트 )
이 프로그램을 설치하고 시작프로그램의 flex를 실행시키면 다음과 같이 EditPlus 화면이 열린다. 그리고 Tools 메뉴의 Configure your tools 를 선택하면 다음과 같은 창이 열린다. 윈도우 환경이라면 g++이 설치되고 여기서 컴파일러 설정이 g++로 바꾸어져 있어야 한다.
3. 렉스 실행
그럼 이제 렉스 실행할 준비를 마쳤으니 토큰을 정의한 렉스의 입력파일을 만들어보자. File 메뉴에서 New / Lex 를 선택한다. 그러면 렉스 입력을 위한 기본 파일이 Noname1.l 이라는 이름으로 열린다.
사실 이것을 그대로 실행할 수도 있으나 main() 함수의 return 0; 위에 printf("Hello, Lex\n");를 추가해 보자. 그리고 다음의 과정을 거쳐 렉스를 실행해 볼 수 있다. 사실 아무것도 안 하는 프로그램이 만들어진다.
(1) Tool / Lex File Compile
(2) Tool / Lex Build
여기까지 실행한 후 해당 디렉토리를 열어 Noname1.exe가 생성된 것을 확인해 본다. 원래는 이 상태에서 에디트플러스의 다음 툴 명령을 이용하여 바로 실행이 가능해야 하는데, 무슨 이유인지 이 실행파일을 찾을 수 없다는 오류가 난다. 에디트플러스가 생성한 실행파일을 제대로 close 하지 않는 것으로 보인다.
(3) Execute exe directly
이를 해결하기 위해 다음 과정을 거쳐야 한다. 해당 실행파일 Noname1.exe를 다른 디렉토리로 옮기고 그 디렉토리에서 파워쉘을 열어 명령창에서 Noname1 을 입력하면 실행된다. (시스템 환경변수에 .\가 포함되어 있어야 함)
4. 토큰 정의하기
렉스가 생성한 어휘분석기가 우리가 원하는 일을 해 주기 위해서는 렉스 입력파일(Noname1.l)을 수정해 주어야 한다. 이 파일에는 인식하기를 원하는 토큰과 그에 대한 액션을 기술하게 된다.
토큰의 정의는 정규표현식의 형태를 가지며, 어떤 문자를 어떤 규칙에 따라 인식할 것인지 규칙을 써주게 된다. 또한 규칙에 따라 토큰이 인식되었을 때 수행할 액션(코드)를 지정해 줄 수 있다. 액션은 그 토큰을 출력하는 것이 될 수도 있고 개수를 세거나 어딘가에 저장하는 것도 가능하다.
먼저 인식할 토큰을 정의해 보자. %%와 %% 사이에 토큰을 정의하는 규칙이 들어가게 된다. 형식은 다음과 같다.
토큰정의부(정규표현식) 액션부 (C 코드)
토큰정의부와 액션부 사이에는 탭이 들어가야 한다. 다음은 숫자에 해당하는 토큰을 정의하고 그것을 그대로 출력하는 코드를 보여준다. 여기서 yytext는 렉스가 정의한 전역변수로 마지막 토큰의 텍스트를 저장하고 있는 char* 변수다. 두 번째 줄의 규칙은 숫자 이외의 모든 것을 매치하는 정규표현식이다. 위에서 매치되지 않은 것은 모두 여기서 .(점)에 의해 매치된다. 그리고 그 경우 액션은 아무 것도 하지 않는 것이다. (;은 아무 것도 하지 말라는 것을 나타낸다.) 즉 숫자 이외의 것은 모두 무시하라는 뜻이 된다.
%%
[0-9]+ printf("%s\n", yytext);
. ;
%%
다음으로 메인 함수 부분에 추가된 코드를 보자. 룰 부분이 끝난 뒤에(두 번째 %% 다음) 나오는 C 코드는 그대로 생성되는 C 파일의 끝에 덧붙여진다. 이전에 있던 printf 문장은 지우고 yylex();를 넣어준다. 이것은 생성된 렉스 코드의 함수를 호출하는 것이다. 이 함수는 토큰을 인식하는 while 루프를 eof(end of file)가 들어올 때까지 반복한다. 액션에서 return;이 있으면 이 함수는 반환되고 main에게 제어가 돌아온다.
%%
int main()
{
//printf("Hello, Lex..\n");
yylex();
return 0;
}
이렇게 작성된 .l 파일을 Lex File Compile -> Lex Build를 거쳐 실행하면 다음과 같은 실행 결과를 볼 수 있다. 여기서 입력은 디폴트로 표준입력(stdin, 키보드 입력)을 받게 된다.
입력에서 숫자 부분만 구분하여 한 줄에 하나씩 출력한다. 입력에서 ^Z(컨트롤-Z, 입력의 끝을 나타내는 EOF역할)을 넣으면 프로그램이 종료한다. (이것도 엔터를 넣어야 프로그램에 전달됨)
'컴파일러 - regex와 cfg' 카테고리의 다른 글
lex 예제 (2) (0) | 2019.10.27 |
---|---|
lex를 이용한 어휘분석기 예제 (1) (1) | 2019.10.27 |
regex로 아이디와 패스워드의 조건 검사하기 (0) | 2019.08.09 |
정규표현식 네번째 - 캡처그룹 (0) | 2019.08.03 |
정규표현식 세번째 - 위치 지정 (0) | 2019.08.03 |
- Total
- Today
- Yesterday
- CompareTo
- indexof
- typedef
- APPEND
- python example
- 지연계산
- TypeError
- 이터러블
- follow
- rust
- contains
- 자바regex
- C++ 클래스
- sort key
- Lazy evaluation
- 패턴
- ToString
- 콜렉션
- contentEquals
- zip
- max
- Iterator
- 스트링
- 스트링 +
- 동적바인딩
- python exercise
- format
- 이터레이터
- Camel Style
- comparable
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |