2012-02-01 2 views
3

GLR 방법으로 shift \ reduce 충돌을 해결하려면 어떻게해야합니까?
구문 분석기가 오른쪽 시프트 연산자와 자체에 대한 템플릿 인수의 두 개의 닫는 꺾쇠 괄호 사이의 충돌을 해결한다고 가정합니다. 나는 렉서가 두 개의 연속적인 ">"기호를 하나의 ">>"토큰으로 병합하지 않고 별도의 토큰으로 전달하도록 만듭니다. 그런 다음이 규칙을 문법에 적용합니다.들소, C + + GLR 구문 분석 : 어떻게 교대 충돌을 강제로?

operator_name: 
    "operator" ">" 
    | "operator" ">" ">" 
; 

나는 이것을 교대 \ 축소 충돌로 만들고 싶습니다. 왼쪽 연관성이있는 ">"에 대한 토큰 선언이있는 경우 충돌이 발생하지 않습니다. 따라서 토큰 우선 순위 \ 조합 성 선언을 제거해야하지만, 충돌하는 각 규칙에 대한 문맥 우선 순위를 지정하여 수동으로 해결하고 싶지 않은 다른 많은 충돌이 발생합니다. 그래서, 토큰을 선언하는 동안 shift \ reduce 충돌을 강제하는 방법이 있습니까?

+0

">"은 시프트 연산자 또는 템플릿 닫기 태그 토큰과는 별도의 토큰으로 간주됩니다."-", 음수 부호 또는 빼기 연산자에 대해서도 마찬가지입니다. – umlcat

+0

예, C#과 Java에서이 기술을 사용했음을 기억합니다.하지만이 파서는 ANTLR 기반이었으며 일부 해킹이 없어도 더 간단했습니다. – slavasav

답변

2

나는 operator_name에 대한 규칙에 context-dependent precedence을 사용하면 효과가 있다고 생각합니다.

업데이트 된 표준에 지정된 C++ 문법은 >> 토큰을 두 개의 열린 템플릿 선언을 닫는 것으로 받아 들일 수 있도록 문법을 실제로 수정합니다. 표준 동작을 얻으려면 다음을 따르는 것이 좋습니다. 예를 들어 "x >> y"는 "x >> y"로 구문 분석되지 않도록주의해야하며 "foo < bar < 2 >> 1 >>"은 유효하지 않으며 "foo < bar < (2 >> 1) >> "이 유효합니다.

+0

Bison은 상황에 따라 우선 순위를 지정할 때 충돌이 해결되는 것으로 간주합니다. 즉, 교대 \ 충돌을 줄이기 위해 첫 번째 규칙의 우선 순위를 두 번째 규칙의 우선 순위와 동일하게 지정하겠다고 명시 적으로 지정하면 bison은 충돌을 해결할 대신 glr을 사용하여 해결하도록 선택합니다. 실행 시간. – slavasav

0

Yacc (Bison과 유사)에서 비슷한 시나리오로 작업했습니다.

표준 문법은 "구문에 의해 지시되는 구문 분석"이라고도합니다.

이 경우는 때로는 "의미에 의한 구문 분석"과 같은 것으로 불립니다.

예 :

... 
// shift operator example 
if ((x >> 2) == 0) 
... 
// consecutive template closing tag example 
List<String, List<String>> MyList = 
... 

우리의 마음은 컴파일러처럼 작동 기억 할 수 있습니다. 인간의 마음은 이것을 컴파일 할 수 있지만, 이전의 문법은 그렇게 할 수 없습니다. 응. 인간의 마음이 어떻게이 코드를 컴파일하는지 볼 수 있습니다.

이미 알고 계시 겠지만 연속되는 ">"및 ">"토큰 앞에있는 "x"는 표현식이나 lvalue를 나타냅니다. 마음은 "expireion 후에 두 개의 연속적인 greater-than 심볼이 단일 시프트 연산자 토큰이되어야한다고 생각합니다."

"문자열"토큰의 경우 : 형식 식별자 뒤에 두 개의 연속 된 큰 기호가 두 개의 연속 된 닫는 태그 토큰이되어야합니다.

이 경우는 일반적인 연산자 우선 순위, shift 또는 reduce 또는 문법만으로는 처리 할 수 ​​없지만 파서 자체에서 제공하는 일부 기능을 사용하여 ("해킹") 사용한다고 생각합니다.

예제 문법 규칙에 오류가 표시되지 않습니다. "연산자"기호는 사용자가 언급 한 두 가지 경우를 혼동하지 않도록합니다. 시프트 연산자가 사용 된 문법과 연속 된 템플릿 닫기 태그가 사용되는 부분에주의해야합니다.

operator_expr_example: 
    lvalue "<<" lvalue | 
    lvalue ">>" lvalue | 
    lvalue "&&" lvalue | 
; 

template_params: 
    identifier | 
    template_declaration_example | 
    array_declaration | 
    other_type_declaration 
; 

template_declaration_example: 
    identifier "<" template_params ">" 
; 

건배.

+0

좋아, 나는 사건을 명확히하기 위해 연산자 예제를 사용했다. "우리의 생각은 컴파일러와 같이 작동한다"고 생각하면 무한한 선견자를 사용하여 구문 분석에 영향을 줄 수있는 방법이 있습니다. 그러나 glr을 사용하는 경우, bison은 파싱 스택을 분할하여 충돌을 해결할 때마다 모든 의미 론적 작업을 연기하고 결정적 상태로 되돌릴 때 이러한 작업을 실행하므로 그 시점에 구문 분석에 영향을 미치기에는 너무 늦습니다. – slavasav