Как обрабатывать любой текстовый файл Unix/DOS/Mac в flex-сканере
Я хочу, чтобы мой гибкий сканер обрабатывал текстовые файлы с символами новой строки, закодированными с использованием lf (Unix), cr (Mac) или cr lf (DOS). Я не забочусь о поддержании точно точного количества строк.
Не делая ничего особенного в файле.l относительно конца строк и компиляции под Ubuntu, мой сканер работает как с файлами Unix, так и с файлами DOS. Тем не менее, файлы Mac делают его неудачным. Добавление правила для удаления любого несоответствующего символа (т. Е. Просто строки с символом .
) не помогает Я считаю, что lex ищет \n для завершения строк и игнорирует \r в файлах DOS, но не работает в файлах Mac, потому что \n не появляется, поэтому он никогда не думает, что читает строку.
Должен быть простой способ справиться с этим! Кто-нибудь знает как?
1 ответ
(F) Лекс делает именно то, что вы просите. Если вам нужно распознать окончания строки и принять все три формы, вам нужно будет указать это, используя такой шаблон, как (\r\n?|\n)
,
(F) lex не является линейно-ориентированным, за исключением трех функций. Эти особенности предполагают, что строки заканчиваются \n
, что верно как для текстовых файлов DOS и Unix. Если вы хотите работать с файлами Mac в старом стиле, вам нужно реализовать эти функции самостоятельно.
Шаблоны начала строки (шаблоны, начинающиеся с
^
). Вы можете использовать условия запуска (см. Ниже).Шаблоны конца строки (шаблоны, заканчивающиеся на
$
).$
может быть просто заменен завершающим контекстным оператором:(some_pattern)$
⇒
(some_pattern)/(\r\n?|\n)
Автоматический подсчет строк с использованием
%option yylineno
, (Только Flex) Вы не сможете рассчитывать автоматически; вам нужно сделать это вручную:(\r\n?|\n) { ++yylineno; }
Конечно, это действие должно быть добавлено к каждому правилу, которое соответствует новой строке, и если какое-то правило может соответствовать нескольким новым строкам, вам необходимо повторно отсканировать совпадение для подсчета новых строк. Это боль, но обычно можно заменить такой длинный шаблон серией совпадений в начальном состоянии.
(F) lex позволяет сделать набор правил условным для состояния лексера, инкапсулированного в начальном состоянии. Например, если вам нужно сделать что-то другое для шаблона прямо в начале строки, вы можете выполнить переход к начальному условию начала строки в вашем шаблоне для новой строки:
%x LINE_START
%%
/* ... */
\r\n?|\n { ++yylineno; BEGIN(LINE_START); }
/* ... */
pattern { /* pattern is not at the start of a line */ }
<LINE_START>pattern { /* pattern is at the start of a line */
BEGIN(INITIAL);
}
<*>other-pattern { /* might or might not be at the start of a line */
BEGIN(INITIAL); /* In case it wasn't */
}
Если вы столкнулись с какой-либо другой проблемой, вам следует подготовить соответствующий вопрос с подробным описанием проблемы и [mcse], в котором вы найдете проблему.