Как мога да инструктирам анализатора да не продължава да обработва незавършени коментари?

Работя върху подобряването на отчитането на грешки в задачата ми за компилатор. Обработвам незавършени коментари във 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 в rhs, чието действие е YYABORT.)

person rici    schedule 10.05.2015