【问题标题】:how can I create a new language in racket?如何在球拍中创建新语言?
【发布时间】:2019-01-12 11:38:43
【问题描述】:

我想创建一种新语言,它的语法与打字球拍相同,但执行时会做两件事:

  1. 以键入的球拍运行给定程序
  2. 如果类型检查,则将输入翻译成另一种语言(比如 python)。我打算写一个从打字球拍形式到 python 语法的翻译器。

关于如何开始或指向一些骨架代码的任何建议?我读过this tutorial,但它主要是关于创建我不需要的新语法。

我了解如何编写球拍代码以将一种语言翻译成另一种语言,但我不明白我如何能做到以上两项,即首先将其作为另一种语言运行,然后用相同的输入。

【问题讨论】:

  • 这不是您想要的,但我认为它可能会有所帮助。 github.com/shinh/elvm 这是一种 IR(中间表示)语言,可以编译为常见的 lisp、python 和其他 30 种语言(其中大部分是小众语言)。并且有一个 C 编译器来输出这个 IR。
  • 通常在创建新语言时,步骤是将语法转换为球拍支持的基础语言,然后球拍会完成剩下的工作,但在球拍中创建新语言后似乎不是这样所以我发现这个问题具有误导性。或许你应该学习Whalesong,它更接近你的目标。

标签: racket


【解决方案1】:

听起来你想用新的#%module-begin 形式制作一种语言。此表单由读者插入(当您在文件顶部执行#lang .... 行时,或者如果您手动编写模块,则由语言插入。无论哪种方式,它通常与您的语言定义相关联。这个宏可以完全访问整个模块的未扩展语法。例如,像这样的宏:

(provide (rename-out [-module-begin #%module-begin]))
(define-simple-macro (-module-begin body ...)
  (#%module-begin
    (writeln '(body ...))
    body ...))

将创建一种做两件事的语言:

  1. 打印出代码主体(作为 s 表达式),并且

  2. 使用编写语言定义的#%module-begin 运行正文。

您可以看到如何使用这种技术来两次抓取程序主体,并用它做两件不同的事情。所以让我们尝试运行这个例子。首先,让我们从上面提取样本,并将其放入文件“mylang.rkt”中:

#lang racket
(provide (rename-out [-module-begin #%module-begin])
         (except-out (all-from-out racket) #%module-begin))
(require syntax/parse/define)
(define-simple-macro (-module-begin body ...)
  (#%module-begin
    (writeln '(body ...))
    body ...))

现在我们可以像这样在mylang 中编写程序:

#lang s-exp "mylang.rkt"
(+ 1 2)

当你运行它时,你会得到这样的东西:

((+ 1 2))
3

首先它打印出程序文本,然后运行它。

您可以在a paper 中阅读有关此过程的更多信息,我写了讨论the Video language 的这一方面。您还可以找到 Beautiful Racket 这本书,其中包含一些您可能会觉得有用的示例。

【讨论】:

    猜你喜欢
    • 2013-09-08
    • 2014-04-29
    • 2020-02-12
    • 2021-08-29
    • 2022-10-06
    • 1970-01-01
    • 1970-01-01
    • 2016-12-24
    • 2021-04-01
    相关资源
    最近更新 更多