这几天在解释器fInterpretor 中加入了静态语义检查
静态语义检查分为下面几个方面:
- 名字检查
- 类型名
- 函数名
- 变量名
- 类型匹配检查
- 各种运算 (比如算术,逻辑)的类型约束
- 函数调用实参和形参的类型匹配
- 函数实际返回类型和声明的返回类型是否匹配
- 变量初始化检查 (非必须)
- 检查局部变量在引用前是否已经初始化 (尚未实现)
这几天在解释器fInterpretor 中加入了静态语义检查
静态语义检查分为下面几个方面:
Lex 和Yacc 总是需要合作来完成任务. Lex 返回token , Yacc 根据产生式来生成语法分析器.
在PLY 中可以非常容易的书写语义动作, 完成我们的任务. 类似 lex, yacc 也使用以”p_”开头的函数(文档字符串表示产生式), 函数的内容就是语义动作.根据我们的目标, 我们需要对输入文件做三次扫描.
下面是代码, 比较长. 而且有一些Ugly.
READ MORE »
PLY 是一个Python 的Lex/YACC 实现. 官方网站在这里http://www.dabeaz.com/ply/
这学期有一门课叫 ” 计算机综合课程设计-基于MIPS16的SOC设计实践” ,其中有一部分是实现一个汇编器. 将MIPS汇编程序转换成Quartus 的mif 文件.
这样的需求使用Lex/YACC 最合适不过, 本来是想使用Flex/Bison , 或上学期自己实现的lex和yacc. 但是在尝试了一下后,决定放弃.原因在于C/C++ 对文本的操纵比较麻烦,另外yacc 的语义动作限制比较大. (主要是数据类型问题)
而PLY 这个实现学习成本很低, 而且很Pythonic.加入符号表等等功能也很简单.
首先我们先来看我们要处理的汇编文件的格式.
1 2 3 4 5 6 7 8 9 10 11 12 13 | ORG_DATA 0000 ;The start address of data BUF DW 00FF, 5500 NEXT DW 0CFF, 5D00 ORG_CODE 0000 ;The start address of code start: addi $t0, $Zero, 0 ;A label for the first statement,$t0=0 lw $v0, BUF($t0) ;$v0=00FF (BUF[0]) addi $t0, $t0, 2 lw $v1, BUF($t0) ;$v1=5500 (BUF[2]) add $v0, $v0, $v1 ;$v0=$v0+$v1=55FF addi $t0, $t0, 2 sw $v0, BUF($t0) ;BUF[4]=55FF j start end start |
下面我们来书写汇编文件的lex 定义. token 类型大概有下面这些.
PLY 的lex 文件格式其实就是一个标准的Python 文件, 不过使用一些规定的格式/名字来指定.
(下面的代码比较长, 所以我要用–MORE–了)
READ MORE »
这几天忙着写编译原理课程设计的另一部分. Seu YACC的实现.
这个程序的核心算法实现不是有我来完成,我负责后端输出的模板代码的书写.
实际上就是一个基于LALR分析表的parser.
我附带加上了生成抽象语法树的功能, 并输出DOT 文件,通过graphviz 生成图片.
下面贴一段Min-C 语言的抽象语法树.(图片比较大)
对应的代码为
int main ( )
{
int x = 0 ;
int b = 2 ;
int c = 5 ;
int d = 6 ;
int a = b ;
if ( x < y )
{
int x = y ;
}
while ( c == d )
{
int m = c + d ;
m = x + y ;
}
}
DFA最小化的详细算法
说明:下面的算法在空间复杂度上有一点小问题,我已经改用deque来实现.算法的基本思想是一致的.
下面的算法比使用deque的实现方式更通俗易懂,所以没有更新下面的描述了.
数据结构:
算法:
如果任何字符都不能分割这个集合
mdfa.finalStates.insert(mapping[dfa.finalStates])
if (!mdfa.meta[mapping[s]] || mdfa.meta[mapping[s]] > dfa.meta[s])
//这里体现了lex输入文件中先出现的规则优先的原则。mdfa.meta[mapping[s]] = dfa.mata[s]
最近评论