自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(43)
  • 收藏
  • 关注

这里可(不)能抛出异常

     先来回顾上一篇开头处的一段代码的结尾处EXIT_FREE_BUFFER: free(buffer);EXIT_CLOSE_DST: fclose(dstf);EXIT_CLOSE_SRC: fclose(srcf); return ret;    有一个问题是, 当有错误发生时 (ret 为非零值) 如果同时 free, fcl...

2010-11-21 16:48:50 122

错误码与异常

    C++ 标准库中的异常是标准库的一个组成部分, 但异常并不是 STL 的一部分, 所以下面这些内容里面不会展现任何关于泛型乃至模板相关可能令人不适的内容.    那, 先在 C 身上找点错误处理相关的乐子.使用返回码进行错误处理    上篇文章聊的是一个非常具体的异常处理, 而在这个环境中, 使用异常是不得已的事情. 在 C 语言单调的世界里, 异常还是不存在的, 大家都非常和...

2010-11-09 10:37:54 298

原创 C++ 中处理除零错误

转自 http://blog.bitfoc.us/?p=100     继承自 C 的"优良"传统, C++ 也是一门非常靠近底层的语言, 可是实在是太靠近了, 很多问题语言本身没有提供解决方案, 可执行代码贴近机器, 运行时没有虚拟机来反馈错误, 跑着跑着就毫无征兆地崩溃了, 简直比过山车还刺激.    虽然 C++ 加入了异常机制来处理很多运行时错误, 但是异常机制的功效非常受限,...

2010-10-30 22:56:47 3991

[优化]删去 NOP 指令

