在球拍中实现语言翻译

时间:2018-06-30 16:14:39

标签: racket

我正在使用Racket实现将代码生成为另一种语言的解释器。作为一个新手,我尽力避免使用宏;)因此,我想到了以下“解释器”:

(define op (open-output-bytes))
(define (interpret arg)
  (define r
     (syntax-case arg (if)    
       [(if a b) #'(fprintf op "if (~a) {~a}" a b)]))
       ; other cases here
  (eval r))

在我看来这有点笨拙。是否有“最佳实践”来做到这一点?我在这里做一件完全疯狂的事吗?

2 个答案:

答案 0 :(得分:2)

简短的回答:是的,这是合理的做法。不过,您的操作方式将在很大程度上取决于您的具体情况。

您绝对正确地注意到,将程序生成为字符串是一种容易出错且易碎的方式。但是,要避免这种情况,就需要能够以更高的级别表达目标语言,以规避该语言的解析器。

同样,它确实与您要定位的语言以及您要完成的工作有很大关系。在我知道我没有时间做正确的事情的情况下,我已经一起整理了自己生成Python这样的东西。

编辑:哦,你也在做Python吗? le! :)

您有许多不同的选择。您最干净的选择是生成Python AST节点的表示形式,因此您可以直接注入它们或使用现有的序列化。您将要问我是否有用于此的库,而且……我很烦。我确实相信当前的Python体系结构包括...好的,是的,我去看了看,您的状态良好。 Python的“解析器”模块会生成AST,看起来可以直接构造AST模块。

https://docs.python.org/3/library/ast.html#module-ast

我猜您最干净的路径是生成代表这些AST模块的JSON,然后编写一个Python存根,将其转换为Python AST。

所有这些都假定您要走高路。涉及到python语法的简单概括的中间方法种类繁多(例如:哦,看起来这种语句带有冒号,后跟缩进的代码块等)。

答案 1 :(得分:2)

如果您的源语言与Racket共享语法,请使用Secretary stan = edna.new Secretary();生成代表输入程序的语法对象。然后使用M-x debug-watch <variable> RETread-syntax递归下降来识别各种构造。

我建议您构建一棵元素树(字符串,数字,符号等),而不是直接打印到输出端口。然后,最后一步是打印树的所有元素。使用树表示输出非常灵活,可以让您无序地处理子表达式。它还使您可以有效地串联来自不同来源的输出。

不需要宏。