GNU tool chain 알아보기: flex와 bison
on
그 오랜 세월 유닉스 환경에서 살아오면서 수 많은 툴과 S/W를 빌드해오면서도 GNU tool chain에 대해서는 무감각하게 살아온 것 같다. 실제로 쓸 일도 없었긴 했지만 알아둬서 나쁠 일은 없다고 본다.
그 중에서 flex와 bison이라는 툴을 관찰하려 한다. flex는 뭔가 flexible할 것 같고, bison은 이름으로 봤을 땐 덩치 큰 들소 (버팔로?) 이런 게 떠오르기도 하고 예전 Street Fighter 끝판왕이 생각나기도 하고 (그만큼 엄청 아재다 내가) 하는데, 어쨌든 bison은 꽤 흔히 쓰이는 툴 중에 하나다.
정의는 매우 간단하다.
flex - the fast lexical analyser generator
bison - GNU Project parser generator (yacc replacement)
쉽게 말해서 flex와 bison은 lex와 yacc의 gnu버전 툴이라고 생각하면 된다. 유닉스에 있었던 tool이 GNU에서 만들어지면서 이름이 달라진 것들은 다들 알다시피 매우 많다. awk가 gawk이듯 말이다.
이 툴은 컴파일러를 만들기 위한 코드를 만들어준다. (무슨 말이지?) 다시 말해서 내가 컴파일러의 기능을 하는 코드를 만들고 싶다고 할 때 컴파일 하려는 언어 혹은 스크립트의 규칙을 알려주면 flex와 bison이 이것들을 parsing할 수 있는 c code를 만들어낸다는 말이다.
flex는 lex에서 왔고 lex는 lexicon에서 온 것이라는 것을 쉽게 짐작할 수 있을텐데, 말 그대로 어휘 (vocabulary/instruction)를 분석하는 c code를 만들어낸다. yacc/bison은 일종의 구분문석을 위한 parser의 c code를 만들어낸다.
여기까지도 설명이 모호한데, 예를 몇 가지 들어보면 이해가 된다.
flex로 작업하는 것들은 이를테면 어떤 문자열이 문자열로 취급해야 하는지 정수로 취급해야 하는지 아니면 부동소수인 실수로 처리해야 하는지를 구분하는 파싱 작업같은 것이다. 즉, 내용물 그 자체를 분석해서 어떤 타입이 되어야 하는지 또는 어떤 명령어를 의미하는지를 파싱하는 것이다.
yacc/bison으로 하는 일은 어떠한 형식을 가진 구문이냐, 이를테면 어떤 문장을 받아와서 그것을 원하는 형식대로 바꾸거나 파싱하려고 할 때 사용하는 것이다. 아직도 이해가 쉽지 않을 수 있지만, 다시 정리하면
-
flex(lex)는 단어 수준에서 이게 어떤 단어이냐를 구분하는 규칙을 작성해 주면 그 규칙에 맞춰 C code를 생성하는 일을 한다.
-
bison(yacc)는 문장 수준에서 어떠한 형식으로 되어있느냐를 파싱하는 C code를 생성하는 일을 한다.
따라서, 어떤 문장을 파싱할 때에는 이 두 가지를 함께 사용해야 하는 것이다. 문장 자체의 구조가 어떠한 구조이냐를 보는 것이 yacc(bison)으로 생성해내는 code이고 문장을 구성하는 각각의 요소 (단어)가 무엇을 뜻하는지 알아내는 code를 작성하는 것이 flex(lex)로 기억하면 된다.
왜 이러한 툴을 이용하느냐 할 수 있는데, 의외로 사용 분야가 매우 넓다. 얼마되지 않는 문장이라든가 단어를 파싱해야하는 경우에는 if then으로 혹은 switch로 해결할 수 있는데, 만약 문장과 단어의 유형이 많아지게 되면 그것을 일일히 C coding을 하는 것보단 규칙을 알려주고 code를 생성하게 하는 편이 유리하다. 더구나 이 규칙과 유형이 계속해서 늘어나게 되는 경우라고 하면 이러한 방법이 절대적으로 유리하다.
구체적인 예는 많은 site들에서 찾아볼 수 있으니 구글링을 하든 해보면 된다.