在控制语句的指令生成过程中, 语句无法知道外界指令结构, 不能贸然将跳出语句定向到外部指令, 因此使用了 NOP 指令缓冲了这些跳转. 然而, 在全部指令生成结束后, 跳转指令就可以根据上下文选择正确的目标了, 那么 NOP 指令只是影响性能的冗余指令了. 本着兔死狗烹的原则, 现在去掉这些指令.static void cleanNop(struct List* instruction...

2009-12-21 15:38:49 613

[开发过程]分支/循环/零零散散的测试

svn update 先.测试约定在 test 目录下, 有一坨 test-X.jerry 和 test-X.expect 文件, X=0, 1, 2, 3. 前者是 Jerry 源文件, 而 .expect 文件的则是, 当这个源文件被编译并执行以后应该输出的结果 (确实, 这些例子中没有对输入的测试).test 目录下还有一个 c 源文件 result-verify.c, 它独立编...

2009-12-10 21:05:03 90

[虚拟机]运行时数据组织

虚拟机 虚拟机的实现包含三个文件 jerry-vm.c 环境配置, 参数分析和 I/O 设定. main 函数在这个文件中 vm.h 类型定义, 以及全局变量的声明. vm.c 指令的实现这些文件编译链接后产生 JerryVM.out 可执行文件. 它的命令行参数之一是 Jerry 字节码. 它将读入指令然后执行它们.双帧栈 所谓的双帧栈就...

2009-11-25 21:16:06 87

[虚拟机]指令写出

是的, 还有几个节点的指令生成没有测试呢, 包括流控制语句, IO. 不过呢, 流控制是相对比较容易优化的, 进行"生成指令再对比"的测试不太好维护, 而 IO 指令很简单: 所以要不这样, 把指令写出来, 然后开个虚拟机运行, 如果运行没问题就算测试通过了.语义错误处理 一些常见的语义错误处理在之前的之前的内容中都以注释形式出现, 不过如果留心的话, 上次更新的代码这些错误处理都是完备...

2009-11-15 10:47:44 121

[开发过程]声明与算术节点的测试

    E, 这个算术节点指的是 ArithmaticNode.    由于之前已经测试了ArithmaticNode 全部可能的子节点项目, 因此这次要测试的非常简单, 只需要查看运算指令执行完毕后, 弹栈弹出的大小是不是期望的那么多. 所以, 直接上测试例子了 struct List* ins; struct List* subIns; struct Arit...

2009-11-01 16:02:41 108

[开发过程]运算节点的测试

准备在语法分析完结篇中我给出了一个压缩包, 里面包含了词法和语法分析的各个方面. 其中有一个叫做 jerry-ui.h 的文件中定义了一些 ui 以及 io 相关函数. 作为指令生成测试这样局部性质的测试, 也需要实现这些接口以免发生编译错误, 但没有必要使用 jerry-ui.c 中实现, 因此先在名为 test-ui.c 的文件中给出伪实现#include <stdio.h&gt...

2009-10-18 11:09:52 214

[指令生成]语法制导的指令生成[5]

    最后还剩下一个, 声明语句的翻译. 因为符号表API已经很完善了, 所以声明语句的翻译不会太困难. 将一些小地方处理好了就行. 难对付的部分是设定初始值, 需要考虑到类型转换. OK, 代码说明一切.struct List* insDeclarationNode(void* node){ struct DeclarationNode* self = (struct Dec...

2009-09-26 19:49:41 143

[指令生成]语法制导的指令生成[4]

运算. 首先是单目运算指令, 相对而言比较简单, 只有3种情况struct List* insUnaryOperationNode(void* node){ struct UnaryOperationNode* self = (struct UnaryOperationNode*)node; AcceptType type = self->typeOf(self)...

2009-09-12 16:46:36 159

[指令生成]语法制导的指令生成[3]

首先回顾一下符号表提供的接口AcceptType typeOf(struct VariableNode* var);int staticOffset(struct VariableNode* var, int* offsets); 前面一个获取类型在这里并不是特别需要——那是在加载变量值的时候考虑的。至于 staticOffset 这个函数,功能已经非常强大了,我们现在要做的就是,计...

2009-09-01 20:31:54 118

[指令生成]语法制导的指令生成[2]

非常抱歉我选择的字体有些问题,导致字符绘制的图表中右侧竖线没有对齐,追求视觉效果的同学可以将它们拷贝下来,粘贴之后改用“宋体”或其它等宽,并且1个中文字符宽度等于2个ASCII字符宽度的字体显示。     Jerry语言比较简单,流程控制仅限于分支和循环(而且只有while循环)。这里并不会对它们的指令生成做优化,只是给出能够运作的最基本解决方案。    首先是分支语句。完整的分支语句...

2009-08-15 11:15:21 217

[指令生成]语法制导的指令生成[1]

    每个节点生成的指令都是一个长长的指令列表,那么得弄几个小工具将这些列表给连接起来。// 将一个指令追加到表末尾static struct List* appendIns(struct List* list, void* ins){ list->addTo(list, ins, list->count(list)); return list;}...

2009-07-31 19:47:36 194

[指令生成]语法制导的指令生成[接口]

    继续向语法树节点结构中追加成员。 #define memberAbstractSyntaxNode \ unsigned int line; \ struct AbstractSyntaxNode* nextNode; \ struct List* (*createIns...

2009-07-24 10:15:23 173

[指令生成]指令数据结构及虚拟机指令集

    这里要说的指令,并不是x86体系结构下的机器指令,而是虚拟机指令。Jerry虚拟机的设计并不是非常复杂——甚至看起来很不灵活——它是一个栈式虚拟机,不包括任何寄存器(除了指令计数器之外),所有的指令都是基于栈进行的。在文章最后将给出完整的指令集。现在先给出指令数据结构,它们包括typedef enum { // ... 指令集,文章最后会贴出完整的} Instructio...

2009-07-11 20:51:45 193

[语义分析]语法树节点波澜再起[编译时类型确定]

    上一次修改AbstractValueNode时添加了一个typeOf成员函数,这个函数用来在编译时确定AbstractValueNode的类型。相对于确定编译时值,确定类型要简单一些。    对于IntegerNode和RealNode,它们的成员函数实现依然是很简单的AcceptType typeOfInt(void* node){ return...

2009-06-17 15:44:21 142

[语义分析]语法树节点波澜再起[编译时值及常数折叠]

    上一次构建语法树相关的节点,是在语法分析刚刚开始的时候,这一次又需要对它们动一动手脚,加入一些语义分析需要的成员函数。    这一次添加的主要是针对AbstractValueNode及其子类(以后还会讨论关于指令生成相关的函数),现在需要把它变成这个样子#define memberAbstractValueNode \ memberAbstractSyn...

2009-06-05 16:07:29 111

[符号表]加一层套

    符号表系统看起来还算是比较好用,不过为了方便起见,现在在它之上再加一层套。考虑到日后一些类型的语法节点,如VariableNode以及DeclarationNode,它们直接与符号表打交道的话,就会出现这样的问题:一方面它们要执行语法制导的指令生成,另一方面还需要处理各种跟符号表有关的错误,这样违反了单一责任原则──特别是,当使用 if-else 分支来处理这些错误时,内部的缩进层...

2009-05-21 15:40:53 90

[符号表]函数实现

    符号表的实现方法可以多种多样,只要通过了测试基本上就没啥问题了。在这里给出一个参考实现。    首先是符号表相关的结构体,这东西最好放到 datastruct.h 中/* 变量单元,存放符号表中注册的变量信息 */struct VarCell { char* ident; // 标识符 int addr; // 基地址 ...

2009-04-28 09:31:31 249

[开发过程]符号表的测试

    之前在词法和语法分析部分都有测试,不过那些测试显得很小打小闹,而且比较麻烦。好在那都是不复杂的东西,测试负担较小。而符号表这东西是语义分析需要用到的基础结构,如果等到最后进行集成测试,出了bug还真不好找。所以这东西有必要单独拿来测试一下。不过C语言的测试驱动开发工具还真是难找,这里就山寨一个先。    测试数据这里简单给出4组// 测试数据数目#define NR_TEST_...

2009-04-19 20:33:23 117

[符号表]静态地址管理符号表接口及使用原则

    进入语义分析的首要任务是组织和管理变量符号。这一点有多种选择,一种是类C/C++语言那样的静态处理,即将变量映射为地址,运行时内存中根据地址取得变量值,这样运行效率无论是从内存使用量和访问速度上都会较高;而另一种就是可反射的符号表,即在运行时根据变量名在符号表中取得变量值,这样做的典型是Python语言,虽然这样效率较低,不过好处是方便ORM等反射机制的实现。不过既然现在Jerry并没有意...

2009-04-12 23:23:00 171

[语法分析]完结篇

附件中包含了到目前为止的所有文件,除了COOL目录之外。    语法分析的功能基本上成熟了,调试也完成了,现在剩下将这些东西整合起来成为一个没有调试输出(特别是内存分配调试)的整体了。首先要做的事情是,把COOL中的Queue/Stack这些东西包含进来,就放在datastruct.h中。#ifndef _DATA_STRUCTURE_H#define _DATA_STRUCTURE_H...

2009-03-28 10:51:41 82

[错误处理]LR分析器的错误处理

    当一个分析器A调用另一个分析器B时,如果称A处于B的“外层”,那么除开测试文件中产生的那个FakeDefaultAnalyser之外,LR分析器是整个语法分析结构中最外层的语法分析器。因此当其它分析器有无法处理的错误时,这些烂摊子都得它来收拾。比如变量分析中可能有冗余的反方括号,表达式分析中可能有冗余的反圆括号,等等,甚至包括其它的LR分析器也有可能把错误扔给更外层的LR分析器。这样一来,...

2009-03-15 21:49:53 542

[错误处理]变量分析器 / 语法分析错误提示函数接口

    变量分析器本身很简单,它的错误处理不需要弄得太复杂,只对正反方括号做做验证,其它的丢给表达式分析器或者LR分析器去弄就行了。(下面一段话中的括号均指方括号。)    大致的构想是这样的:当需要反括号时,没碰到反括号,直接提示错误,然后装作啥也没发生一样重新看看这个终结符;而遇到除了括号以外的其它符号时,就终止识别(此时变量识别结束,返回)。实现如下:void wrapname(cons...

2009-03-07 16:42:42 491

[错误处理]表达式分析器的容错

    由于语法分析模块由多个不同的分析器协同完成,当一个分析器中发现语法错误,或者仅仅是该识别的非终结符识别完成,即将返回时,该分析器会将从这里开始的终结符都扔给委托它的分析器去处理。这会导致一个问题,那就是错误会从当前分析器扩散到调用栈中的其它分析器。比如输入:    if ( x == 1 2 ) { // other codes ...在没有任何保护措施的情况下,表达式分析器遇到“2”...

2009-03-02 11:38:13 141

[语法分析]识别变量的分析器

   变量这玩意儿本身很简单,无非是一个标识符开头,然后若干对中间夹着一个算数运算的正反方括号,而分析算术运算节点的任务又可以委托给专门的分析器来做,因此识别变量的分析器本身其实没什么需要做的。下面是它的数据结构。struct VariableAnalyser { memberSyntaxAnalyser struct VariableNode* var; // 用来存放识别的变...

2009-02-21 11:13:57 164

[语法分析]LR语法分析器的构造

    LR分析器的consumeNonTerminal函数在上一节提到过,其实跟Goto表没有关系:如果在分析器内部规约得到一个非终结符,那么规约函数执行结束之后,马上就会根据传入宏的“leftPart”在Goto表中查找对应的目标状态并压栈,而根本不用执行consumeNonTerminal函数。这个成员函数的用武之地在于接受其它分析器得到的非终结符,并在Goto表中“额外”的那一列里查找对应...

2009-02-15 10:04:41 1650

[语法分析]LR分析器与其它分析器的交互

    Action表中还有一小部分没有填完,就是LR分析器委托其他分析器识别非终结符的那一部分。其中包括在变量定义时委托VariableAnalyser识别变量,在识别循环条件或赋值语句等状态中委托OperationAnalyser识别运算式,以及在识别正反花括号内部的基本块时委托一个新的LRAnalyser去识别它。这些Action也可以用宏来实现,大家应该已经轻车熟路,这里就不多说了,直接看...

2009-02-12 15:21:43 104

[语法分析]LR分析中的规约及产生式函数

    对于LR分析而言,规约状态可以从这个角度分为两类,一类是“纯”的规约状态,也就是分析预测表中某个状态Action表一行全部是规约行为,如Jerry语言的状态WhileLoop_5,这个状态无论遇到什么符号都会规约一个while循环到一个语句;另外一种就是有移进-规约冲突的状态。从实现的角度来看,这两种状态的实现可以完全不同:对于前一种情况,一旦步入该状态,就规约,然后根据规约后得到的非终结...

2009-02-09 10:53:27 886

[开发过程]宏函数及调试

    在使用了大量的宏来快速构建函数后,一个问题出现了:如果你发现某个地方出了bug,你得定位它,于是使用debugger,然而宏的“简易”导致你进行了许多次“下一步”还是停留在使用宏的那一行。    当然也不是完全没办法,如果你曾经接触过Python语言,并且听说过“Python语言八荣八耻”,那么你应该对这句话有印象——以打印日志为荣,以单步跟踪为耻。虽然我不太明白为什么Python语言有...

2009-02-08 21:31:59 322

[语法分析]SLR(1)分析预测表Action表中移进的构造

    在构造之前当然要先抽取接口,让其它语法分析器能愉快的跟LR分析器相处/* syntax-analyser.h */void initialLRStates(void);void destructLRStates(void);第一个函数是构造函数,第二个则是析构函数。这些东西跟LR分析器的构造函数是独立,因为分析预测表(也就是LR状态集)是一个静态数据结构,比如我曾经说在状态Sen...

2009-02-04 14:21:43 872

[语法分析]LR状态集

    由于识别表达式的工作已经委托给其他的分析器去做了,因此这一阶段需要关注的产生式其实很少,它们是: Jerry -> BasicBlock <END> BasicBlock -> εBasicBlock -> Sentence BasicBlock Sentence -> <EOS>Sentence -> IfElseBr...

2009-01-31 21:02:57 184

[语法分析]算符优先分析的实现及独立测试

    好了,现在来尝试把那些该未实现的注释给实现掉了。当然有两个地方在上一节中本应该实现,它们是代码块1中的// 将一个左括号压入栈顶// 实现为opana->opStack->push(opana->opStack, newOperator(LPARENT, 0x7fffffff, nullOperate)); 和代...

2009-01-23 21:48:25 116

[语法分析]无需产生式的分析器

    算符优先分析用来处理表达式非常便捷,甚至你可以忘记算术运算相关的一切产生式。对于算符优先分析来说最重要的东西有三:运算符的优先级、元和结合方式。优先级在任务布置时已经讲过了;元很简单,一般运算符都是二元的,只有正号和负号是一元的;结合方式一般分两种,普通的运算都是左结合的,赋值和乘幂运算是右结合的,而Jerry不支持乘幂运算。简单的表达式求值算法可以参考这篇文章,文中相关实现也是基于该算法...

2009-01-21 10:45:35 84

[语法分析]混合语法分析

    之前小小地透露过,我会用LR分析方法。它很强大,而且效率比较高,而且Jerry语言的语法(虽然还未具体证实,但我可以保证)是相对(于LALR(1)或LR(1)方法)容易构造的SLR(1)文法。    然而无论如何,Jerry语言语法的复杂性显然是大大高于书上一般给出的练习,那些练习通常只有几个产生式,至多十来个LR项目。然而Jerry一共有三十多个产生式,写出LR项目一共有大约70个。所...

2009-01-17 16:51:06 131

[语法分析]前奏:怎么扩展

    现在完成的是一个词法分析器,那么怎么将它与语法分析相连?    话说,基本上所有的编译器构造相关的文章都是把词法分析丢在语法分析之前,类似这样: 预处理(C语言为代表,Jerry没这一环) -> 词法分析 -> 语法分析 -> 语义分析 -> 中间代码生成和代码优化 ->目标代码 貌似互相独立的过程。然而从某种程度上来说,语法和词法应该“混为一谈”,...

2009-01-11 21:55:36 70

[错误处理]面向经验的玩意儿

    错误处理的方法之一是认可错误的输入,将它判定为某一种正确输入的变体,然后在报出错误后再其纠正它。这个过程很大程度上跟经验相关,对于出错的经验越丰富,那么就可以矫正越多种类的错误。在词法分析中这一点体现得并不多——词法本身很简单,而敲击键错误导致的某些错误程序员应该会及时看到(比如在Jerry编程时非注释的部分输入了一个"@"符号)并改正它。而语法分析过程中这种情况则少得多,比如输入   ...

2009-01-09 15:14:10 129

[词法分析]一个雏形

到了终结之前那一团散沙的时候了。先把几个头文件列出来。下面每一段代码的首行注释的内容表示包含这些代码的文件的文件名。/* const.h */#ifndef _CONSTANT_H#define _CONSTANT_Htypedef enum { END, IDENT, ELSE, IF, WHILE, READ, WRITE, BREAK, INTEGER_TYPE,...

2009-01-07 20:32:14 84

[词法分析]解析输入

    词法分析的最终目标是将输入字符流变成一个个符号,因此还需要引入一个新的结构: /* datastruct.h */struct Token { int line; // 所在行 AcceptType type; // 类型 char* image; // 像};其中type和image域是至关重要的,分别表示该符号的接受类型和"外貌",后者对于常数值、标识...

2009-01-06 16:44:47 229

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除