. 일반 분석기

여기까지 가장 많이 사용되는 문법에 대해 세 개의 분석기를 작성해 봤다. 이 장은 분석기 자체가 목적이 아니고 분석기를 만드는 방법이 목적이므로 C/C++ 분석기를 제외하고는 그다지 정확하지 않다. PHP 함수의 경우 하도 많아서 다 입력하지도 못했으며 ASP는 구조를 다 알지 못해 더 이상 작성할 수가 없었다. 자바나 Perl, C# 분석기도 만들고 싶지만 이런 언어들은 제작자 스스로가 잘 모르기 때문에 함부로 작성했다가는 엉터리로 만들 것 같아 그만 두기로 했다. 모르면 솔직히 모른다고 해야지 괜히 아는 척 해 봐야 아무에게도 득이 되지 않는다.

정확한 분석기를 만드는 것은 코딩의 문제가 아니라 설계의 문제인 것 같다. 분석하고자 하는 문법의 특징을 제대로 간파해야만 효율적인 분석 루틴을 만들 수 있으며 그래서 분석기 작업만큼은 혼자서 할 일이 아니다. 한 사람이 모든 것을 다 잘할 수는 없는 노릇이고 각 분야의 전문가에게 도움을 받아야 한다. 사실 나는 자바나 XML은 겨우 기본 정도만 구경해 봤고 C#은 아직 공부해본 바가 없으며 Perl이나 Tex 기타 스크립트류는 그런 것도 있다는 것만 귀동냥을 한 정도다. 포트란이나 코볼은 알기는 하지만 실용성이 거의 없다. 이런 상황에서 무슨 분석기를 만들 수 있겠는가?

다음 버전에서는 여러 사람의 도움을 받아 베이직, 파스칼, 어셈블리를 포함해서 시간이 허락하는 대로 더 많은 분석기를 추가할 것이다. 현재의 방식대로 분석기별로 하나씩 클래스를 작성하는 것은 문법의 특이한 부분까지 다 표현할 수 있다는 점과 다른 분석기에 영향을 미치지 않고 개별 분석기를 수정할 수 있다는 점에서 일단 우수하다. 하지만 지원 문법이 늘어날 때마다 프로그램이 비대해진다는 것이 문제가 되고 대량의 분석기를 빠른 시간에 작성하기 어렵다는 것이 큰 단점이다.

구문 분석의 완성 형태는 아마도 모든 문법을 분석해 낼 수 있는 일반 분석기일 것이다. 일반(General) 분석기는 특정한 문법만 전문적으로 분석하는 루틴이 아니라 문법의 구조를 설명하는 문법 파일을 던져 주면 이 파일의 지시대로 문서를 분석해 내는 코드의 집합이다. 문법 파일에는 문법에 포함되는 스타일의 종류, 각 스타일의 색상값, 키워드의 종류, 분석 절차, 적용 방법, 특이 사항 등에 대해 상세하고도 분명하게 기술되어야 한다. C/C++ 문법에 대한 문법 파일은 아마도 다음과 같은 모양을 가질 것이다.

 

 

[C/C++]

설명=C/C++ 언어에 대한 명세

구분자=!@#$%^&*() 등등

키워드=auto break bool case char const continue default 어쩌고 저쩌고

전처리기=#define #include #if #else 궁시렁 궁시렁

대소문자=구분해야지!

한 줄 주석=//

블록 주석 시작=/*

블록 주석 끝=*/

확장열 이스케이프=\

행 계속 문자=\

16진수 표기법=0x,0X

8진수 표기법=0으로 시작하면 8진수

2진수 표기법=그런 거 없음

문서 포맷=니 맘대로

기타=여러 줄에 걸치는 문자열 상수 허용 안함. 중첩 주석 안됨.

...........

 

일반 분석기는 이런 문법 파일의 지시로부터 문서를 어떤 순서대로 어떻게 분석할 지를 알아내고 그대로 분석할 수 있는 분석기이다. 일반 분석기가 완성되면 코딩은 더 할 필요없이 문법 파일만 계속 추가하면 분석기를 간단하게 추가할 수 있고 문법 파일을 프로그램 외부에 둔다면 프로그램의 용량에도 영향을 주지 않는다. 더구나 문법 파일을 사용자가 직접 편집할 수 있으므로 사용자정의 문법을 만드는 것도 가능해진다.

하지만... 일반 분석기를 만든다는 것은 정말이지 쉬운 일이 아니다. 각각의 문법들은 상상 이상으로 독특하기 때문에 모든 문법을 다 표현할 수 있는 알고리즘을 찾기란 결코 쉽지 않다. 대소문자 구분, 확장열, 행계속 여부, 상이한 구성 요소들, 주석 지원 방식 등이 모든 문법에서 다르며 다른 문법에는 없는 이상한 제약들도 많다. 같은 문법이라도 버전과 컴파일러(또는 브라우저)에 따라 약간씩 달라지기도 한다.

예를 들어 포트란은 문자열이 일정 길이를 넘으면 변수명으로 인정하지 않으며 주석은 반드시 첫 컬럼에만 올 수 있다. 코볼은 포트란보다 더 형식이 엄격해서 문장 구조에 따라 시작 컬럼을 반드시 지켜야 하며 80컬럼을 넘을 때는 별도의 표시를 해야 한다. 구형 C 컴파일러만 해도 #include는 첫 컬럼에 올 때만 인정되며 베이직은 프리포맷을 지원하지 않는다. HTML은 주석문안에 의미 있는 코드가 들어갈 수도 있으며 어떤 C 컴파일러는 블록 주석의 중첩을 허용하기도 한다.

현재 시장에 나와 있는 편집기들은 대부분 일반 분석기를 지원한다. 하지만 이런 것들도 조금만 살펴 보면 완벽하게 동작하지 않는다는 것을 쉽게 확인할 수 있다. 대부분의 문법에 대해 지원 가능한 부분만 공통적으로 뽑아내서 일반화된 규칙을 만들었기 때문에 특이한 문법에 대해서는 어느 정도 포기를 할 수밖에 없다. C 언어는 \를 행 계속 문자로 정의하지만 이런 것들은 제대로 분석이 안된다. 상용 편집기들이 일반 분석기를 잘못 만들었다는 것이 아니라 그만큼 완벽한 일반화가 어렵다는 얘기다.

이런 어려움과 불완전함에도 불구하고 일반 분석기는 최종 목표로 삼을 만큼 충분히 매력적이다. ApiEdit도 최종 목표는 하나의 객체와 복수 개의 데이터로 모든 문서를 분석 가능하게 만드는 것이다. 하지만 현재 단계에서는 일반 분석기를 시도할 수 없다. 왜냐하면 일반 분석기를 제대로 만들려면 고도로 일반화된 룰이 필요한데 고작 분석기 세 개를 만들어 보고 이 상태에서 룰을 추출할 수는 없기 때문이다.

CParse 클래스는 그나마 세 분석기의 공통된 룰에 대해 공유 가능한 함수를 제공하는데 이 함수 집합을 만드는 것도 결코 쉽지 않았다. 그런데 차후에 10, 20개로 지원 문법이 늘어나면 그때는 지금과는 다른 고도의 치밀한 일반화 전략이 필요해질 것이다. 일단 염두에 두고 분석기를 추가해 나가되 성급하게 일반 룰을 찾지는 않을 것이다. 일반 분석기가 포기해야 할 부분이 너무 많다면 차라리 지금 이 구조를 유지하는 것이 더 나을지도 모르겠다.