Программа, сгенерированная lex (flex), не обрабатывает весь ввод - PullRequest
1 голос
/ 14 февраля 2010

У меня есть относительно простой файл lex / flex, и я запускаю его с отладочным флагом flex, чтобы убедиться, что он правильно разбит на токены.К сожалению, я всегда сталкиваюсь с одной из двух проблем - либо программа, сгенерированная flex, останавливается, просто беззвучно сдается после пары токенов, либо правило, которое я использую для распознавания символов и строк, не вызывается, и правило по умолчаниювместо этого вызывается.

Может кто-нибудь направить меня в правильном направлении?Я приложил свой гибкий файл и пример ввода / вывода.

Редактировать: я обнаружил, что сгенерированный лексер останавливается после определенного правила: "cdr".Это более подробно, но и гораздо более запутанно.Я опубликовал укороченный измененный файл lex.

/* lex file*/
%option noyywrap
%option nodefault

%{
       enum tokens{
                CDR,
                CHARACTER,
                SET
        };
%}

%%

"cdr"                                               { return CDR; }
"set"                                               { return SET; }

[ \t\r\n]                                           /*Nothing*/
[a-zA-Z0-9\\!@#$%^&*()\-_+=~`:;"'?<>,\.]      { return CHARACTER; }

%%

Пример ввода:

set c cdra + cdr b + () ;

Полный вывод при выполнении ввода через сгенерированный синтаксический анализатор:

--(end of buffer or a NUL)
--accepting rule at line 16 ("set")
--accepting rule at line 18 (" ")
--accepting rule at line 19 ("c")
--accepting rule at line 18 (" ")
--accepting rule at line 15 ("cdr")

Какие-нибудь мысли?Сгенерированная программа сдается после половины ввода!(для справки, я делаю ввод, перенаправляя содержимое файла в сгенерированную программу).

Ответы [ 2 ]

3 голосов
/ 14 февраля 2010

При создании автономного лексера (то есть, не с токенами, определенными в bison / yacc, вы обычно пишете перечисление в верхней части файла, определяющего ваши токены. Однако основной цикл программы lex, включая основной цикл, сгенерированный по умолчанию, выглядит примерно так:

while( token = yylex() ){
    ...

Это нормально, пока ваш лексер не совпадет с правилом, которое появляется первым в перечислении - в данном конкретном случае CDR. Поскольку перечисления по умолчанию начинаются с нуля, это приводит к завершению цикла while. Перенумерация вашего enum - решит проблему.

enum tokens{
            CDR = 1,
            CHARACTER,
            SET
    };

Короткая версия: при определении токенов вручную для лексера начинайте с 1, а не с 0.

0 голосов
/ 14 февраля 2010

это правило

[-+]?([0-9*\.?[0-9]+|[0-9]+\.)([Ee][-+]?[0-9]+)? 
          |

, похоже, отсутствует закрывающая скобка сразу после первых 0-9, я добавил | ниже, где я думаю, что это должно быть. Я не мог догадаться, как Flex отреагирует на это.

Правило, которое я обычно использую для имен символов: [a-zA-Z$_], это как строки без кавычек за исключением того, что я обычно допускаю числа внутри символов, если символ не начинается с цифры.

[a-zA-Z$_]([a-zA-Z$_]|[0-9])*

Символ - это просто короткий символ. Я не думаю, что ему нужно иметь свое собственное правило, но если это так, то вам нужно убедиться, что строковое правило требует как минимум 2 символа.

[a-zA-Z$_]([a-zA-Z$_]|[0-9])+
...