最近對編譯原理比較感興趣,到底一門語言它有什麼門道,爲了一探究竟就買了本《自制編程語言》,希望把自己一點理解記錄下來。
再說都是廢話了,進入正題。下面是crowbar 主要代碼。
#include <stdio.h>
#include "CRB.h"
#include "MEM.h"
int
main(int argc, char **argv)
{
CRB_Interpreter *interpreter;
FILE *fp;
if (argc != 2) {
fprintf(stderr, "usage:%s filename", argv[0]);
exit(1);
}
fp = fopen(argv[1], "r");
if (fp == NULL) {
fprintf(stderr, "%s not found.\n", argv[1]);
exit(1);
}
/*生成解釋器*/
interpreter = CRB_create_interpreter();
/*將FILE*作爲參數傳遞,並生成分析樹*/
CRB_compile(interpreter, fp);
/*運行*/
CRB_interpret(interpreter);
/*運行完畢後回收解釋器*/
CRB_dispose_interpreter(interpreter);
MEM_dump_blocks(stdout);
return 0;
}
此代碼最核心就是CRB_Interpreter這個數據結構,這些函數都是圍繞它進行的。下面看下這個結構體各個成員變量。
//此代碼在CRB.h,使用不完全類型,向外界屏蔽此結構體的細節。
typedef struct CRB_Interpreter_tag CRB_Interpreter;
//此代碼在Crowbar.h,各個成員書上說的很詳細。
struct CRB_Interpreter_tag {
MEM_Storage interpreter_storage;
MEM_Storage execute_storage;
Variable *variable;
FunctionDefinition *function_list;
StatementList *statement_list;
int current_line_number;
};
上面main的代碼流程,也是解釋器的主要原理:
1.生成這個結構體。
2.分析這個用這個語言寫的代碼源文件,也就是對CRB_Interpreter_tag結構體各個成員變量賦值,主要是生成StatementList這個語句鏈表。
3.順序執行這個CRB_Interpreter_tag結構的StatementList
4.釋放內存。
下面來看下這個解釋器具體執行時的變化
生成結構體之前
生成之後爲
上面綠色表示已更改
我讓解釋器執行的是這倆個語句
a=4*10;
print(a);
下面該執行CRB_compile這個函數,預期StatementList有兩個。下面就去看一下吧。
OK,一目瞭然。現在可以說一個如何寫一個解釋器就是如何構造這樣一個結構體,以及如何對他們的成員填充的。當然這個結構體源碼作者已經設計出來了,以後重點是看如何對這個結構體填充。