왜 '('( ')'( ')')에 대한 교대 감소/충돌이있는 이유는 무엇입니까?
-
11-09-2019 - |
문제
나는 구문이 있습니다
%(var)
그리고
%var
그리고 (var)
내 규칙은 같은 것입니다
optExpr:
| '%''('CommaLoop')'
| '%' CommaLoop
CommaLoop:
val | CommaLoop',' val
Expr:
MoreRules
| '(' val ')'
문제는) %(CommaLoop)
또는 % (val)
그러나 그것은 (도대체가 무엇입니까? (
? 오류를 어떻게 해결해야합니까? 나는 생각한다 %(
토큰은 좋은 솔루션이지만 이유를 확신하고 싶습니다. $(
이 작업을 수행하기 전에 오류가 아닙니다.
해결책
이것은 LR Parsing이 작동하는 방식 때문입니다. LR 파싱은 효과적으로 상향식으로, 문법 규칙의 RHS에 따라 토큰을 함께 그룹화하고 LHS로 대체합니다. 파서가 '이동'하면 스택에 토큰을 넣지 만 실제로는 규칙과 일치하지 않습니다. 대신, 현재 상태를 통해 부분적으로 일치하는 규칙을 추적합니다. 규칙의 끝에 해당하는 상태에 도달하면 스택에서 RHS의 기호를 팝업하고 LHS를 나타내는 단일 기호를 뒤로 밀 수 있습니다. 따라서 갈등이있는 경우, 파서가 어떤 규칙의 끝까지 도달 할 때까지 나타나지 않으며 감소 할 것인지 (또는 감소 할 것인지)를 결정할 수 없습니다.
당신의 예에서, 본 후 % ( 발, 그것이 스택에있을 것입니다 (상단은 오른쪽에 있습니다). 전망대가있을 때 ), 그것은 규칙을 통해 발을 터야하고 줄여야하는지 결정할 수 없습니다. Commaloop : Val, 또는 이동 해야하는 경우 ) 그러면 3 가지를 튀기고 규칙에 따라 줄일 수 있습니다. expr : '('val ')'
여기에 다음과 같은 추가 규칙이 있다고 가정합니다. commaloop : expr, 그렇지 않으면 문법은 실제로 아무것도 일치하지 않으며 Bison/YACC는 사용하지 않은 비 터미널에 대해 불평 할 것입니다.
다른 팁
지금, 당신의 설명과 문법은 일치하지 않는 것 같습니다. 당신의 설명에서, 당신은 세 가지 문구를 모두 'var'인 것으로 표시하지만, 문법은 '%'로 시작하는 문법이 쉼표로 구분 된 목록을 허용하는 것으로 표시되며, 하나는 단일 'val'만 허용합니다.
현재, 나는 세 가지 모두 쉼표로 구분 된 목록을 허용해야한다고 가정 할 것입니다. 이 경우, 나는 다음과 같은 문법을 더 고려합니다.
optExpr: '%' aList
aList: CommaLoop
| parenList
parenList: '(' CommaLoop ')'
CommaLoop:
| val
| CommaLoop ',' val
Expr: MoreRules
| parenList
나는 optexpr과 expr을 변경 했으므로 빈 순서와 일치 할 수는 없습니다. 제 생각에는 아마도 당신이 시작하려고하지 않았을 것입니다. 나는 이것을 BYACC를 통해 실행할만큼 충분히 살았습니다. 경고 나 오류가 발생하지 않습니다.