brunch

You can make anything
by writing

C.S.Lewis

by 쑹이씨 Jan 10. 2016

Lexer의 실용성

아는 게 힘이었다

Lexer

나는 Lexer는 나와는 관계없는 컴파일러를 만들 때 쓰는 저수준의 툴이라고 생각했었다.

위키피디아에는 아래와 같이 설명된다.

lex는 구문 분석기를 읽어와서, Lexer를 만든 뒤 이를 C 언어로 만들어진 소스 코드의 형태로 출력한다.

그래서 그게 무엇인지 안 뒤로는 근처에도 안 갔고, 생각도 해본 적이 없었다.


한계에 부딪히다

HTML을 DIFF로 비교하기 위해 배열로 쭉 나열하려고 했다.

나는 HTML 태그 단위로 자르고, 기호 단위로 자르고, 숫자 이후로 잘랐다.


"<b>2000원</b>"

["<b>","2000","원","</b>"]

이 되었고, 나는 흐뭇했다.


이어서 

"http://mabook.com/2016"

["http", "://", "mabook", ".", "com", "/", "2016"]

가 되었다. (응?)


난도질당해버린 URL을 보면서, 내가 대체 무슨 짓을 한 건가 싶었다.


그리고 

"02-000-1234"

도 처참히

["02", "-", "000", "-", "1234"]

가 되어있었다.


나는 이들의 생명을 찾아주고 싶었다.


먼저 챙겨줬다

URL, 전화번호 패턴은 먼저 치환을 해줬다.

#{1}, #{2},  #{3}으로 각각 치환하고, 저장해뒀다.

그리고 HTML 태그, 기호, 숫자로 잘랐다.

하아... ["#", "{", "1", "}"] ... 어쩔 거...


잘랐다

URL, 전화번호 패턴을 기준으로 전체 텍스트를 여러 개로 잘라줬고,

각각의 덩어리들을 HTML 태그, 기호, 숫자로 잘라 배열로 만들고,

다시 각 배열들을 합치면서 URL, 전화번호를 다시 끼워줬다.


성공.

근데 앞으로도 이러고 살아야 하나 싶어 졌다.

그 큰 텍스트를 자르고 배열로 만들고, 또 각각의 요소들을 저장해뒀다가 합쳐주고..

빠르게 하지는 못하겠다 싶었다.


Lexer가 떠올랐다

1. lexer는  앞에서부터 한 글자씩 이동하면서

2. 정규식을 차례로 대입하다가

3. 매치하는 만큼, 이름을 붙여주고

4. 매치된 뒤부터 2번으로 반복


순차적으로 진행되는데다가, 정규식의 우선순위와 이름만 설정해주면, 이름이 붙은 토큰이 나온다.

게다가 코딩을 매번 해주지 않아도 정규식 리스트만 입력으로 넣어주면 쉽게 토큰을 구분해 낼 수 있다.


* URL : http\S+

* TEL : \d+-\d+-\d+

* TAG : <[^>]+?>

* NUM : \d+

* SEP : [\p{Z}\p{P}\p{S}]+

* TEXT : [^\p{Z}\p{P}\p{S}].+


위와 같은 순서로 해주면, URL 뽑고, 전화번호 뽑고, 태그 뽑고, 숫자 뽑고, 공백/구두문자/기호가 아닌 그냥 TEXT로 뽑는다.


Lexer가 이 Rule로 처리하게 되면,

"<b>2000원</b> http://mabook.com/2016 02-000-1234"

TAG : "<b>"
NUM : "2000"
TEXT : "원"
TAG : "</b>"
SEP : " "
URL : "http://mabook.com/2016"
SEP : " "
TEL : "02-000-1234"

가 된다.

아... 아름답다.


그래서 만들었다

https://github.com/sng2c/RuntimeLexer

https://github.com/sng2c/Parse-Token-Lite

나름 오토마타도 구현하려고 했는데 시원찮다.

쓰다가 고치고 하다 보면 나아지겠지.

작가의 이전글 반복되는 구간의 선별
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari