2015. 3. 18.

flex and bison - 문법에 관하여..

  이전의 flex and bison - 간단한 계산기 만들기 글에서 썼던 문법에 대해 추가 설명을 하겠다.

표현을 할 때 그냥 아래와 같이 쓰면 안될까?

exp: exp ADD exp
     | exp SUB exp
     | exp MUL exp
     | exp DIV exp
     | ABS exp
     | NUMBER
     ;

안된다.

  왜냐하면 선후행 관계가 없기 때문이다. 곱하기 나누기를 더하기 빼기보다 먼저해야하는데 위와 같은 표현에서는 알수가 없다.






알겠다.. 그럼 더하기 빼기만이라도 아래와 같이 쓰면 안될까?

exp: exp ADD exp
     | exp SUB exp
     | factor
     ;

안된다.

  왜냐하면 이렇게 '모호한' 표현을 해주면 parser에서 충돌이 일어나게 된다.
예를들어 1 - 2 + 3 이 있을 때 (1-2) +3 과 1 - (2+3) 은 전혀 다른 결과가 나오게 된다.
물론 1 + 2 + 3 과 같은 경우는 상관이 없다. 그러나 대부분의 경우 error 가 생긴다.


  보통 bison의 parsing 알고리즘은 token이 input에 대해 어떤 rule과 매칭 될지 예견할 수 있다.
그런데 어떤 문법은 모호하지 않지만 예견하기 위해서 하나 이상의 token이 필요할 때가 있다.
비록 이럴때 보통 token이 충분하도록 문법을 수정할 수 있기는 하지만.. 충돌을 일으킨다.

그리고 이렇게 선후행 관계를 각각 따로 떨어진 rule로 지루하게 만들어야하는가?
아니다! 다른 방법도 있다!

이러한 것들에 대해서는 나중에 배우게 될 것이다.



flex와 bison이 멋진 점은 문법 수정이 아주 쉽다는 것이다!

'괄호'와 '주석' 라는 것을 쓰기 위해 이전 글에 내용을 약간 추가해보자.






flex의 내용에 아래를 추가한다.

"(" { return OP; }
")" { return CP; }
"//".* /* ignore comments */






bison의 내용에 아래를 추가한다.

%token OP CP in the declaration section
...
%%
term: NUMBER
       | ABS term { $$ = $2 >= 0? $2 : - $2; }
       | OP exp CP { $$ = $2; } New rule
       ;


OPCP token을 새로 정의한다.  여기서 OP는 ' ( '를 의미, CP 는 ' ) '를 의미한다.

다시 build를 하게 되면 괄호와 주석까지 쓸 수 있는 계산기가 된다.





출처 :
flex_bison_O'Reilly

댓글 없음: