Генерация Java-классов из файла грамматики DSL
Я ищу способ генерировать анализатор из файла грамматики (BNF/BNF-like), который будет заполнять AST. Тем не менее, я также хочу автоматически генерировать различные классы AST так, чтобы они были удобочитаемыми для разработчиков.
Пример: для следующего файла грамматики
expressions = expression+;
expression = CONST | math_expression;
math_expression = add_expression | substract_expression;
add_expression = expression PLUS expression;
substract_expression = expression MINUS expression;
CONST: ('0'..'9')+;
PLUS: '+';
MINUS: '-';
Я хотел бы создать следующие классы Java (с примером того, что я ожидаю, что их поля будут):
class Expressions {List<Expression> expression};
class Expression {String const; MathExpression mathExpression;} //only one should be filled.
class MathExpression {AddExpression addExpression; SubstractExpression substractExpression;}
class AddExpression {Expression expression1; Expression expression2;}
class SubstractExpression {Expression expression1; Expression expression2;}
И во время выполнения я бы хотел, чтобы выражение "1+1-2" генерировало следующий граф объектов для представления AST:
Expressions(Expression(MathExpression(AddExpression(1, SubstractExpression(1, 2)))))
(не говоря уже о приоритете оператора).
Я изучал генераторы синтаксического анализатора DSL (JavaCC/ANTLR и друзья), и самым близким, что я мог найти, было использование ANTLR для генерации класса слушателя с методами стиля "enterExpression" и "exitExpression". Я нашел несколько похожий код, сгенерированный с использованием JavaCC и jjtree с использованием "multi", но он чрезвычайно неудобен и сложен в использовании.
Мои грамматические потребности несколько просты - и я хотел бы максимально автоматизировать создание графов объектов AST.
Есть намеки?
1 ответ
Если вам нужна большая поддержка построения DSL, ANTLR и JavaCC, вероятно, не лучший способ. Они обеспечивают разбор, некоторую поддержку построения деревьев... и после этого вы сами. Но, как вы уже поняли, очень много работы над созданием ваших собственных деревьев, проработкой деталей, и вы вряд ли закончите с DSL; Вы все еще не можете использовать это.
Есть более полные решения: JetBrains MPS, Xtext, Spoofax, DMS. Все они предоставляют способы определения DSL, преобразования его во внутреннюю форму ("деревья построения") и поддержку генерации кода. Первые три имеют встроенную поддержку IDE и предназначены для "маленьких" DSL; DMS не поддерживает, но обрабатывает настоящие языки, такие как C++, а также DSL. Я думаю, что первые три с открытым исходным кодом; DMS коммерческий (я участник DMS).
Markus Voelter только что выпустил онлайн-книгу по DSL Engineering, в которой можно найти идею пожертвования. Он подробно рассказывает о MPS, XText, Spoofax, но не о DMS. Он говорит вам, что вам нужно знать и что вам нужно делать; Судя по моему взгляду на книгу, она довольно обширная. Вы, вероятно, не собираетесь выходить на "простом"; DSL имеют большую семантическую сложность, а вспомогательный механизм сложен.
Я знаю автора, очень уважаю его навыки на этой арене и вместе с ним читал лекции по техническим летним навыкам, включая выпивку хорошего пива. Иначе мне нечего делать этой книге.