C ++中抽象语法树的最惯用表示是什么?

时间:2019-11-02 14:28:20

标签: c++ abstract-syntax-tree lambda-calculus

我想为简单类型的lambda演算构造一个简单的解析器/类型检查器/评估器。我已经在Rust中实现了这种方法,但是作为C ++的新手,我不确定表示AST的最佳方法是什么。例如,在Rust中,我可以定义递归和类型。然后,我可以使用模式匹配或“访客”模式来访问子术语。

enum Term {
    // de Bruijn index
    Var(usize),
    // Lambda abstraction x: T. t
    Abs(Box<Term>, Box<Term>),
    // Application t1 t2
    App(Box<Term>, Box<Term>),
}

fn ex(term: &mut Term) {
    match term {
        Term::Var(idx) => {

        },
        Term::Abs(ty, tm) => {
            ex(tm.as_mut());
        },
        Term::App(t1, t2) => {
            // do something
        }
    }
}

没有求和类型,似乎有两种主要的方式来表示C ++中的相似事物:枚举/联合对(我将在C中使用)或具有访客模式的类层次结构(未显示完整实现)

class Expr {
public:
  virtual void visit(Visitor &v) const = 0;
  virtual ~Expr() {}
};

class Var : public Expr {
public:
  Var(int idx) : debruijn{idx} {}

private:
  int debruijn;
};

class App : public Expr {
public:
  App(std::unique_ptr<Expr> t1, std::unique_ptr<Expr> t2)
      : e1{std::move(t1)}, e2{std::move(t2)} {}

private:
  std::unique_ptr<Expr> e1;
  std::unique_ptr<Expr> e2;
};

class Abs : public Expr {
public:
  Abs(Type ty, std::unique_ptr<Expr> e) : e{std::move(e)}, ty{ty} {}

private:
  Type ty;
  std::unique_ptr<Expr> e;
};

这是最好的方法吗?我想通过以最现代和惯用的风格编写代码来开始C ++学习。

1 个答案:

答案 0 :(得分:0)

从C ++ 17开始,C ++在标准库std::variant中确实具有求和类型-之类的。

您可以use std::visit with the overloaded hack匹配正确的案例类。如今,将其用于AST应该很惯用了。

此外,您可能希望使用std::optional<T>而不是std::unique_ptr<T>


...或者,您可以查看Boost.Spirit X3库,该库生成解析器,并查看其中的内容。这是一个C ++ 14库。