2010-03-10 7 views
7

Ist es möglich, einen Parse-Baum gleichzeitig mit dem rekursiven Descent-Parser zu generieren, um zu überprüfen, ob die Daten mit der Grammatik übereinstimmen?Ist es möglich, Recursive Descent Parser zu verwenden, um sowohl die Grammatik zu überprüfen als auch gleichzeitig den Parse-Baum zu erstellen?

Wenn ja, welchen Ansatz würde ich verwenden, um einen Baum zu erstellen, wie ich rekursiv absteigend?

Danke, Boda Cydo.

Hinweis: Ich bin neu beim Parsen. (Ich habe schon einige Fragen zu SO gestellt, und es geht mir immer besser.)

Antwort

6

Ja, das ist möglich. Wie das geht, hängt von der gewünschten Implementierung ab. Hier ist ein Beispiel, das für Sie arbeiten könnte:

Zunächst definieren Sie Ihre Knoten:

class ParseTreeNode { 
    private final String name; 
    private final List<ParseTreeNode> children = /* new */; 
    public ParseTreeNode(String name) { 
    this.name = name; 
    } 
    public void addChild(ParseTreeNode child) { 
    children.add(child); 
} 

Als Nächstes müssen Sie das in Ihre rekursiven Abstiegs-Funktionen integrieren:

class RDParser { 
    ParseTreeNode parse(Input input) { 
    ParseTreeNode root = createParseTreeNodeNamed("Root") 
    switch (input.nextToken()) { 
     case OPT1: 
     root.addChild(createParseTreeNodeNamed("Opt1")); 
     break; 
     case OPT2: 
     while (/*someCondition*/) { 
      root.addChild(createParseTreeNodeNamed("Opt2-sibling" + /* i */)); 
     } 
     case SUBTREE: 
     ParseTreeNode subtree = createParseTreeNodeNamed("Subtree"); 
     root.addChild(subtree); 
     parseSubtree(subtree, input); 
     break; 
     default: 
     error("Input %s was not in the expected first/follow sets", input.nextToken()); 
    } 
    } 
    void parseSubtree(ParseTreeNode node, Input input) { 
    node.addChild(createParseTreeNodeNamed("subtree-child")); 
    /* ... */ 
    } 

    /* and other functions do similarly */ 
    ParseTreeNode createParseTreeNodeNamed(String name) { 
    return new ParseTreeNode(name); 
    } 
} 

Wie Sie Wenn Sie den Parserbaum herunterfahren, werden Sie wahrscheinlich den neuen "root" -Knoten senden müssen, damit Kinder hinzugefügt werden können. Alternativ könnte parseSubtree einen Knoten erstellen und zurückgeben, der dann zum Stammknoten hinzugefügt würde.

Sie können entweder den Syntaxbaum oder einen einfachen abstrakten Baum mithilfe des obigen Prozesses erstellen. Da die Syntaxanalysefunktion den Wurzelknoten zurückgibt, der auf alle untergeordneten Knoten verweist, haben Sie nach dem Parsen vollständigen Zugriff auf den Syntaxbaum.

Unabhängig davon, ob Sie einen heterogenen oder homogenen Syntaxbaum verwenden, benötigen Sie eine Möglichkeit, ausreichende Informationen zu speichern, um sie nützlich zu machen.

+1

Ausgezeichnete Antwort, Kaleb. Es brachte mich sofort zum Laufen, und ich denke, ich werde es jetzt selbst schreiben können! Aber können Sie bitte den Unterschied zwischen "Parse Tree" und "Abstract Tree" und "heterogenous" und "homogenen" Parse Bäumen klären? (Ich kenne den Unterschied noch nicht, aber ich würde es gerne wissen!) – bodacydo

+1

homogen - Ein Baum, der aus der gleichen Art von Knoten besteht. heterogen - Ein Baum, der aus Knoten verschiedener Typen besteht. Ein Syntaxbaum repräsentiert die Struktur der Eingabedaten und enthält normalerweise unnötige Syntax. Ein abstrakter Syntaxbaum bewahrt die essenzielle Struktur und Information, eliminiert aber unnötige Struktur oder Syntax. Ich habe meinen Beitrag geändert, um zu zeigen, wie der Baum tiefer wächst - ich hoffe, das verdeutlicht. –

+0

Danke für die Erklärung! Ich implementiere bereits. :) Ich werde fragen, ob ich nicht weiterkomme. Mein Baum wird ein abstrakter, heterogener Baum sein. :) – bodacydo