私はコンパイラに興味があり、C++で基本的なものを書いてみました!コンパイラがソースコードを解析してトークンツリーを作成する方法を理解しています。私が理解できないことは、そのツリーがどのように評価され、必要であれば値を返すかということです。たとえば、ステートメント(a + b)がある場合、aとbを渡す+トークンを処理する関数がありますか?それは私が比較演算で同じことをするつもりです、そして、たとえ文であっても?コンパイラはどのように解析されたトークンツリーを評価しますか?
0
A
答えて
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
うわー、助けてくれてありがとう。その説明をありがとう。私は確かにこれについてもっと読んでいます。 –
関連する問題
- 1. JSコードがコンパイラによって解析/評価されないようにする方法は?
- 2. コンパイラは `typeid`演算子をどのように評価しますか?
- 3. オブジェクトリテラルのキーはどのように評価されますか?
- 4. Clojure - シンボルはどのように評価されますか?
- 5. 評価はどのようにして得られますか?
- 6. 解析された式の複素数の評価
- 7. テンソルフローサマリーオブジェクトで評価された `summary_str`バイト文字列の解析
- 8. コンパイラは常にゼロに評価されるブロックを削除しますか?
- 9. Angularはどのように式を評価しますか?
- 10. C#はどのようにLogicブロックを評価しますか?
- 11. JavaScriptはどのように引数を評価しますか?
- 12. これはどのように解析されますか?
- 13. 遅延評価はどのように機能しますか?
- 14. 次のphp正規表現はどのように評価されますか?
- 15. 次のコードはどのようにCで評価されますか?
- 16. Python - 次の式はどのように評価されますか?
- 17. このコード行はJava(Android)でどのように評価されますか?
- 18. SQLで「ビューの作成」はどのように評価されますか?
- 19. Javaの三項式はどのように評価されますか?
- 20. Facebookのデータインポートによって「今すぐ評価された値が今すぐ評価されました」
- 21. ドッカーイメージ名はどのように解析されますか?
- 22. git引数はどのように解析されますか?
- 23. DOMはどのように解析されますか?
- 24. djangoテンプレートはどのように解析されますか?
- 25. オープンソースプロジェクトホストをどのように評価しますか?
- 26. Pythonで微分をどのように評価しますか?
- 27. 評価実装をどのように構築しますか?
- 28. コンパイラはどのようにスコープを解決しますか?
- 29. 評価値はいつ評価されますか?
- 30. このクエリはどのように評価できますか?
"トークンツリー" ???あなたがしなければならないことは、コンパイラがどのように動作するかについての本を読むことです。この複雑な技術のための簡単で短い答えはありません。 –
理論的には、ソースをリテラル文字列演算子などのトークンコンポーネントに解析して、評価されるツリーにします。 –