Tôi biết câu hỏi này đã hơn 4 tuổi nhưng tôi cảm thấy nên thêm một câu trả lời chi tiết hơn.
Cây Syntax trừu tượng được tạo ra không khác với các cây khác; tuyên bố đúng hơn trong trường hợp này là các nút Syntax Tree có số lượng nút rất NHƯ NHU CẦU.
Một ví dụ là các biểu thức nhị phân như 1 + 2
Một biểu thức đơn giản như thế sẽ tạo ra một nút gốc duy nhất giữ một nút phải và trái chứa dữ liệu về các số. Trong ngôn ngữ C, nó trông giống như
struct ASTNode;
union SyntaxNode {
int64_t llVal;
uint64_t ullVal;
struct {
struct ASTNode *left, *right;
} BinaryExpr;
};
enum SyntaxNodeType {
AST_IntVal, AST_Add, AST_Sub, AST_Mul, AST_Div, AST_Mod,
};
struct ASTNode {
union SyntaxNode *Data;
enum SyntaxNodeType Type;
};
Câu hỏi của bạn cũng là làm thế nào để đi qua? Di chuyển trong trường hợp này được gọi là Nút thăm . Truy cập từng nút yêu cầu bạn sử dụng từng loại nút để xác định cách đánh giá dữ liệu của từng nút Cú pháp.
Đây là một ví dụ khác về C trong đó tôi chỉ cần in nội dung của từng nút:
void AST_PrintNode(const ASTNode *node)
{
if( !node )
return;
char *opername = NULL;
switch( node->Type ) {
case AST_IntVal:
printf("AST Integer Literal - %lli\n", node->Data->llVal);
break;
case AST_Add:
if( !opername )
opername = "+";
case AST_Sub:
if( !opername )
opername = "-";
case AST_Mul:
if( !opername )
opername = "*";
case AST_Div:
if( !opername )
opername = "/";
case AST_Mod:
if( !opername )
opername = "%";
printf("AST Binary Expr - Oper: \'%s\' Left:\'%p\' | Right:\'%p\'\n", opername, node->Data->BinaryExpr.left, node->Data->BinaryExpr.right);
AST_PrintNode(node->Data->BinaryExpr.left); // NOTE: Recursively Visit each node.
AST_PrintNode(node->Data->BinaryExpr.right);
break;
}
}
Lưu ý cách hàm truy cập đệ quy từng nút theo loại nút chúng ta đang xử lý.
Hãy thêm một ví dụ phức tạp hơn, một if
cấu trúc câu lệnh! Hãy nhớ lại rằng nếu các câu lệnh cũng có thể có một mệnh đề khác tùy chọn. Hãy thêm câu lệnh if-other vào cấu trúc nút ban đầu của chúng tôi. Hãy nhớ rằng nếu bản thân các câu lệnh cũng có thể có các câu lệnh if, do đó, một loại đệ quy trong hệ thống nút của chúng ta có thể xảy ra. Các câu lệnh khác là tùy chọn để elsestmt
trường có thể là NULL mà hàm khách truy cập đệ quy có thể bỏ qua.
struct ASTNode;
union SyntaxNode {
int64_t llVal;
uint64_t ullVal;
struct {
struct ASTNode *left, *right;
} BinaryExpr;
struct {
struct ASTNode *expr, *stmt, *elsestmt;
} IfStmt;
};
enum SyntaxNodeType {
AST_IntVal, AST_Add, AST_Sub, AST_Mul, AST_Div, AST_Mod, AST_IfStmt, AST_ElseStmt, AST_Stmt
};
struct ASTNode {
union SyntaxNode *Data;
enum SyntaxNodeType Type;
};
trở lại trong chức năng in của khách truy cập nút được gọi AST_PrintNode
, chúng ta có thể điều chỉnh if
câu lệnh AST xây dựng bằng cách thêm mã C này:
case AST_IfStmt:
puts("AST If Statement\n");
AST_PrintNode(node->Data->IfStmt.expr);
AST_PrintNode(node->Data->IfStmt.stmt);
AST_PrintNode(node->Data->IfStmt.elsestmt);
break;
Đơn giản vậy thôi! Tóm lại, Cây Cú pháp không khác gì một cây liên kết được gắn thẻ của cây và chính dữ liệu của nó!