zoukankan      html  css  js  c++  java
  • 使用bison和yacc制作脚本语言(4)

    我们现在开始设计数据结构:

    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{},最后形成抽象语法树把各个表达式连接起来

    如果我们不给$$赋值,那么将会把$1压入栈

    %union {
        char                *identifier;
        Expression          *expression;
        int integer;
        double db;
        Statement*statement;
        Statement_list*statement_list;
        Function_t*function;
        ParamList*paramlist;
    }
    

    这个联合体声明就是终结符和非终结符的类型

    终结符和非终结符类型可以选择声明

    %token表示终结符,%type表示非终结符

    %token <integer> INT_LITERAL
    %type <statement_list> block statement_list
    

    语句最后会被规约单个语句

    代码已经上传至github地址:https://github.com/stdpain/compiler-interpreter

    可以看一下create.c 和 ms.y

  • 相关阅读:
    ちょっとした難しい言葉まとめ10
    ちょっとした難しい言葉まとめ9
    ちょっとした難しい言葉まとめ8
    ページの先頭へジャンプするボタンを作るには?
    Interaction with the camera or the photo library
    ナビゲーションバー
    javascript 小计
    爬mei紫图最后代码2015-2019-1-14全部
    备份
    爬mei紫图
  • 原文地址:https://www.cnblogs.com/stdpain/p/10529368.html
Copyright © 2011-2022 走看看