2012-03-14 14 views
0

パーズツリーを作成したら、今すぐシンボルテーブルにデータを設定する必要があります。シンボルテーブル解析後の人口。コンパイルビルド

私は、識別子のなどをオフセット、

種類、適用範囲などの情報を保管する必要があります。

私は知っているので、その特定のID(語彙分析後)の語彙値と行番号が分かっているので、どのようにして識別子のタイプ、スコープを知っていますか?

どのように私はすべてのことについて知りましたか?ありがとう。

答えて

2

EJPが述べたように、構文解析ツリーをステップ実行する必要があります。ソースコードの文と式が評価されるのと同じ順序で各ノードにアクセスして、順序通りの探索を行うことができるように、ツリーが作成されているはずです。ツリーノードは特定の言語構造にも対応する必要があります。 WhileStmtNodeMethodDeclNodeなど

シンボルテーブルを構築していて、ツリーを繰り返し再帰的に進んで、メソッド本体ノードを入力したとします。私は次のようなものがあるかもしれません:

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

私はスコープを管理するためにグローバル変数を保持します。範囲が変わるブロックに入るたびに、私はインクリメントしますcurrScope。同様に、私はcurrClasscurrMethodの変数を後のフェーズのシンボル名、タイプ、オフセットなどと一緒に保存するようにします。

更新:

言って、私は木を横断していますが、毎回私 は、タイプと一緒に スコープなどをシンボルテーブルに値を入力する必要がありますIDに遭遇し、私が '{'か 関数名に遭遇したかどうかを調べるスコープについて言うが、どのようなIDのタイプがこれであるかをどのように知っていますか?

各ツリーノードには、構造全体に必要な情報がすべて含まれている必要があります。 CUPやBisonのようなパーサジェネレータを使用している場合は、文法アクションでツリーを構築する方法を指定できます。例えば。

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

これらプロダクションFoo f;と一致し、ツリーに変数宣言ノードを追加することになります。そのノードは、語彙の行番号、文字番号、および文字列値を含む2つの識別子ノードをカプセル化します。第1の識別子ノードはタイプであり、第2の識別子ノードは変数名である。 IDは、識別子が一致したときにレクサーによって返される端末記号です。私はあなたがこれにある程度親しんでいると仮定しています。

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; 
    } 

} 

このようなノードを持つ構文ツリーがあると、必要な情報がすべて得られます。

第二の更新:

カスタムパーサまたは生成されたものを使用しているかどうかは問題ではありません、あなたが生産に一致すると、ツリーにノードを追加する1つの異なる点があります。そして、あなたが使っている言語は問題ではありません。 Cの構造体はうまくいくでしょう。

それ以外の端末は、非終端記号名などの情報を持っており、それ トークンすなわち、端末、トークンすなわち語彙素価値のその後の情報であれば、 トークン名と行番号が格納されている場合

ツリーには特殊なノードが必要です(例: ClassNode、TypeNode、MethodDeclNode、IfStmtNode、ExprNode。 1つのタイプのノードを格納し、非端末と端末をそのノードに置くだけではいけません。非終端記号はツリーノードとして表現され、それを構成する部分の横にそれに関する情報を格納する情報はありません。一般に非終端記号です。トークン情報は保存しません。字句の文字列値を実際に格納するインスタンスはほんのわずかですが、識別子と文字列/ブール値/整数リテラルの場合があります。

thisの例をご覧ください。最初の削減中にS(S + F)に縮小された場合は、ParenExprNodeをツリールートに追加します。またParenExprNodeの子としてAddExprNodeを追加します。そのロジックは、文法のルール2による削減を適用するときにパーサーにハードコードされなければなりません。

ツリー:

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

コード:

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; 
} 

次のステップにおいて、左括弧が入力から除去されます。その後、Sがスタックの上にあり、ルール1によってFに縮小されます。Fは識別子の非終端記号であるため、IdNodeで表されます。

ツリー:

ExprNode 
     | 
    ParenExprNode 
     | 
    AddExprNode 
/  \ 
ExprNode ExprNode 
    | 
IdNode 

コード:

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; 
} 

のように...処理による

+0

私はCを使用しています。parsetreeのノードには情報lexemeの値があり、トークンNAmeの場合は/ IFまたは名前/ IDまたは12/INTEGERです。私はIDを渡って来るたびに、私はツリーを横断していると言うと、タイプ、スコープなどとともにシンボルテーブルに値を入力する必要があります。スコープについては、 '{'または関数名、しかし、どのようなIDのタイプがこれなのかは分かりません。 – Kraken

+0

@Kraken:木を正しく作っていないように思えます。更新を参照してください。 – blackcompe

+0

今まで私がやったことはすべてあなたに連れて行きましょう。 1.字句解析:字句を適切にトークン化し、ソースコードのパス中に収集されたすべての情報(すなわち、語彙値、tokeName、lineno)を維持します。 2.構文解析:予測構文解析(構文解析テーブルを使用)が使用され、文法規則は配列ルールとして維持され、配列の各エントリはリンクリストであり、各ルールを維持します。同様に、最初のセットとフォローセットが維持されます。今、私はシンボルを開始してスタックを維持し、字句アナライザによって生成されたトークンリストから次のトークンをチェックしてください。(coninued).. – Kraken

0

私が知っているすべては真実ではない、特定のID

のための語彙素の値と行番号です。解析ツリーでどこが宣言されているかを知っています。これは必要なものすべてを示します。この手順は、の処理ツリーで行います。今私が知っている すべてが( 字句解析後)は、その特定のIDのための語彙素の値と行番号であるため、どのように私は、タイプ、識別子の範囲を知っていますか

+0

あなたは属性文法(継承属性)を作成し、意味ですか[私はちょうど来ましたしたがって、私は完全に間違っている可能性があります。スコープについては、かっこの新しいペアが出現したか、新しい関数が存在するかどうかを確認することができます。 – Kraken

+0

@Krakenはい、それは私の言いたいことです。字句と行番号だけでシンボルを処理することはありません。 – EJP

関連する問題