我正在设计一个转换为Java源代码的DSL。它们的常用符号通常用于指定编译器的语义/转换吗?
示例:
DSL:
a = b = c = 4
转换为:
Integer temp0 = 4;
Integer a = temp0;
Integer b = temp0;
Integer c = temp0;
提前致谢,
的Jeroen
答案 0 :(得分:2)
模式匹配语言可用于形式化小树变换。有关此类DSL的示例,请查看Nanopass framework。更通用的方法是将树变换视为术语重写的一种形式。
这种变换足够正式,例如,它们可以被认证,如CompCert。
答案 1 :(得分:2)
有定义语义的正式语言;您可以在编程语言的会议论文集中的几乎任何技术论文中看到这些语言和定义。有关该主题的文本可供使用:https://mitpress.mit.edu/.../semantics-programming-languages您需要有一些阅读简明数学符号的意愿。
实际上,这些语义不用于驱动翻译/编译器;这仍然是一个研究课题。请参阅http://Fwww.andrew.cmu.edu%2Fuser%2Fasubrama%2Fdissertation.pdf要阅读这些内容,您通常需要花一些时间阅读上述介绍性文本。
在定义翻译方面有更多实际工作;最实用的是program transformation systems。 使用这些工具,可以使用源语言的符号(例如,您的DSL)和目标语言的符号(例如,Java或汇编程序或其他),转换规则进行编写 形式:
replace source_language_fragment by target_language_fragment if condition
这些工具由源语言和目标语言的语法驱动,并将转换规则从其可读形式解释为AST到AST重写。要将复杂的DSL完全翻译成另一种语言通常需要数百条规则,但关键是它们比手写翻译器的典型程序代码更容易阅读。
尝试遵循OP的示例,假设一个人使用OP的“MyDSL”和“Java”作为目标语法,并使用我们的DMS软件再造工具包的转换规则风格:
source domain dsl;
target domain Java;
rule translate_single_assignment(t: dsl_IDENTIFIER, e: dsl_expression):
" \t = \e " -- MyDSL syntax
-> -- read as "rewrites to"
" int \JavaIdentifier\(\t\)=\e;
".
rule translate_multi_assignment(t1: dsl_IDENTIFIER, t2: dsl_IDENTIFIER, e: dsl_expression):
" \t1 = \t2 = \e " -- MyDSL syntax
-> -- read as "rewrites to"
" \>\dsl \t2 = \e \statement
int \t1;
\t1=\t2;
".
您需要两个规则:一个用于简单赋值的基本情况t = e;和一个处理多个赋值案例。多重赋值案例剥离了最外层的赋值, 并为其生成代码,并将多个赋值的剩余部分插回到其原始DSL格式中,由两个规则之一重新处理。
看到另一个用于重构的示例(source_language == target_language)