yacc/lex или ручное кодирование?
Я работаю над новым языком программирования, но я всегда был озадачен тем фактом, что все используют yaxx / lex для разбора кода, а я нет.
Мой компилятор (который уже работает) написан вручную на C++/STL, и я не могу сказать, что он сложный или занял слишком много времени. У него есть как лексер, так и парсер, но они не генерируются автоматически.
Ранее я написал компилятор C (не полную спецификацию) тем же способом - он смог скомпилировать программу за 1 проход, с разрешением и предварительной обработкой всех обратных ссылок - это определенно невозможно с помощью yacc/lex.
Я просто не могу убедить себя отказаться от всего этого и начать погружаться в yaxx / lex - что может потребовать значительных усилий для реализации и может ввести некоторые грамматические ограничения.
Есть что-то, что я пропускаю, когда не использую yacc/lex? Я делаю зло?
5 ответов
Yacc негибок в некоторых отношениях:
- хорошая обработка ошибок трудна (в основном, ее алгоритм определен только для правильного разбора правильной строки, в противном случае все ставки отключены; это одна из причин, по которой GCC перешел на рукописный анализатор)
- зависимость от контекста трудно выразить, тогда как с помощью рукописного анализатора рекурсивного спуска вы можете просто добавить параметр в функции
Кроме того, я заметил, что объектный код lex/yacc часто больше, чем рукописный анализатор рекурсивного спуска (исходный код имеет тенденцию быть наоборот).
Я не использовал ANTLR, поэтому я не могу сказать, лучше ли это в этих точках.
Основные преимущества использования любого вида генератора лексеров / парсеров в том, что он дает вам гораздо больше гибкости, если ваш язык развивается. В лексере / парсере с ручной кодировкой (особенно если вы смешали много функций за один проход!) Изменения в языке становятся довольно неприятными, тогда как с помощью генератора синтаксического анализатора вы вносите изменения, перезапустите генератор, и двигаться дальше со своей жизнью. Конечно, нет никаких внутренних технических ограничений, чтобы всегда просто писать все вручную, но я думаю, что способность к развитию и ремонтопригодность автоматизации скучных битов того стоят!
Другое огромное преимущество использования генераторов состоит в том, что они гарантированно обрабатывают точно и только тот язык, который вы указали в грамматике. Вы не можете сказать это ни о каком рукописном коде. Варианты LR/LALR также гарантированно равны O(N), что опять-таки нельзя утверждать ни о каком ручном кодировании, по крайней мере, без особых усилий при создании доказательства.
Я написал оба и жил с обоими, и я никогда больше не буду писать код вручную. Я сделал это только потому, что в то время у меня не было yacc на платформе.
Возможно, вы упускаете ANTLR, который хорош для языков, которые могут быть определены с помощью стратегии синтаксического анализа с рекурсивным спуском.
Потенциально есть некоторые преимущества использования Yacc/Lex, но их использование не обязательно. Есть и недостатки использования Yacc/Lex, но преимущества обычно перевешивают недостатки. В частности, часто легче поддерживать грамматику, основанную на Yacc, чем ручную, и вы получаете выгоду от автоматизации, которую обеспечивает Yacc.
Однако написание собственного парсера с нуля не является чем-то злым. Это может усложнить поддержание в будущем, но может и облегчить.
Это, безусловно, зависит от сложности вашей грамматики языка. Простая грамматика означает, что есть легкая реализация, и вы можете просто сделать это самостоятельно.
Взгляните, возможно, на худший из возможных примеров: C++:) (Кто-нибудь знает другой язык, кроме естественных языков, которые сложнее правильно анализировать?) Даже с такими инструментами, как Antlr, довольно сложно сделать это правильно, хотя это управляемо. При этом, с другой стороны, даже несмотря на то, что это намного сложнее, кажется, что некоторые из лучших синтаксических анализаторов C++, например, GCC и LLVM, также в основном написаны от руки.
Если вам не нужно слишком много гибкости и ваш язык не слишком тривиален, вы наверняка сэкономите некоторую работу / время, используя Antlr.