使用bison和yacc制作腳本語言(4)
阿新 • • 發佈:2019-03-14
eva tor primary github iso left n) 枚舉 ron
我們現在開始設計數據結構:
interpreter.h
#ifndef INTERPRETER #define INTERPRETER #include "../include/eval.h" typedef struct interpreter_tag Interpreter; struct interpreter_tag { MEM_Storage storage;//存儲器 MEM_Storage charpool; Statement_list *list;//語句表 Function_t *functionlist;//函數表 Environment globalEnvironment;//全局變量存放的位置 }; Interpreter *getInterpreterInstance(); void *Interpreter_malloc(int size);//使用存儲器分配內存 char *Interpreter_str_malloc(char *str);//分配字符串 #endif
Interpreter就是解釋器的結構體,存放一些全局信息,在需要的時候可以通過getInstance獲取實例
我們的解釋器執行的時候是先使用yylex
構建抽象語法樹(AST
),然後再解釋執行
我們先來看一下語句的結構體:
struct Statement_tag
{
enum StatementType type;
union {
ExpressionStatement *e;//表達式語句
For_Statement *f;//for語句
If_Statement *i;//if 語句
} u;
};
我們把表達式語句,if和for語句放在一個聯合體中,通過type來區分不同的聯合體,比直接使用void*更方便
表達式語句中存放一個表達式
struct Expression_Statement_tag
{
Expression *expression;
};
表達式也和語句一樣,使用type來區分指針
struct Expression_tag { enum Expression_type type; Expression_u u; }; union Expression_uni { PrimaryExpression *p;//這個主要跟文法中primary_expresison對應 Binary_Expression *b;//主要跟二元操作對應,比如add sub mul div eq ne Assign_Expression *a;//賦值表達式 Expression *e;//表達式指針 FuncCallExpression *func;//函數表達式 };
我們先來看primaryexpression
結構體,裏面同理裏使用枚舉來確定聯合體裏面保存的變量類型
struct PrimaryExpression_tag
{
enum ValueType type;
union {
int i;
double d;
// char *str;
MString*mstring;
char *identifier;
} u;
};
註意其中mstring是由引用計數管理的字符串指針
Expression *create_IntergerExpression(int i);//創建一個整數表達式
Expression *create_DoubleExpression(double i);//創建一個浮點數表達式
Expression *create_StrExpression(char *p);//創建一個字符串表達式
Expression *create_IDExpression(char *p);//創建一個identitier表達式
Binary_Expression *createBinaryExpression(enum ExpressionAction action, Expression *left, Expression *right);//二元表達式
Assign_Expression *createAssignExpression(char *c, Expression *expression);//賦值表達式
Expression *binExpressionWarpper(Binary_Expression *expression);//二元表達式包裝為Expression
Expression *AssignExpressionWarpper(Assign_Expression *expression);//賦值
Expression *create_FuncCallExpression(char *identifier, ParamList *params);//創建函數
這些函數是各個表達式創建函數我們可以在bison語法文件 m.y中使用這些函數
這裏拿 primaryexpression
舉例
primary_expression:SUB primary_expression
{
$$=$2;
}
|LP expression RP
{
$$=$2;
}
|IDENTIFIER
{
$$=create_IDExpression($1);
}
|STRING_LITERAL
{
$$=create_StrExpression($1);
}
|INT_LITERAL
{
$$=create_IntergerExpression($1);
}
|DOUBLE_LITERAL
{
$$=create_DoubleExpression($1);
}
|IDENTIFIER LP RP
{
$$=create_FuncCallExpression($1,NULL);
}
|IDENTIFIER LP arglist RP
{
$$=create_FuncCallExpression($1,$3);
}
;
$$
代表是將會壓入棧中的變量,$n是代表當前參與規約的第n個元素,比如IDENTIFIER LP arglist RP
中$1代表IDENTIFIER
,$3代表arglist
當使執行規約的時候會自動執行action{}
,最後形成抽象語法樹把各個表達式連接起來
代碼已經上傳至github
地址:https://github.com/stdpain/compiler-interpreter
可以看一下create.c 和 ms.y
使用bison和yacc制作腳本語言(4)