про восстановление ошибок от bison2.4.1

Я хочу справиться с исправлением ошибок из bison2.4.1.

Я сослался на книгу Орейли (lex & yacc) и на некоторые веб-сайты, чтобы поместить токен ошибки в свое правило,

но я думаю, что это не работает. это не помогает мне справляться с восстановлением после ошибок!

мой код выглядит следующим образом:

PDL:
    DataDesc ComputationDesc    {Build_front_proc($1,$2);}
    ;
DataDesc:
    PartyDecl AccLvDesc     {$$ = echo_dataDesc($1, $2);}
    ;
// Party Description
PartyDecl:
    PARTY ':' ID ',' ID ENDL    {if($3->is_func || $5->is_func)
                        yyerror("it is a reserved word!\n");
                    $$ = echo_partyDecl($3->name,$5->name);}
    |error ENDL         {printf("There is a error");}
    ;

Я дал слова "Party: id_a ;" (это должно быть два идентификатора имени после «Вечеринки».)

и он пошел прямо к yyerror() и показал синтаксическую ошибку...

Я понятия не имею, почему он не обрабатывает эту ошибку.


person user997948    schedule 14.04.2012    source источник
comment
возможный дубликат обработки ошибок в YACC   -  person Kaz    schedule 16.04.2012


Ответы (1)


Правила ошибок в yacc/bison не ПРЕДОТВРАЩАЮТ ошибок — они ВОССТАНАВЛИВАЮТ после ошибок. Таким образом, в этом случае вы получаете сообщение об ошибке (и оно вызывает yyerror("syntax error")), а ЗАТЕМ ищете правила обработки ошибок для восстановления. Таким образом, в этом случае он будет находиться в состоянии поиска ',' для переключения после переключения PARTY, ':' и ID. В этом состоянии ';' невозможно проанализировать, поэтому будет выдана синтаксическая ошибка. После ошибки он начнет выталкивать состояния, пока не найдет одно с ошибкой - в этом случае 3 состояния, чтобы перейти к тому, которое соответствует началу PartyDecl. В этом состоянии он сместит ошибку, поместив ее в состояние, ожидающее ENDL. Затем он будет отбрасывать входные символы (; и все, что после него), пока не найдет ENDL, который он сдвинет, переведя в состояние, в котором он может сократить правило PartyDecl: error ENDL, вызвав printf("There is a error");.

Если он никогда не найдет ENDL, он выйдет после того, как дойдет до EOF, так и не восстановившись после ошибки. Кроме того, он останется в режиме исправления ошибок еще на 2 смены после ENDL — если до этого появится еще одна ошибка, он не вызовет yerror и вместо этого сразу перейдет к восстановлению после ошибки.

person Chris Dodd    schedule 15.04.2012