В данной статье мы рассмотрим решение проблем, которые могут возникнуть при создании парсера для языка Pascal с помощью YACC и FLEX. Мы будем использовать пример простого парсера, который обрабатывает объявления целых чисел, некоторые базовые выражения и операторы if-else.
Описание проблемы
При создании парсера для языка Pascal с помощью YACC и FLEX может возникнуть проблема, когда парсер не может найти ошибку, несмотря на то, что терминал выдает сообщение об ошибке "Error at line:0", что кажется невозможным. В данном случае мы будем использовать Flex для создания лексического анализатора, а YACC для создания синтаксического анализатора.
Контекст
Ниже приведены файлы лексического анализатора (lex.l) и синтаксического анализатора (grammar.y), а также пример входных данных, которые вызывают ошибку в строке 1.
lex.l:
%{
#include <stdio.h>
#include <string.h>
#include "y.tab.h"
extern int yylval;
int linenum=0;
%}
digit [0-9]
letter [A-Za-z]
%%
if return IF;
then return THEN;
else return ELSE;
for return FOR;
while return WHILE;
PROGRAM return PROGRAM_SYM;
BEGIN return BEGIN_SYM;
VAR return VAR_SYM;
END return END_SYM;
INTEGER return INTEGER_SYM;
{letter}({letter}|{digit})* return identifier;
[0-9]+ return NUMBER;
[<][=] return CON_LE;
[>][=] return CON_GE;
[=] return CON_EQ;
[:][=] return ASSIGNOP;
; return semiColon;
, return comma;
\n {linenum++;}
. return (int) yytext[0];
%%
PROGRAM myprogram;
VAR
i, i3, j: INTEGER;
BEGIN
i := 3;
j := 5;
i3 := i + j * 2;
i := j * 20;
if i > j then
i3 := i + 50 + (45 * i + (40 * j))
else
i3 := i + 50 + (45 * i + (40 * j)) + i + 50 + (45 * i + (30 * j))
END.
Подтвержденный ответ
Проблема заключается в том, что лексический анализатор возвращает пробелы и табуляции как токены, но грамматика не распознает их. Чтобы решить эту проблему, нужно добавить правило парсера:
[ \t\r] { }
Это позволяет добраться до строки 6 вместо строки 0 перед возникновением ошибки. Ошибка на строке 0 возникает потому, что между объявлениями не допускаются-semicolon.
Чтобы исправить это, нужно изменить грамматику, как показано ниже:
dec_block:
dec_block dec
|
dec
;
dec:
int_dec_list semiColon
;
Также нужно изменить правило logical_expression, чтобы оно могло дойти до терминала expression:
После внесения этих изменений парсер должен правильно обрабатывать входные данные без ошибок.
Альтернативный ответ
Для отладки грамматик YYDEBUG является вашим другом. Либо добавьте #define YYDEBUG 1 в %{ } %} в верхней части вашего файла .y, либо.compile с -DYYDEBUG, и добавьте yydebug = 1; в main перед вызовом yyparse, и вы получите поток информации о том, какие токены видит парсер и что он с ними делает.
Заключение
В данной статье мы рассмотрели решение проблем, которые могут возникнуть при создании парсера для языка Pascal с помощью YACC и FLEX. Мы использовали пример простого парсера и показали, как исправить ошибки, связанные с неправильным расположением точек с запятой и нераспознаванием пробелов и табуляций. Также мы предложили альтернативный подход к отладке грамматик с помощью YYDEBUG.
В данной статье рассматривается решение проблем, возникающих при создании парсера для языка Pascal с помощью YACC и FLEX, с использованием примера простого парсера, обрабатывающего объявления целых чисел, базовые выражения и операторы if-else.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.