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