Bu sorunun 4 yaşından büyük olduğunu biliyorum ama daha ayrıntılı bir cevap eklemem gerektiğini düşünüyorum.
Soyut Sözdizimi Ağaçları diğer ağaçlardan farklı olarak yaratılmaz; bu durumda daha doğru olan ifade, Sözdizimi Ağacı düğümlerinin, AS İHTİYACI OLARAK değişken miktarda düğümlere sahip olmasıdır.
Örnek, şöyle bir ikili ifadelerdir. Bunun gibi 1 + 2
basit bir ifade, sayılarla ilgili verileri tutan sağ ve sol düğümü tutan tek bir kök düğüm oluşturur. C dilinde, bunun gibi bir şey olurdu
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;
};
Sorunuz da nasıl geçileceği idi? Bu durumda Traversing Ziyaret Düğümleri denir . Her Düğümü ziyaret etmek, her bir Sözdizimi düğümü verilerinin nasıl değerlendirileceğini belirlemek için her düğüm türünü kullanmanızı gerektirir.
İşte C'deki her bir düğümün içeriğini basmaya başladığım başka bir örnek:
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;
}
}
Hangi düğümle uğraştığımıza göre, işlevin her düğümü tekrar tekrar ziyaret ettiğine dikkat edin.
Daha karmaşık bir örnek, bir if
ifade yapısı ekleyelim ! İfadelerin isteğe bağlı başka bir cümlecik olabileceğini de hatırlayın. İf-else ifadesini orijinal düğüm yapımıza ekleyelim. Eğer ifadelerin kendileri de eğer ifadelerde olabilirse, düğüm sistemimizde bir tür özyinelemenin oluşabileceğini unutmayın. Başka ifadeler isteğe bağlıdır, bu nedenle elsestmt
özyinelemeli ziyaretçi işlevinin göz ardı edebileceği NULL olabilir.
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;
};
geri çağrılan düğüm ziyaretçi baskısı işlevimize geri AST_PrintNode
dönersek, if
bu C kodunu ekleyerek AST yapı ifadesini düzenleyebiliriz :
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;
Kadar basit! Sonuç olarak, Sözdizimi Ağacı, etiketli bir birliğin ağacından ve verilerinin kendisinden çok daha fazlası değildir!