Compiler construction 如何从BNF设计抽象语法树(AST)

Compiler construction 如何从BNF设计抽象语法树(AST),compiler-construction,translation,abstract-syntax-tree,bnf,Compiler Construction,Translation,Abstract Syntax Tree,Bnf,我已经定义了我的语言的BNF,不知道如何用它来设计AST 例如,从我的BNF的前几行: <program> ::= <import declarations>? <class declaration>? <import declarations> ::= <import declaration> | <import declarations> <import declaration> <class decl

我已经定义了我的语言的BNF,不知道如何用它来设计AST

例如,从我的BNF的前几行:

<program> ::= <import declarations>? <class declaration>?
<import declarations> ::= <import declaration> | <import declarations> <import declaration>
<class declaration> ::= class <identifier> <class body>
<import declaration> ::= import <type name> ';'
::=?
::=  |  
:=类
:=导入“;”
如何从AST中表达这一点?我应该这样设计吗

typedef vector<ImportDeclaration*> ImportDeclarationList;

class Program {
    ImportDeclarationList importDeclarations;
    ClassDeclaration classDeclaration;
};

class ImportDeclaration {
    TypeName typeName;
};

class ClassDeclaration {
    Identifier identifer;
    ClassBody classbody;
};
typedef向量导入删除列表;
班级计划{
ImportDeclarationList importDeclarations;
类声明类声明;
};
类导入声明{
类型名类型名;
};
类声明{
标识符标识符;
类体类体;
};
我需要在这些类中添加一些继承吗


有一些关于如何从BNF设计AST的书吗?

您只需要实现一个树数据结构。这意味着您将需要某个类,例如节点,AST的所有其他可能元素都必须从该类继承。然后可以使用成员指针(节点*)。如果子对象的数量可能不同,则可以将它们存储在std::vector中。 对于一个非常简单的产品(假设IntLiteral是一个终端):

可以为AST编写以下代码:

struct Node {
    virtual Node* clone() { return new Node(*this);};
    virtual ~Node() {}
};
class IntLiteral : Node {
    int value;
public:
    IntLiteral(int v) : value(v) {}
    virtual IntLiteral* clone()
    {
        return new IntLiteral(*this);
    }
};
class Addition : Node {
    Node* left;
    Node* right;
public:
    Addition(Node* l, Node* r)
        : Node(), left(l->clone()), right(r->clone()) {}
    virtual Addition* clone()
    {
        return new Addition(*this);
    }
};
假设您是手工实现的,您可以在解析器代码的接受函数中将节点添加到根节点(在本例中为类型添加*)

实际上,您可能希望为每个节点使用
generate
函数。或者,这可能是一个更好的主意,您将需要访问器和树遍历器来生成代码

有很多关于解析器的书,其中一本是经典的“龙之书”,尽管这里的重点实际上是编译器。

节点需要包含一个“抽象”语法类别(通常接近许多规则的LHS)。有关AST与CST的讨论,以及为什么您可能希望节点包含具体的语法类别(例如,确切地说是规则的LHS,或叶子的具体名称),请参见。
struct Node {
    virtual Node* clone() { return new Node(*this);};
    virtual ~Node() {}
};
class IntLiteral : Node {
    int value;
public:
    IntLiteral(int v) : value(v) {}
    virtual IntLiteral* clone()
    {
        return new IntLiteral(*this);
    }
};
class Addition : Node {
    Node* left;
    Node* right;
public:
    Addition(Node* l, Node* r)
        : Node(), left(l->clone()), right(r->clone()) {}
    virtual Addition* clone()
    {
        return new Addition(*this);
    }
};