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

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. 解决yii2.0里url重写引用js路径问题(@web/的用法)

    在实际项目中,为了seo优化,使用了伪静态,开启了url重写

  2. lua之m进制转换为n进制-任意进制转换算法

    够无聊的写这个,为防止需要的人也无聊一遍,写个吧 算法有n种,但是,咱们一种就够用了 --数组倒序排列 local function orderByDesc( input ) local output ...

  3. React v15.5.0更新说明 & v16.0.0更新预告

    React今日发布了15.5.0版本,同时这也将是以15开头的最后一个版本,下一次发布,我们将迎来React 16.0.0 在15.5.0这一版本中,主要有以下两处改动: 独立React.PropTy ...

  4. UML用例图间关系说明

    用例间一般存在如下四种关系: 1."通信"关系(<<cmmunicate>>构造型): "通信"关系:使用实心的关联线或带<< ...

  5. MySQL语法一:数据定义语句

    MySQL语句语法主要分为以下三大类: 一.数据定义语句DDL(CREATE,ALTER,DROP,DECLARE) 数据定义语句是用于修改表结构的. 一).语法提炼: 二).由上图可知,数据定义语句 ...

  6. BZOJ2346:[Baltic 2011]Lamp(最短路)

    Description 2255是一个傻X,他连自己家灯不亮了都不知道. 某天TZ大神路过他家,发现了这一情况, 于是TZ开始行侠仗义了. TZ发现是电路板的问题, 他打开了电路板,发现线路根本没有连 ...

  7. BZOJ2333:[SCOI2011]棘手的操作(Splay)

    Description 有N个节点,标号从1到N,这N个节点一开始相互不连通.第i个节点的初始权值为a[i],接下来有如下一些操作: U x y: 加一条边,连接第x个节点和第y个节点 A1 x v: ...

  8. zip 函数

    zip 函数,看上去是打包的意思,其实功能是将多个可迭代对象,组合成一个个元组. zip(iter1,iter2) a,b = zip(*zip(iter1,iter2)) a = [1,2,3] b ...

  9. 【模板】Splay总结

    rentenglong大佬写的splay的梳理使我受益颇丰,特此做出一定的总结. 数据结构 定义了一个struct结构体. 为了在splay操作下储存根节点,我们宏定义了root 为 tree[0]. ...

  10. C# Hadoop学习笔记(七)—C#的云计算框架借鉴(下)

    转自:http://blog.csdn.net/black0707/article/details/12853049 在上篇里,我们主要讨论了,这个系统怎样处理大数据的“读”操作,当然还有一些细节没有 ...