首页 > 解决方案 > 如何在球拍中创建新语言?

问题描述

我想创建一种与键入球拍具有相同语法的新语言,但执行时会做两件事:

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

关于如何开始或指向一些骨架代码的任何建议?我已经阅读了本教程,但它主要讨论的是创建我不需要的新语法。

我了解如何编写球拍代码以将一种语言翻译成另一种语言,但我不明白的是如何同时完成上述两项工作,即首先将其作为另一种语言运行,然后使用相同的输入执行其他操作.

标签: racket

解决方案


听起来你想用一种新的#%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

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

您可以在我写的一篇讨论视频语言这一方面的论文中阅读有关此过程的更多信息。您还可以找到Beautiful Racket一书,其中包含一些您可能会觉得有用的示例。


推荐阅读