使用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
使用bison和yacc制作脚本语言(4)的更多相关文章
- 使用bison和yacc制作脚本语言(1)
使用bison和yacc制作脚本语言(1) 环境: 环境 windows 10 Cygwin64 语言 C 工具 mingw bison flex 主要是使用bison和flex这两个软件,编译器无所 ...
- 使用bison和yacc制作脚本语言(2)
我们先来想一下语法 一般脚本语言不需要定义类型直接在赋值的时候确定 我们主要考虑一下变量的类型 a = 1; b = 1.1; c = "str"; 一般来讲,我们使用这三种类型, ...
- 使用bison和yacc制作脚本语言(3)
我们现在已经可以写好文法了,下一步我们打算开始正式创建工程了 在工程目录下,我们创建如下文件夹 ./include ./memory ./ms include文件夹下我们将放头文件 memory是内存 ...
- [Java面试九]脚本语言知识总结.
核心内容概述 1.JavaScript加强,涉及到ECMAScript语法.BOM对象.DOM对象以及事件. 2.Ajax传统编程. 3.jQuery框架,九种选择器为核心学习内容 4.JQuery ...
- Perl,Python,Ruby,Javascript 四种脚本语言比较
Perl 为了选择一个合适的脚本语言学习,今天查了不少有关Perl,Python,Ruby,Javascript的东西,可是发现各大阵营的人都在吹捧自己喜欢的语言,不过最没有争议的应该是Javascr ...
- JAVA平台上的网络爬虫脚本语言 CrawlScript
JAVA平台上的网络爬虫脚本语言 CrawlScript 网络爬虫即自动获取网页信息的一种程序,有很多JAVA.C++的网络爬虫类库,但是在这些类库的基础上开发十分繁琐,需要大量的代码才可以完成一 个 ...
- Shell简介:1分钟理解什么是Shell 脚本语言 解释器 以及编译器和编译语言
Shell简介:1分钟理解什么是Shell 脚本语言 解释器 以及编译器和编译语言 现在我们使用的操作系统(Windows.Mac OS.Android.iOS 等)都是带图形界面的,简单直观,容易上 ...
- PCB 规则引擎之脚本语言JavaScript应用评测
世界上没有好做的软件,觉得好做,只是你的系统简单而已,而不是哪个行业简单,特别像我们PCB制造企业务逻辑的很复杂的,仅仅靠决策树中的每个节点布置决策逻辑是不能满足要求的,所以我们在制作PCB规则引擎必 ...
- Procomm Plus 与ASPECT脚本语言在基于远程终端设备上的测试应用
产测 ---------------------------------------------------- 原文:http://www.bixuanzl.com/20180801/1084478. ...
随机推荐
- GetDIBits 提示堆栈损坏的解决办法
...... BITMAPINFOHEADER bi; bi.biSize = sizeof(BITMAPINFOHEADER); bi.biWidth = bmpScreen.bmWidth; bi ...
- js函数 标签: javascript 2016-08-12 16:48 56人阅读 评论(0) 收藏
函数实际上是对象,函数名实际上也是一个指向函数对象的指针. 使用不带圆括号的函数名是访问函数指针,而非调用函数. 函数声明和函数表达式: alert(test(2,3)); function test ...
- gtest学习
介绍 学习如下gtest课程,总结主要的部分 1.玩转Google开源C++单元测试框架Google Test系列(gtest)之一 - 初识gtest 2.玩转Google开源C++单元测试框架Go ...
- 双十一问题:kafka消费能力低下原因思考
抛去cpu.内存等机器原因,在每个分区皆分配一个进程消费的情况下,利用扩机器来提高kafka消费速率已无能为力 此时发现,在实际洪峰时段的消费速率元达不到先前压测时的消费速率 原因思考: 1.洪峰时段 ...
- ANT table表格合并
1. 合并前提 后台返回数据必须是:相同重复的数据必须是连在一起的,这样前台才能通过rowspan方法合并表格数据.(这是前提,后台需要注意) 2.步骤 1.前台需要根据后台返回的数据内容, ...
- 天地图,js 4.0 api,简单调用,高手请绕行
本文介绍使用天地图 js4.0 api,实现地图显示后台gps分布情况: 主要借用H5 GPS获取,利用天地图的背景展示: 效果图如下: 第一步,通过采集网页,手机gps数据,录入后台数据库:界面如下 ...
- dia无法输入中文的解决
安装dia后无法输入中文,解决如下: 修改/usr/bin/dia #dia-normal --integrated "$@" dia-normal "$@"
- 总结一下MVC思想
MVC (Model View Controler)本来是存在于Desktop程序中的,M是指数据模型,V是指用户界面,C则是控制器.使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用 ...
- 解决FileUpload上传大文件报错
<system.webServer> <security> <requestFiltering> <requestLimits maxAllowedConte ...
- 【洛谷P1373】小a和uim之大逃离
小a和uim之大逃离 题目链接 因为每次只能向下或向右走,我们可以递推 dp[i][j][d][0/1]表示走到(i,j),mod k 意义下差值为d,轮到小a/小uim操作时的方案数 dp[i][j ...