Конец строки lex - PullRequest
0 голосов

Я пишу интерпретатор для сборки с использованием lex и yacc. Проблема в том, что мне нужно разобрать слово, которое будет строго в конце файла. Я читал, что есть якорь $, который может помочь. Однако это не работает, как я ожидал. Я написал это в моем файле lex:

ABC$    {printf("QWERTY\n");}

Входной файл:

ABC

без пробелов и других невидимых символов. Поэтому я ожидаю, что на выходе будет QWERTY, однако получаю:

ABC

что, я думаю, означает, что программа не смогла разобрать его. Тогда я подумал, что $ может быть обычным символом в lex, поэтому я изменил входной файл на этот:

ABC$

Итак, если $ не является специальным символом, он будет проанализирован как обычный символ, и на выходе будет QWERTY. Этого не происходит, вывод:

ABC$

Вопрос в том, является ли $ в lex нормальным или специальным символом.

1 Ответ

2 голосов
/ 13 мая 2019

В (f) лекс, $ соответствует нулю символов , за которым следует символ новой строки .

Это отличается от многих библиотек регулярных выражений, где $ будет соответствовать в конце ввода,Поэтому, если в вашем файле нет новой строки в конце, как показывает ваш вопрос (при условии, что вы считаете новую строку невидимым символом), он не будет совпадать.

Как @ sepp2k предлагает в комментарии,шаблон также не будет сопоставлен, если во входном файле используются окончания строк Windows (которые состоят из последовательности \r\n), если только сгенерированный файл flex не был скомпилирован для Windows.Таким образом, если вы создали файл в Windows и запустили сканер, сгенерированный flex, в среде Unix, \r также приведет к тому, что шаблон не будет соответствовать.В этом случае вы можете использовать (f) оператор конечного контекста lex:

ABC/\r?\n   { puts("Matched ABC at the end of a line"); }

См. Документацию по гибкому шаблону для шаблонов для полного описания оператора конечного контекста.(Ищите «конечный контекст» на этой странице; он примерно на полпути вниз.) $ равен точно эквивалентно /\n.

Это все равно не будет соответствовать ABC присамый конец файла.Совпадение строк в самом конце файла немного сложно, но это может быть сделано с двумя шаблонами, если можно распознать строку, отличную от конца файла, вызывая другое действие:

ABC/.    { /* Do nothing. This ABC is not at the end of a line or the file */ }
ABC      { puts("ABC recognised at the end of a line"); }

Это работает, потому что первый шаблон будет совпадать, если после ABC есть какой-то не-символ новой строки.(. соответствует любому символу, кроме новой строки. Для получения подробной информации см. Ссылку выше). Если вам также нужно работать с окончаниями строк Windows, вам необходимо изменить конечный контекст в первом шаблоне.

...