2016-04-19 15 views
0

私はコンパイラに興味があり、C++で基本的なものを書いてみました!コンパイラがソースコードを解析してトークンツリーを作成する方法を理解しています。私が理解できないことは、そのツリーがどのように評価され、必要であれば値を返すかということです。たとえば、ステートメント(a + b)がある場合、aとbを渡す+トークンを処理する関数がありますか?それは私が比較演算で同じことをするつもりです、そして、たとえ文であっても?コンパイラはどのように解析されたトークンツリーを評価しますか?

+0

"トークンツリー" ???あなたがしなければならないことは、コンパイラがどのように動作するかについての本を読むことです。この複雑な技術のための簡単で短い答えはありません。 –

+0

理論的には、ソースをリテラル文字列演算子などのトークンコンポーネントに解析して、評価されるツリーにします。 –

答えて

1

コンパイラはASTを評価しません。それは(単純な)インタプリタが行うことです。コンパイラはASTからコードを生成します。

簡単な整数のみのASTは、ASTノードは、ノードと子ノードの配列のタイプを伝える列挙型で構成されていることを仮定して、このようなものに見えるかもしれません評価:

int eval_expression(node) { 
    switch(node.type) { 
    case ADD: 
    return eval_expression(node.children[0]) + eval_expression(node.children[1]); 
    case IF: 
    if(eval_expression(node.children[0])) { 
     return eval_expression(node.children[1]); 
    } else { 
     return eval_expression(node.children[2]); 
    } 
    // and so on 
    } 
} 

あなたの言語に応じて、とあなたがASTをどのように表しているか、これは大きく異なって見えるかもしれませんが、うまくいけば、これはあなたにアイデアを与えます。 (非常に単純な)コンパイラが行う可能性がありますどのような

は、より次のようになります。

void compile_expression(Node node, const char* target_register) { 
    switch(node.type) { 
    case ADD: 
    const char* temp_register = find_unused_register(); 
    compile_expression(node.children[0], target_register); 
    compile_expression(node.children[1], temp_register); 
    printf("ADD %s %s\n", target_register, temp_register); 
    free_register(temp_register); 
    case IF: 
    const char* condition_register = find_unused_register(); 
    compile_expression(node.children[0], condition_register); 
    const char* elseLabel = generate_label(); 
    const char* labelAfterIf = generate_label(); 

    // If the condition was zero, jump to the else case 
    printf("JZ %s %s\n", condition_register, elseLabel); 
    compile_expression(node.children[1], target_register); 
    printf("JUMP %s\n", labelAfterIf); 

    printf("%s:\n", elseLabel); 
    compile_expression(node.children[2], target_register); 

    printf("%s:\n", labelAfterIf); 
    free_register(temp_register); 
    // and so on 
    } 
} 

上記のコードではなく、かなり本当のコンパイラは何をするのかである、stdoutに直接アセンブリコードを書き込みます。それはまた、悪い工学的実践に満ちており、むしろ単純化されたアセンブリ方言を目標としています。うまくいけば、それはアイデアを得るが、実世界のコンパイラはASTから直接アセンブリ(またはマシンコード)を生成しません、また通訳が直接ASTを評価することを


は注意してください。代わりに、どちらも最初にASTから中間コード(3アドレスコードのような)の何らかの形式を生成し、さらにそれを使用します。

+0

うわー、助けてくれてありがとう。その説明をありがとう。私は確かにこれについてもっと読んでいます。 –

関連する問題