Я хотел бы реализовать внешний DSL, такой как SQL, в Scala с использованием макросов. Я уже видел документы о том, как реализовать внутренние DSL em> с помощью Scala. Кроме того, я недавно написал статью о как это можно сделать на Java, я сам.
Теперь внутренние DSL всегда кажутся немного неуклюжими, поскольку они должны быть реализованы и использоваться на основном языке (например, Scala) и придерживаться синтаксических ограничений основного языка. Вот почему я надеюсь, что макросы Scala позволят интегрировать внешний DSL без каких-либо таких ограничений. Однако я не совсем понимаю макросы Scala и то, как далеко я могу зайти с ними. Я видел эту SLICK, а также гораздо менее известную библиотеку под названием sqltyped начали использовать макросы, но SLICK использует синтаксис Scalaesque для запросов, который на самом деле не является SQL, тогда как sqltyped использует макросы для анализа строк SQL. (что можно сделать и без макросов). Кроме того, различные примеры, приведенные на веб-сайте Scala, слишком тривиальны для что я пытаюсь сделать
У меня вопрос:
Рассмотрим пример внешнего DSL, определенного как некоторая грамматика BNF, например:
MyGrammar ::= (
'SOME-KEYWORD' 'OPTION'?
(
( 'CHOICE-1' 'ARG-1'+ )
| ( 'CHOICE-2' 'ARG-2' )
)
)
Могу ли я реализовать указанную выше грамматику с помощью макросов Scala для таких клиентских программ? Или макросы Scala недостаточно мощны для реализации такого DSL?
// This function would take a Scala compile-checked argument and produce an AST
// of some sort, that I can further process
def evaluate(args: MyGrammar): MyGrammarEvaluated = ...
// These expressions produce a valid result, as the argument is valid according
// to my grammar
val result1 = evaluate(SOME-KEYWORD CHOICE-1 ARG-1 ARG-1)
val result2 = evaluate(SOME-KEYWORD CHOICE-2 ARG-2)
val result3 = evaluate(SOME-KEYWORD OPTION CHOICE-1 ARG-1 ARG-1)
val result4 = evaluate(SOME-KEYWORD OPTION CHOICE-2 ARG-2)
// These expressions produce a compilation error, as the argument is invalid
// according to my grammar
val result5 = evaluate(SOME-KEYWORD CHOICE-1)
val result6 = evaluate(SOME-KEYWORD CHOICE-2 ARG-2 ARG-2)
Обратите внимание: меня не интересуют решения, анализирующие строки, например sqltyped делает