在 Ruby 中构造 AST 的惯用方法是什么?

What is the idiomatic way to construct an AST in Ruby?

我正在为一个简单的语法制作一个解析器来学习解析技术。

例如,如果我有以下语法:

exp    := if-exp ...
if-exp := if bool-exp then exp else exp
....

在支持代数数据类型的语言中,我可以做到:

type exp = 
| If-exp of bool-exp * exp * exp
| ....

A Java example 我发现为每个子表达式创建一个 class:

Class If_exp
  @bool_exp
  @then_exp
  @else_exp

 ...

end

"How to manually construct an AST?" 使用哈希构造 AST。

哪种方式更好? Ruby 方法是什么?

我认为不一定有 'idiomatic way'。仅使用哈希与自定义域对象各有利弊。自定义域对象(一个 class 代表每个节点类型)可能更好,但需要更多的工作来实现。

Parslet 是一个易于使用的 ruby 库,用于解析和创建 AST。尽管要注意 Parslet 有点慢,不应该在性能很重要的地方使用。我认为 Parslet 默认情况下会给你一个 AST 作为散列,但如果你设置正确,你可以获得自定义域对象。

哈希主要是因为它们易于实现而被使用,我认为在所有其他方面它们可能更差。哈希只是一种捷径。但是 ruby 中经常使用的一种,当然。

没有任何共识 "ruby" 可以做到这一点。对每种类型的子表达式使用单独的 class 将被视为 'more object oriented'。与使用哈希相比,它可能会或可能不会更快或更慢的性能。它可能需要更多的工作来实施,但也可能不需要。

Ruby 2.6 添加RubyVM::AST模块

https://blog.bigbinary.com/2018/10/02/ruby-2-6-adds-rubyvm-ast-module.html