, поэтому я пишу a = 7 (без ';') в строке, это просто говорит синтаксическая ошибка Ошибка в строке: 7.так где же мое сообщение об ошибке _?
Ваше действие error
говорит Yacc сбросить токены, пока он не найдет ';'маркер.Пока это не произойдет, оно не может уменьшиться по этому правилу.
Кроме того, вы должны выполнить yyerrok;
где-то в теле правила, чтобы сообщить парсеру, что восстановление выполнено.При желании вы также можете использовать yyclearin;
, чтобы также выбросить токен, вызвавший ошибку.Делать это сложно, потому что вы предполагаете, что токен неуместен.На самом деле это может быть правильный токен, но что-то еще, прежде чем его не будет!Например, вы видите точку с запятой, потому что закрывающая скобка была опущена и т. Д.
Действия по ошибке не будут заменять поведение вызова yyerror
.Когда возникает синтаксическая ошибка, синтаксический анализатор вызовет yyerror
с сообщением (обычно «синтаксическая ошибка»), а затем рассматриваются ошибки производства.Создание ошибок не является чем-то вроде «пользовательских переопределений синтаксических ошибок».(Похоже, вы ожидаете, что «синтаксическая ошибка» будет заменена вашим собственным общим сообщением об ошибке «Вы допустили ошибку».)
Если вы создаете ошибку, если вы можете догадаться о ее природе,Вы можете распечатать дополнительную диагностику, которая более полезна.
Одна полезная вещь - это переменная yychar
, которая сообщает вам жетон предпросмотра.Вы можете проверить это в правиле устранения ошибок и попытаться угадать, что пошло не так, основываясь на его значении.Вы можете проверить это не только для своих собственных типов токенов, но и для значения YYEOF
, которое указывает, что синтаксическая ошибка происходит из-за достижения не какого-то плохого токена, а конца ввода.
Я написал парсер вкоторый в некоторых случаях с ошибками я просто взял токен из yychar
, преобразовал его в описательное имя и распечатал сообщение «неожиданно в».Это лучше, чем ничего;он сообщает пользователю, на каком токене синтаксис отличается от ожидаемого.
Кроме того, синтаксические анализаторы yacc могут производить диагностику даже при правильном разборе!(Очевидно; например, как еще вы реализовали бы предупреждения для языка.) В основном вам нужна некоторая центральная функция сообщения об ошибках, которую вы можете вызывать самостоятельно и которая также будет вызываться yyerror
.Эта функция должна установить флаг, указывающий, произошли ли фатальные ошибки (или вести подсчет количества ошибок, предупреждений и т. Д.).Например, вы можете выбросить дерево синтаксического анализа и сохранить программу с состоянием сбоя завершения, если были фатальные ошибки, даже если синтаксический анализатор восстановился после любых синтаксических ошибок.