2017-02-10 13 views
1

나는 다음과 같은 구조를 가지고 yacc에 문법의 일부 (또는 오히려 jison하지만, 이주 동일한 공통 기본)와 같은 :Yacc에서 강제로 시프트하는 방법?

Type 
    : IDENT 
    | Type "[" "]" 
    | Type "*" 
    | "func" "(" Types ")" "=>" Type 
    ; 

Types 
    : /* No arguments */ 
    | Type /* Single argument */ 
    | Types "," Type /* Multiple arguments */ 
    ; 

이것은 물론 간단한 예입니다, 그러나 일반 아이디어를 줄 것이다 문제가 실제로 나타나는지 보여줍니다. 나는 Foo[], Foo*, Foo*[](Foo)[], (Foo)*, ((Foo)*)[]에 각각 파싱하고 싶다.

그러나, Yacc와는 정당 그것은 다음과 같은 구조를 발견 할 때 무엇을 해야할지하지 않습니다 불평 :

func (A, B) => C[] 

그것은 func (A, B) => (C[]) 또는 (func (A, B) => C)[] 하나에 구문 분석 할 수 있습니다. 물론 (첫 번째 경우는 (Type)이므로) 첫 번째로 좋아할 것입니다. 이 상황에 부딪혔을 때 내가 바꾸고 싶은 yacc (또는 jison)에게 말할 수있는 방법이 있습니까?

답변

1

%prec 선언과 의사 터미널을 사용하거나 최후의 터미널 인 =>의 기본값 인 기본값을 사용하여 마지막으로 Type 프로덕션을 제공하십시오. 그런 다음 [ 토큰의 우선 순위가 더 높은지 확인하십시오. (다른 shift-reduce 충돌을 해결하기 위해 *의 우선 순위를 =>보다 높게 만들어야합니다.)

다른 해결책이 있지만 가장 간단한 방법입니다.

사실, bison/yacc/jison/etc. 항상 시프트 감소 충돌에서 시프트를 선호하므로 시프트를하려면 아무 것도 할 필요가 없습니다. 우선 순위 규칙에 따라 경고가 표시되지 않지만,이를 수행하려면 expect 선언을 사용할 수도 있습니다.

+0

그래,'% left'와'% prec'을 치며 실제로 문제를 해결했습니다. 감사! –

+0

@ B.Alfred '*'와는 또 다른 모호함이 있습니다. 또는 적어도 Zaach의 온라인 jison 도구로 얻은 것입니다. 나는 그 대답을 편집했다. – rici