我想为简单类型的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 ++学习。
答案 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库。