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

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

使用bison和yacc制作脚本语言(4)的更多相关文章

  1. 使用bison和yacc制作脚本语言(1)

    使用bison和yacc制作脚本语言(1) 环境: 环境 windows 10 Cygwin64 语言 C 工具 mingw bison flex 主要是使用bison和flex这两个软件,编译器无所 ...

  2. 使用bison和yacc制作脚本语言(2)

    我们先来想一下语法 一般脚本语言不需要定义类型直接在赋值的时候确定 我们主要考虑一下变量的类型 a = 1; b = 1.1; c = "str"; 一般来讲,我们使用这三种类型, ...

  3. 使用bison和yacc制作脚本语言(3)

    我们现在已经可以写好文法了,下一步我们打算开始正式创建工程了 在工程目录下,我们创建如下文件夹 ./include ./memory ./ms include文件夹下我们将放头文件 memory是内存 ...

  4. [Java面试九]脚本语言知识总结.

    核心内容概述 1.JavaScript加强,涉及到ECMAScript语法.BOM对象.DOM对象以及事件. 2.Ajax传统编程. 3.jQuery框架,九种选择器为核心学习内容 4.JQuery ...

  5. Perl,Python,Ruby,Javascript 四种脚本语言比较

    Perl 为了选择一个合适的脚本语言学习,今天查了不少有关Perl,Python,Ruby,Javascript的东西,可是发现各大阵营的人都在吹捧自己喜欢的语言,不过最没有争议的应该是Javascr ...

  6. JAVA平台上的网络爬虫脚本语言 CrawlScript

    JAVA平台上的网络爬虫脚本语言 CrawlScript 网络爬虫即自动获取网页信息的一种程序,有很多JAVA.C++的网络爬虫类库,但是在这些类库的基础上开发十分繁琐,需要大量的代码才可以完成一 个 ...

  7. Shell简介:1分钟理解什么是Shell 脚本语言 解释器 以及编译器和编译语言

    Shell简介:1分钟理解什么是Shell 脚本语言 解释器 以及编译器和编译语言 现在我们使用的操作系统(Windows.Mac OS.Android.iOS 等)都是带图形界面的,简单直观,容易上 ...

  8. PCB 规则引擎之脚本语言JavaScript应用评测

    世界上没有好做的软件,觉得好做,只是你的系统简单而已,而不是哪个行业简单,特别像我们PCB制造企业务逻辑的很复杂的,仅仅靠决策树中的每个节点布置决策逻辑是不能满足要求的,所以我们在制作PCB规则引擎必 ...

  9. Procomm Plus 与ASPECT脚本语言在基于远程终端设备上的测试应用

    产测 ---------------------------------------------------- 原文:http://www.bixuanzl.com/20180801/1084478. ...

随机推荐

  1. db2巡检小脚本

    写了下db2巡检的一个小脚本,只能做常规检查,减少日常工作量,脚本内容如下: #!/bash/bin echo "物理CPU个数为:"cat /proc/cpuinfo| grep ...

  2. 取多个name值相同的input里面的值

    html 中是允许多个具有相同name属性的元素的,例如服务器端读取的常规做法是: string name = Request.Params["txtName"]; 得到的将是一串 ...

  3. 搞定INTEL快速存储技术(用SSD硬盘做缓存加速)

    给朋友买了个联想 ideapad s400超级本,还真是锻炼我的idea啊,原机不带WIN7系统,所以只好自己动手装WIN7,并打开24G SSD硬盘做缓存. 一.用常规方法GHOST了一个WIN7系 ...

  4. [原]零基础学习视频解码之FFMpeg中比较重要的函数以及数据结构

    在正式开始解码练习前先了解下关于FFmpeg中比较重要的函数以及数据结构. 1. 数据结构:  (1) AVFormatContext  AVFormatContext是一个贯穿始终的数据结构,很多函 ...

  5. SpringMVC错误小结

    No mapping found for HTTP request with URI [/SpringMVC/user.do] in DispatcherServlet with name 'spri ...

  6. 【JQ】鼠标经过一组button,弹出各自的气泡图片

    HTML <div id="bubble1" class="bubble"><img src="../image/p_bubble1 ...

  7. 2019.1.3 Mac安装免费版StarUml3.0.2 &&&Xmind思维导图 &&Google浏览器***版

    下载StarUml http://staruml.io/ 好像需要FQ 附赠一个 链接:https://pan.baidu.com/s/1_pa9LwopowhOTum5g89zZQ 密码:fxtc ...

  8. linq 和lamba表达式

    一.什么是Linq(what)二.Linq的优点(why)三.Linq查询的步骤(how)四.查询基本操作五.結合實例代碼(具體聯繫用linqtosql來寫的增刪改查)一.什么是Linq(what). ...

  9. leetcode 78. Subsets 、90. Subsets II

    第一题是输入数组的数值不相同,第二题是输入数组的数值有相同的值,第二题在第一题的基础上需要过滤掉那些相同的数值. level代表的是需要进行选择的数值的位置. 78. Subsets 错误解法: cl ...

  10. Git如何从github上pull别人的项目

    1:使用git方式导入项目 菜单-File->import->Git->Projects from Git 2:选择某个服务器上的资源 3:选择需要pull的地址 后面需要自己加上 ...