假设我有以下示例EBNF语法。 这不是一个完美的语法,但它应该正确地演示了问题。
Statement = FunctionDefinition | Assignment | Expr ;
Expr = { Term | "(" , Expr , ")" } ;
Assignment = Word , "=" , Expr ;
FunctionDefinition = Word , { Word } , "=" , Expr ;
Term = Word | Number
当一个Word
是一些字母和数字的组合,而一个Number
则是一个有效的数字文字。
我可以这样在Rust中表示:
enum Statement {
FunctionDefinition {
name: String,
params: Vec<String>,
body: Expr,
},
Assignment {
name: String,
body: Expr,
},
//TODO: Expr
}
然而,这里已经存在一个问题。我如何添加Expr
?Expr
可能应该有自己的定义,因为它在其他几个地方也被使用。给Expr
单独定义然后将其添加到此枚举中将会重新定义它。
如果我继续尝试定义Expr
,我会遇到更多问题:
type Expr = Vec<...?...>;
// or maybe...
struct Expr {
terms: Vec<Expr>, // but what about Term??
}
我试图使用type
,因为Expr
不一定需要成为自己的结构体或枚举类型,因为它只是Term
或其他Expr
的集合。然而,这种递归定义很难实现。如果我尝试使用枚举类型来模拟Expr和Term的联合类型,那么我必须在该枚举中重新定义Expr
并在枚举中定义Term
,这将使得我需要的其他结构体无法使用Term。
Expr(Expr)
或Term(Term)
。有点丑陋,但它能用。 - Sunjay Varma