1. 程式人生 > >使用bison和yacc制作腳本語言(4)

使用bison和yacc制作腳本語言(4)

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)