如何在Rust数据结构中表示递归EBNF语法?

时间:2016-06-02 01:27:11

标签: parsing data-structures rust ebnf

我们说我有以下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
}

但这里已经存在问题了。如何添加ExprExpr应该有自己的定义,因为它也用在其他几个地方。给Expr单独的定义,然后将其添加到此枚举中将重新定义它。

如果我继续并继续尝试定义Expr,我会遇到更多问题:

type Expr = Vec<...?...>;
// or maybe...
struct Expr {
    terms: Vec<Expr>, // but what about Term??
}

我尝试使用type,因为Expr不一定需要是自己的结构或枚举,因为它只是Term s或其他Expr的集合。尽管如此,很难以递归方式定义它。如果我尝试使用枚举来模拟Expr和Term的联合类型,那么我必须在该枚举中重新定义Expr并在枚举中定义Term,这使得其他结构中的Term不可用需要。

1 个答案:

答案 0 :(得分:2)

Expr可以是type别名,但您需要定义enum来表示替换。 Term也需要单独enum

enum Statement {
    FunctionDefinition {
        name: String,
        params: Vec<String>,
        body: Expr,
    },
    Assignment {
        name: String,
        body: Expr,
    },
    Expr(Expr),
}

type Expr = Vec<ExprItem>;

enum ExprItem {
    Term(Term),
    Parenthesized(Expr),
}

enum Term {
    Word(String),
    Number(f64),
}
相关问题