compiler-construction - 语言文字支持

标签 compiler-construction constructor literals

是否有任何语言可以轻松扩展编译器以支持新的文字示例,例如json / xml / yaml /不同的字符串编码/其他数字类型。
我知道您可以随时派发编译器,编写dsl,但这并不是我要问的。我知道某些语言(例如smalltalk和lisp)非常灵活,但是我并不是在寻找可以由一个团队完成的相当简单的事情,而是试图将其引入整个语言并允许其作为通用做法的尝试。 。您也可以分享对类似想法的任何研究。

或者,是否有任何语言通过对象中带有字符串参数alla的特殊方法支持文字(在这种情况下,““”表示要传递给Xml.newFromTripleString(String a)的字符串的开始和结束。

Xml exapmleXml =“”“

#{名称}
#{标题}

“”
我了解许多语言都通过做类似的事情来支持这种事情
XMl exapmleXml = Xml.newFromTripleString(“” +“ \ n”
“ +” \ n“ +
“#{name} +” \ n“ +
“#{title} +” \ n“ +
“”)
但是是否有任何语言尝试通过隐式转换等方法使此操作变得更容易?对这些技术有任何研究吗?

关于如何在语言中引入更灵活的文字或类似文字的支持的其他想法的任何链接和说明也都很好。

最佳答案

Ioke

Ioke允许覆盖文字,但不能覆盖新的文字。这种工作方式是将文字简单地转换为消息发送,然后可以像其他任何方法一样覆盖相应的方法。

例如,这是Dict的“文字语法”,其中有两个条目,一个条目将Symbol映射到Text,另一个条目将Symbol映射到Number

{ :name => "Jörg", :age => 31 }


实际上,这被转换为消息发送,对于名为{}的消息(顺便说一句:列表以相同的方式工作,它们对应的消息为[])。它完全等效于(如果需要,可以这样写):

{}(:name => "Jörg", :age => 31)


现在,=>实际上只是为几乎所有对象定义的一个运算符,它仅返回一个Pair,键(第一个元素)为接收者,值为自变量。现在,操作员也只是消息发送,所以等效于:

{}(:name =>("Jörg"), :age =>(31))


表示文字符号的:标记也被翻译为消息发送:

{}(:("name") =>("Jörg"), :("age") =>(31))


文本文字被转换为发送internal:createText消息:

{}(:("name") =>(internal:createText("Jörg")), :("age") =>(31))


[注意:显然,此处的编写方式将导致无限递归。事实是,internal:createText的参数显然不是Ioke Text,而是平台字符串。即对于Ioke的JVM实现ikj,它实际上是java.lang.String;对于CIL实现,对于ikc,它是System.String。我在这里用三引号表示了这一点。]

{}(:("name") =>(internal:createText("""Jörg""")), :("age") =>(31))


这只是给我们留下了数字,您猜对了,这也是一条发送消息:

{}(:("name") =>(internal:createText("""Jörg""")),
   :("age") =>(internal:createNumber("""31""")))


由于所有内容都是消息发送,因此您可以通过实现相应的方法随意自定义文字的行为。以下是互动式Ioke REPL iik的简短记录:

iik> "Hello"
+> "Hello"

iik> internal:createText = method(raw, super(raw) upper)

iik> "Hello"
+> "HELLO"


Converge

融合允许强大的编译时元编程,包括称为DSL块的功能。 DSL块是不使用Converge语法的代码块。 DSL块如下所示:

$<<xml>>:
    <xml>
      <literal>here</literal>
    </xml>


这种工作方式是$<<>>之间的字符串是函数的名称,该函数的名称在编译时被调用,并以字符串形式传递整个DSL块(以及某些源代码元数据,例如行号,文件名等),并返回Converge抽象语法树的片段。因此,在这种特殊情况下,将具有如下功能:

func xml(dsl_block, src_infos):
    // implement an XML parser here ...
    return ast


Factor

Factor允许定义分析词,这些词会影响相同范围内其他词的分析方式。 Factor实际上有一个XML library implementation使用解析词来获取语法,该语法看起来非常类似于Scala的XML文字,但是只是普通的Factor代码:

: feed>xml ( feed -- xml )
    [ title>> ]
    [ url>> present ]
    [ entries>> [ entry>xml ] map ] tri
    <XML
        <feed xmlns="http://www.w3.org/2005/Atom">
            <title><-></title>
            <link href=<-> />
            <->
        </feed> 
    XML> ;


[快速介绍因素::定义了一个新词,即第一行定义了一个名为feed>xml的词,该词带有一个参数并产生一个结果。单词的前三行从提要对象中提取标题,URI和条目,并将它们放在堆栈中。 <XML是解析词,它打开XML模式,而XML>再次将其关闭。在XML代码内部,<->从堆栈中获取一个值并将其插入XML。]

普通口齿不清

Common Lisp Reader Macros允许您进入阅读阶段,即获取字符串并生成嵌套列表,然后将其交给编译器/评估器的阶段。它们要求您选择一个唯一的一个或两个字符的前缀,并且它们是全局的。第一个问题不大,因为我们可以简单地选择<字符作为前缀使它看起来自然。

Perl 6

Perl 6应该允许您在程序运行时更改语法。 Perl 6具有动态可变语法,这意味着代码在执行时会被解析,并且可以更改语法,以便使用新语法来解析文件中更远的其他代码。

OMeta /可乐

Alessandro Warth's OMeta language之上运行的Ian Piumarta's COLA system允许使用所谓的“特定于心情的语言”。即这些语言的规范和实现非常轻巧,因此您可以在程序中间只使用它们一行,然后再次切换到其他语法。

在Alan Kay的Inventing Fundamental New Computing TechnologiesViewpoint Research Institute中使用它。一种示例用法是,通过设计一种语法与IETF RfC中使用的ASCII艺术图相同的语言和另一种用于编写网络协议状态机的语言,仅用200行代码即可实现整个TCP / IP网络堆栈。然后,网络堆栈的实现仅包括复制和粘贴来自RfC的ASCII图,并将英语状态机描述从RfC转换为状态机语言。

(哦,如果您想知道的话:200行不仅用于ASCII图和状态机。它还包括两种语言的解析器和编译器。)

π

π编程语言也可能很有趣。

关于compiler-construction - 语言文字支持,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3137742/

相关文章:

linux - 使用 MONO 编译 - 引用 C# 库的 C#?

c# - 试图在编译时分配一个大数字

javascript - 了解使用 'Object.create()' 而不是 'new' 关键字创建原型(prototype)对象

c++ - 使用 "()"调用构造函数不同于 "{}"

Scala:如何转义文字中的反引号?

java - 寄存器分配中的预着色节点 - 每种颜色最多一种?

c - 在什么阶段抛出错误?

flutter - 如何检查是否使用 dart 中的命名构造函数创建了元素?

javascript - HTML 模板到 Javascript 字符串文字

.net - 如何在 F# 中编写内联大字符串