작은 파서를 쓰려고합니다. 불행히도 "교대 감소 충돌"이 발생합니다. 문법은 저의 강점이 아니며,이 문구를 약간만 해 주면됩니다. 오류를 생성하는 축소 된 문법은 다음과 같습니다.Shift/내 문법의 IF-ELSE 충돌을 줄입니다.
stmts_opt -> stmts
;
stmts -> stmt
| stmts stmt
| stmsts
;
stmt -> id
| ITERATE content_stmt
| IF test then content_stmt ELSE content_stmt
| IF test then content_stmt
;
content_stmt: BEGIN stmt_opt END
| stmt
;
수정 된 문법을 제공하는 솔루션은 높이 평가할 수 있습니다.
편집 : 내 문법 RICI의 대답 @ 양복지하지만 문제가 계속 수정
.
BEGINNING-OF-PROGRAM
BEGINNING-OF-EXECUTION
IF not-next-to-a-beeper THEN
move;
IF not-facing-north THEN
turnleft;
ELSE <--- ERROR
turnleft;
IF not-facing-east THEN
IF not-facing-west THEN
turnleft;
turnoff
END-OF-EXECUTION
END-OF-PROGRAM
내가 처음 ELSE
에 오류가 점점 오전 : 여기
prog: BEGIN_PROG def_sprogram BEGIN_EXEC stmts_opt END_EXEC END_PROG
{() }
;
def_sprogram: /* empty */ {() }
| define_new def_sprogram {() }
;
define_new: DEFINE_NEW_INSTRUCTION ID AS content_stmt SEMI { }
;
stmts_opt: /* empty */ {() }
| stmts {() }
;
stmts: stmt {() }
| stmts SEMI stmt {() }
| stmts SEMI {() }
;
content_stmt: BEGIN stmts_opt END {() }
| stmt {() }
;
stmt: open_stmt {() }
| closed_stmt {() }
;
open_stmt: ITERATE INT TIMES open_stmt {() }
| WHILE test DO open_stmt {() }
| IF test THEN closed_stmt ELSE open_stmt {() }
| IF test THEN stmt {() }
;
closed_stmt: simple_stmt {() }
| ITERATE INT TIMES closed_stmt {() }
| WHILE test DO closed_stmt {() }
| IF test THEN closed_stmt ELSE closed_stmt {() }
;
내가가 테스트하고있는 예이다 : 여기 내 실제 문법 작품이다. 또한 @rici가 제안한 것처럼 간단한 우선 순위를 선언하려고 시도했습니다.
%nonassoc THEN
%nonassoc ELSE
그러나이 오류는 해결되지 않았습니다.
yacc/bison이 올바른 해결 방법을 선택하기 때문에 shift-reduce 충돌 만이 else 애매함으로 인해 생기는 경우 문법이 올바르게 작동합니다. 경고를 없애려면 여기에서 "다른 것을 매달아"검색하십시오. – rici
camlyacc를 사용하고 있으며 경고가 아닌 오류가 표시됩니다. 여기에서 검색하려했지만 문법이 약간 다릅니다 (BEGIN 및 END). 제안 된 해결책이 나에게 적합하지 않았습니다. –
오류를 만드는 것은 짜증나게합니다. 그렇게해서는 안됩니다. 그러나 시작과 끝 토큰은 아무런 효과가 없어야합니다. 당신은 무엇을하지 않았습니까? – rici