- 浏览: 58969 次
- 性别:
- 来自: 武汉
最新评论
-
NeuronR:
之前自搭 blog, 太累. 最近在研究 C艹 语言的错误处理 ...
C++ 中处理除零错误 -
lwwin:
话说很久没有看到你更新BLOG了,最近在研究LINUX开发^^ ...
C++ 中处理除零错误 -
lwwin:
RednaxelaFX 写道我的见识还是太少了……最近在某在x ...
[优化]删去 NOP 指令 -
RednaxelaFX:
我的见识还是太少了……最近在某在x86上跑的东西的手写汇编里的 ...
[优化]删去 NOP 指令 -
NeuronR:
lwwin 写道没想到一个NOP把FX也拉来了^^关于代码…… ...
[优化]删去 NOP 指令
文章列表
这里要说的指令,并不是x86体系结构下的机器指令,而是虚拟机指令。Jerry虚拟机的设计并不是非常复杂——甚至看起来很不灵活——它是一个栈式虚拟机,不包括任何寄存器(除了指令计数器之外),所有的指令都是基于 ...
- 2009-07-11 20:51
- 浏览 1166
- 评论(3)
上一次修改AbstractValueNode
时添加了一个typeOf
成员函数,这个函数用来在编译时确定AbstractValueNode
的类型。相对于确定编译时值,确定类型要简单一些。
对于IntegerNode
和RealNode
,它们的成员函数实现依然是很简单的
AcceptType typeOfInt(void* node)
{
return INTEGER;
}
AcceptType typeOfReal(void* node)
{
return REAL;
}
而确定变量的类型,well,我们在符号表管理器中已经 ...
- 2009-06-17 15:44
- 浏览 958
- 评论(0)
上一次构建语法树相关的节点,是在语法分析刚刚开始的时候,这一次又需要对它们动一动手脚,加入一些语义分析需要的成员函数。
这一次添加的主要是针对AbstractValueNode
及其子类(以后还会讨论关于指令生成相关的函数),现在需要把它变成这个样子
#define memberAbstractValueNode \
memberAbstractSyntaxNode \
int (*staticInt)(void*, int*); \
int (*staticReal)(void*, double*); ...
- 2009-06-05 16:07
- 浏览 1023
- 评论(2)
符号表系统看起来还算是比较好用,不过为了方便起见,现在在它之上再加一层套。考虑到日后一些类型的语法节点,如VariableNode
以及DeclarationNode
,它们直接与符号表打交道的话,就会出现这样的问题:一方面它们要执 ...
- 2009-05-21 15:40
- 浏览 956
- 评论(3)
符号表的实现方法可以多种多样,只要通过了测试基本上就没啥问题了。在这里给出一个参考实现。
首先是符号表相关的结构体,这东西最好放到 datastruct.h 中
/* 变量单元,存放符号表中注册的变量信息 */
struct VarCell {
char* ident; // 标识符
int addr; // 基地址
AcceptType type; // 类型
int nrDim; // 维数
int* dims; // 每一维偏移
};
...
- 2009-04-28 09:31
- 浏览 1192
- 评论(3)
之前在词法和语法分析部分都有测试,不过那些测试显得很小打小闹,而且比较麻烦。好在那都是不复杂的东西,测试负担较小。而符号表这东西是语义分析需要用到的基础结构,如果等到最后进行集成测试,出了bug还真不好找。所以这东西有必要单独拿来测试一下。不过C语言的测试驱动开发工具还真是难找,这里就山寨一个先。
测试数据这里简单给出4组
// 测试数据数目
#define NR_TEST_CASE (4)
// 测试数据的基地址
#define BASE_ADDR (1 << 3)
// 待测试的符号表指针
struct SymbolTable* table;
...
- 2009-04-19 20:33
- 浏览 891
- 评论(0)
进入语义分析的首要任务是组织和管理变量符号。这一点有多种选择,一种是类C/C++语言那样的静态处理,即将变量映射为地址,运行时内存中根据地址取得变量值,这样运行效率无论是从内存使用量和访问速度上都会较高 ...
- 2009-04-12 23:23
- 浏览 1579
- 评论(4)
附件中包含了到目前为止的所有文件,除了COOL目录之外。
语法分析的功能基本上成熟了,调试也完成了,现在剩下将这些东西整合起来成为一个没有调试输出(特别是内存分配调试)的整体了。首先要做的事情是,把COOL中 ...
- 2009-03-28 10:51
- 浏览 946
- 评论(0)
当一个分析器A调用另一个分析器B时,如果称A处于B的“外层”,那么除开测试文件中产生的那个FakeDefaultAnalyser之外,LR分析器是整个语法分析结构中最外层的语法分析器。因此当其它分析器有无法处理的错误时,这些烂摊子都得它来收拾。比如变量分析中可能有冗余的反方括号,表达式分析中可能有冗余的反圆括号,等等,甚至包括其它的LR分析器也有可能把错误扔给更外层的LR分析器。这样一来,LR分析器中至少得对付这样一些错误
static ErrMsg excessiveRParent = "Excessive close parenthese.",
...
- 2009-03-15 21:49
- 浏览 1464
- 评论(0)
变量分析器本身很简单,它的错误处理不需要弄得太复杂,只对正反方括号做做验证,其它的丢给表达式分析器或者LR分析器去弄就行了。(下面一段话中的括号均指方括号。)
大致的构想是这样的:当需要反括号时 ...
- 2009-03-07 16:42
- 浏览 913
- 评论(2)
由于语法分析模块由多个不同的分析器协同完成,当一个分析器中发现语法错误,或者仅仅是该识别的非终结符识别完成,即将返回时,该分析器会将从这里开始的终结符都扔给委托它的分析器去处理。这会导致一个问题,那就是错误会从当前分析器扩散到调用栈中的其它分析器。比如输入:
if ( x == 1 2 ) { // other codes ...
在没有任何保护措施的情况下,表达式分析器遇到“2”时,会认为表达式识别结束,然后返回一个表达式节点,表征
x == 1
然后将“2”传入LR分析器。接着LR分析器一看也傻眼了,怎么来了个数字,于是也开始报错。而这一切的根源也许仅仅是因为多键入了 ...
- 2009-03-02 11:38
- 浏览 913
- 评论(3)
变量这玩意儿本身很简单,无非是一个标识符开头,然后若干对中间夹着一个算数运算的正反方括号,而分析算术运算节点的任务又可以委托给专门的分析器来做,因此识别变量的分析器本身其实没什么需要做的。下面是它的数据结构。
struct VariableAnalyser {
memberSyntaxAnalyser
struct VariableNode* var; // 用来存放识别的变量
};
下面是它的各成员函数的实现,这里用了一种有趣的实现方式。
/* variable-analyser.c */
#include<stdlib.h>
#include"da ...
- 2009-02-21 11:13
- 浏览 979
- 评论(2)
LR分析器的consumeNonTerminal函数在上一节提到过,其实跟Goto表没有关系:如果在分析器内部规约得到一个非终结符,那么规约函数执行结束之后,马上就会根据传入宏的“leftPart”在Goto表中查找对应的目标状态并压栈,而根本 ...
- 2009-02-15 10:04
- 浏览 1825
- 评论(3)
Action表中还有一小部分没有填完,就是LR分析器委托其他分析器识别非终结符的那一部分。其中包括在变量定义时委托VariableAnalyser识别变量,在识别循环条件或赋值语句等状态中委托OperationAnalyser识别运算式,以及在识别正反花括号内部的基本块时委托一个新的LRAnalyser去识别它。这些Action也可以用宏来实现,大家应该已经轻车熟路,这里就不多说了,直接看代码吧
#define switchAnalyser(current, encounter, analyser) \
static void linkName( ...
- 2009-02-12 15:21
- 浏览 1231
- 评论(2)
对于LR分析而言,规约状态可以从这个角度分为两类,一类是“纯”的规约状态,也就是分析预测表中某个状态Action表一行全部是规约行为,如Jerry语言的状态WhileLoop_5,这个状态无论遇到什么符号都会规约一个while循环到一个语句;另外一种就是有移进-规约冲突的状态。从实现的角度来看,这两种状态的实现可以完全不同:对于前一种情况,一旦步入该状态,就规约,然后根据规约后得到的非终结符Goto;而后一种情况则要等到下一符号输入之后再确认应规约(注:这里的实现并没有符号类型判断这一过程,而是根据符号类型查找分析预测表获取Action函数入口地址,因此在规约函数内部会直接进行规约)。
...
- 2009-02-09 10:53
- 浏览 1935
- 评论(2)