Как я могу указать синтаксическому анализатору не продолжать обработку незавершенных комментариев?

Я работаю над улучшением отчетов об ошибках в моем назначении компилятора. Я обрабатываю незавершенные комментарии во Flex, используя следующий код:

<INITIAL>"/*"       {BEGIN(COMMENT);}
<COMMENT>"*/"       {BEGIN(INITIAL);}
<COMMENT>([^*]|\n)+   {}
<COMMENT><<EOF>>    {yyerror("UNTERMINATED COMMENT"); BEGIN(INITIAL);}

Проблема в том, что синтаксический анализатор также печатает сообщение об ошибке:

 $ ./comp tests/comments.cf 
 ERROR: UNTERMINATED COMMENT: 27
 ERROR: syntax error: 27

Как я могу дать указание парсеру не продолжать свою работу? Добавление exit после BEGIN(INITIAL) дает мне то, что я хочу, но, похоже, это не способ справиться с этим.


person Guilherme Salazar    schedule 09.05.2015    source источник
comment
Кстати, ваши <COMMENT> правила неверны; ни одно правило не соответствует * внутри комментария, так что это попадет в правило по умолчанию. Если ваше правило по умолчанию . { return yytext[0]; }, это будет иметь особенно катастрофические последствия; если правилом по умолчанию является сгенерированное flex правило по умолчанию (ECHO), это будет просто странно. Кроме того, набор символов [^*] включает \n, поэтому |\n является избыточным.   -  person rici    schedule 10.05.2015


Ответы (1)


Вы, безусловно, должны вернуть 0 (или что-то в этом роде) из действия <<EOF>>, потому что, если вы этого не сделаете, лексер попытается продолжить сканирование (что является неопределенным поведением; сканер не должен продолжать считывать ввод после сигнала EOF, если только он предусмотрел новый входной буфер.)

Вполне вероятно, что незавершенный комментарий приведет к синтаксической ошибке, поскольку конец программы, скорее всего, проглочен комментарием. Если вы не хотите, чтобы сообщалось об этой ошибке, вы можете просто установить флаг, который yyerror проверяет перед печатью сообщения об ошибке. В этом простом случае нет необходимости сбрасывать этот флаг, поскольку ошибка незавершенного комментария может возникнуть только в конце ввода, и в этот момент восстановление после ошибки невозможно.

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

Если вам нужно решение с более чистым интерфейсом между сканером и синтаксическим анализатором, вы можете рассмотреть следующую возможность:

  1. В вашем лексере при обнаружении незавершенного комментария верните неиспользуемый токен, скажем, UNTERMINATED_COMMENT.

  2. Когда синтаксический анализатор получает токен UNTERMINATED_COMMENT, он немедленно сигнализирует о синтаксической ошибке (или почти сразу. При некоторых обстоятельствах он может выполнять некоторые сокращения, прежде чем даже проверит, что такое упреждающий токен). Когда вызывается yyerror, значение yychar global будет упреждающим токеном, поэтому он будет UNTERMINATED_COMMENT; yyerror может использовать этот факт для создания более точного сообщения об ошибке, а не общей "синтаксической ошибки".

  3. В этот момент важно немедленно прекратить синтаксический анализ, поскольку повторный вызов сканера приведет к неопределенному поведению. Это можно сделать, установив yychar в YYEOF в функции yyerror. (Альтернативой может быть включение производства ошибок с UNTERMINATED_COMMENT в правой части, действие которого YYABORT.)

person rici    schedule 10.05.2015