Есть ли лучший (более современный) инструмент, чем lex / flex для генерации токенизатора для C ++? - PullRequest
22 голосов
/ 31 января 2010

Я недавно добавил разбор исходного файла в существующий инструмент, который генерировал выходные файлы из сложных аргументов командной строки.

Аргументы командной строки стали настолько сложными, что мы начали разрешать их предоставление в виде файла, который был проанализирован, как если бы это была очень большая командная строка, но синтаксис все еще был неудобным. Поэтому я добавил возможность разбора исходного файла с использованием более разумного синтаксиса.

Я использовал flex 2.5.4 для окон, чтобы сгенерировать токенизатор для этого пользовательского формата исходного файла, и он работал. Но я ненавидел код. глобальные переменные, странное соглашение об именах и сгенерированный им код на c ++ были ужасны. Существующий бэкэнд генерации кода был приклеен к выводу flex - я не использую yacc или bison.

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

  • Запускается в командной строке Windows (интеграция Visual Studio в порядке, но я использую make files для сборки)
  • Создает правильный инкапсулированный токенайзер C ++. (Без глобальных переменных)
  • Использует регулярные выражения для описания правил токенизации (совместимо с синтаксисом lex a plus)
  • Не заставляет меня использовать c-runtime (или подделывать его) для чтения файлов. (разбор по памяти)
  • Предупреждает меня, когда мои правила заставляют токенизатор отказаться (или исправляют это автоматически)
  • Дает мне полный контроль над именами переменных и методов (чтобы я мог соответствовать существующему соглашению об именах)
  • Позволяет мне связать несколько парсеров в один .exe без коллизий имен
  • Может генерировать анализатор UNICODE (16-битный UCS-2), если я хочу
  • НЕ является встроенным токенизатором + синтаксическим генератором (я хочу замену lex, а не замену lex + yacc)

Я мог бы, вероятно, жить с инструментом, который только что сгенерировал таблицы токенизации, если бы это было единственно доступным.

Ответы [ 5 ]

11 голосов
/ 31 января 2010

Ragel: http://www.complang.org/ragel/ Подходит для большинства ваших требований.

  • Работает на Windows
  • Он не объявляет переменные, поэтому вы можете поместить их внутри класса или внутри функции, как вам нравится.
  • У него есть хорошие инструменты для анализа регулярных выражений, чтобы увидеть, когда они будут возвращаться. (Я не очень разбираюсь в этом, так как я никогда не использую синтаксис в Ragel, который бы создал парсер обратного отслеживания.)
  • Имена переменных не могут быть изменены.
  • Имена таблиц начинаются с префикса с именем машины, и они объявлены как «const static», так что вы можете поместить более одного в один файл и иметь более одного с тем же именем в одной программе (до тех пор, пока они в разных файлах).
  • Вы можете объявить переменные как любой целочисленный тип, включая UChar (или любой другой тип UTF-16, который вы предпочитаете). Однако он автоматически не обрабатывает суррогатные пары. Он также не имеет специальных классов символов для Unicode (я думаю).
  • Имеет только регулярные выражения ... не имеет функций bison / yacc.

Код, который он генерирует, очень мало мешает программе. Код также невероятно быстрый, а синтаксис Ragel более гибок и читаем, чем все, что я когда-либо видел. Это твердый кусок программного обеспечения. Он может генерировать парсер, управляемый таблицами, или парсер, управляемый goto.

6 голосов
/ 31 января 2010

Boost.Spirit.Qi (анализатор-токенизатор) или Boost.Spirit.Lex (только токенизатор). Я очень люблю Ци, и Лекс тоже неплох, но я просто склоняюсь брать Ци для своих нужд в разборе ...

Единственный реальный недостаток Qi - это увеличение времени компиляции, и оно также работает немного медленнее, чем рукописный код синтаксического анализа. Как правило, это гораздо быстрее, чем анализ с помощью регулярных выражений.

http://www.boost.org/doc/libs/1_41_0/libs/spirit/doc/html/index.html

5 голосов
/ 31 января 2010

Flex также имеет опцию вывода C ++.
Результатом является набор классов, которые выполняют этот анализ.

Просто добавьте в заголовок вашего файла lex следующее:

%option C++
%option yyclass="Lexer"

Тогда в вашем источнике это:

std::fstream  file("config");
Lexer         lexer(&file)
while(int token = lexer.yylex())
{
}
5 голосов
/ 31 января 2010

На ум приходят два инструмента, хотя вам нужно найти для себя подходящий: Antlr и GoldParser . В обоих инструментах доступны привязки к языку, которые можно подключить к среде выполнения C ++.

2 голосов
/ 31 января 2010

boost.spirit и Двор парсер приходят мне в голову. Обратите внимание, что подход к созданию генераторов лексеров несколько заменяется внутренним DSL C ++ (предметно-ориентированный язык) для указания токенов. Просто потому, что это часть вашего кода без использования внешней утилиты, просто следуя ряду правил для определения вашей грамматики.

...