Как предотвратить "синтаксическую ошибку" по умолчанию в Bison - PullRequest
0 голосов
/ 11 марта 2020

Как описано в шапке, я использую Bison и Flex для получения парсера, но мне нужно обработать ошибку и продолжить после того, как я ее найду. Таким образом, я использую:

Stmt:   Reference '=' Expr ';'                                { printf(" Reference = Expr ;\n");}
|       '{' Stmts '}'                                         { printf("{ Stmts }");}
|       WHILE '(' Bool ')' '{' Stmts '}'                      { printf(" WHILE ( Bool ) { Stmts } ");}
|       FOR NAME '=' Expr TO Expr BY Expr '{' Stmts '}'       { printf(" FOR NAME = Expr TO Expr BY Expr { Stmts } ");}
|       IF '(' Bool ')' THEN Stmt                             { printf(" IF ( Bool ) THEN Stmt ");}
|       IF '(' Bool ')' THEN Stmt ELSE Stmt                   { printf(" IF ( Bool ) THEN Stmt ELSE Stmt ");}
|       READ Reference ';'                                    { printf(" READ Reference ;");}
|       WRITE Expr ';'                                        { printf(" WRITE Expr ;");}
|       error ';'                                             { yyerror("Statement is not valid"); yyclearin; yyerrok;}
;

, однако, я всегда получаю сообщение об ошибке «Синтаксическая ошибка», и я не знаю, откуда она и как ее предотвратить, чтобы мой собственный «код ошибки» был выполнен , Я пытаюсь исправить ошибки здесь, чтобы мой анализатор продолжал анализировать ввод до EOF.

1 Ответ

2 голосов
/ 11 марта 2020

Люди часто путают назначение правил error в yacc / bison - они предназначены для ВОССТАНОВЛЕНИЯ ошибки, а не для ОБРАБОТКИ ошибки. Таким образом, правило ошибки не вызывается в ответ на ошибку - ошибка возникает, а затем используется правило ошибки для восстановления.

Если вы хотите устранить ошибку самостоятельно (поэтому избегайте вывода «синтаксической ошибки»). сообщение), вам нужно определить собственную yyerror функцию (то есть обработчик ошибок), которая делает что-то со строкой «синтаксическая ошибка», отличную от ее печати. Один из вариантов - ничего не делать, а затем напечатать сообщение в правиле восстановления после ошибок (например, там, где вы вызываете yyerror, вместо этого измените его на printf). Проблема заключается в том, что если восстановление после ошибки завершится неудачно, вы не получите никакого сообщения (вы получите сообщение об ошибке, возвращенное из yyparse, поэтому можете напечатать сообщение там).

...