Frage

Nachdem ich den Analysebaum erstellt habe, muss ich jetzt die Symboltabelle füllen.

Ich muss Informationen speichern wie

Typ, Umfang, Offset usw. für die Bezeichner.

Woher weiß ich nun den Typ und den Umfang der Bezeichner, da ich nur den Lexemwert und die Zeilennummer für diese bestimmte ID weiß (nach lexikalischer Analyse)?

Wie komme ich zu der ganzen Sache?Danke.

War es hilfreich?

Lösung

Woher weiß ich nun den Typ, den Umfang der Identifikatoren, da ich nur den Lexem -Wert und die Zeilennummer für diese bestimmte ID (nach lexikalischer Analyse) ist.

Wie von EJP erwähnt, müssen Sie den Analysebaum schrittweise durchlaufen.Ihr Baum sollte so erstellt worden sein, dass Sie einen Durchlauf in der richtigen Reihenfolge durchführen und jeden Knoten in derselben Reihenfolge besuchen können, in der Quellcodeanweisungen und -ausdrücke ausgewertet werden.Ihre Baumknoten sollten auch einem bestimmten Sprachkonstrukt entsprechen, z. B. WhileStmtNode, MethodDeclNode, usw.

Angenommen, ich erstelle die Symboltabelle, gehe rekursiv durch den Baum und habe gerade einen Methodenkörperknoten eingegeben.Ich könnte so etwas wie das Folgende haben:

public void doAction(MethodBodyNode methodBody) {
    currScope = 2;
    methodBody.getExpr().applyAction(this);
    currScope = 2;
}

Ich behalte eine globale Variable, um den Bereich zu verwalten.Jedes Mal, wenn ich einen Block betrete, in dem sich der Bereich ändert, würde ich ihn erhöhen currScope.Ebenso würde ich beibehalten currClass Und currMethod Variablen zum Speichern mit Symbolname, Typ, Offset usw.für spätere Phasen.

Aktualisieren:

Sagen Sie nun, ich überquere den Baum, jedes Mal, wenn ich auf eine ID stoße, müsste ich zusammen mit dem Typ, dem Umfang und anderen den Wert in die Symboltabelle eingeben. Aber woher weiß ich, welche Art von ID das ist?

Jeder Baumknoten sollte alle notwendigen Informationen für das gesamte Konstrukt enthalten.Wenn Sie einen Parser-Generator wie CUP oder Bison verwenden, können Sie in den Grammatikaktionen angeben, wie der Baum erstellt werden soll.Z.B.

variableDeclaration::= identifier:i identifier:i2 SEMICOLON {: RESULT = new VarDeclNode(i, i2, null); :};
identifier::= ID:i {: RESULT = new IdNode(i.getLineNum(), i.getCharNum(), i.getStringValue()); :};

Diese Produktionen würden zusammenpassen Foo f; und einen Variablendeklarationsknoten an den Baum anhängen.Dieser Knoten kapselt zwei Bezeichnerknoten, die die Zeilennummer, die Zeichennummer und den Zeichenfolgenwert des Lexems enthalten.Der erste Identifikatorknoten ist der Typ und der zweite der Variablenname. ID ist ein Terminalsymbol, das vom Lexer bei Übereinstimmung mit einem Bezeichner zurückgegeben wird.Ich gehe davon aus, dass Sie damit einigermaßen vertraut sind.

public class VarDeclNode extends StmtNode {

    private IdNode id;
    private IdNode type;
    private ExprNode expr;

    public VarDeclNode(IdNode id, IdNode type, ExprNode expr) {
        super();
        this.id = id;
        this.type = type;
        this.expr = expr;
    }

}

Wenn Sie einen Syntaxbaum mit solchen Knoten haben, verfügen Sie über alle Informationen, die Sie benötigen.

2. Update:

Es spielt keine Rolle, ob Sie einen benutzerdefinierten oder einen generierten Parser verwenden. Es gibt einen bestimmten Punkt, an dem Sie beim Abgleichen einer Produktion einen Knoten zum Baum hinzufügen.Und es spielt keine Rolle, welche Sprache Sie verwenden.C-Strukturen reichen völlig aus.

Wenn es sich um ein Nicht -Terminal handeltein Token, dann die Informationen im Token, d. h.Lexeme -Wert, Token -Name und Zeilennummer werden gespeichert

Der Baum muss über spezielle Knoten verfügen, z. B.ClassNode, TypeNode, MethodDeclNode, IfStmtNode, ExprNode.Sie können nicht einfach einen Knotentyp speichern und darin Nicht-Terminals und Terminals einfügen.Ein Nicht-Terminal wird als Baumknoten dargestellt. Abgesehen von den Teilen, aus denen es besteht und die im Allgemeinen selbst Nicht-Terminals sind, können keine weiteren Informationen darüber gespeichert werden.Sie würden keine Token-Informationen speichern.Es gibt nur wenige Fälle, in denen Sie den Zeichenfolgewert eines Lexems tatsächlich speichern würden:für einen Bezeichner und für ein String-/Boolean-/Integer-Literal.

Schauen Sie mal rein Das Beispiel.Während der ersten Reduktion wann S reduziert wird auf (S + F), Sie hängen a an ParenExprNode bis zur Baumwurzel.Sie fügen außerdem a hinzu AddExprNode als Kind des ParenExprNode.Diese Logik muss in Ihrem Parser fest codiert sein, wenn Sie eine Reduktion durch Regel 2 der Grammatik anwenden.

Der Baum:

    ExprNode (root)
       |
  ParenExprNode
       |
   AddExprNode
   /         \
ExprNode   ExprNode

Der Code:

struct ExprNode { void* exprNode; };
struct ParenExprNode { void* exprNode; };
struct AddExprNode { void* op1, * op2; };
struct IdNode { char* val; int line; int charNum; };
struct IntLiteralNode { int val; int line; int charNum; };

void reduce_rule_2(ExprNode* expr) {

    //remove stack symbols

    //create nodes
    struct ParenExprNode* parenExpr = malloc(sizeof(struct ParenExprNode));
    struct AddExprNode* addExpr = malloc(sizeof(struct AddExprNode));
    addExpr->op1 = malloc(sizeof(struct ExprNode));
    addExpr->op2 = malloc(sizeof(struct ExprNode));

    //link them
    parenExpr->exprNode = (void*)addExpr;
    expr->exprNode = (void*)parenExpr;
}

Im nächsten Schritt wird die linke Klammer aus der Eingabe entfernt.Nachher, S liegt oben auf dem Stapel und wird reduziert auf F nach Regel 1.Seit F ist das Nichtterminal für einen Bezeichner, durch den er dargestellt wird IdNode.

Der Baum:

    ExprNode
       |
  ParenExprNode
       |
   AddExprNode
   /         \
ExprNode   ExprNode
   |
 IdNode

Der Code:

reduce_rule_2(addExpr->op1);

void reduce_rule_1(ExprNode* expr) {
    //reduce stack symbols
    struct IdNode* id = malloc(sizeof(struct IdNode));
    id->val = parser_matched_text();
    id->lineNum = parser_line_num();
    id->charNum = parser_char_num();
    expr->exprNode = (void*)id;
}

Und so weiter...

Andere Tipps

Alles, was ich kenne, ist der Lexeme-Wert und die Zeilennummer für diese bestimmte ID

das ist nicht wahr.Sie wissen, wo es in der Parse-Baum erklärt wird, was Ihnen alles sagt, was Sie brauchen.Sie machen diesen Schritt um -Verarbeitung den Parse-Baum.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top