CflatToken
这个类是对Token类的一个包装.这样能整合Token和SpecialToken.首先我们看一下官方的Token的定义,这里有两个关键的调用
因此,我们可以用这两个方法来分别获得sptoken和普通token.所以在CflatToken类中,实现的方法:
其中token序列相当于链表,每找到一个普通TOKEN,向上遍历找之前的spTOKEN序列的头.然后看情况是否添加.
节点编写
首先,我们定义所有的实体类有如下几种:
- Constant 常量
- DefinedVariable 定义的变量
- UndefinedVariable 声明的变量
- DefinedFunction 定义的函数
- UndefinedFunction 声明的函数
- StructNode struct定义
- UnionNode union定义
- TypedefNode 定义的类型
看一下我们顶层的Declarations类,这个类在根节点中出现用来汇集import声明和函数体的类.基本上就是一个各种类型的集合.1234567891011public class Declarations {Set<DefinedVariable> defvars = new HashSet<DefinedVariable>();Set<UndefinedVariable> vardecls = new HashSet<UndefinedVariable>();Set<DefinedFunction> defuns = new HashSet<DefinedFunction>();Set<UndefinedFunction> funcdecls = new HashSet<UndefinedFunction>();Set<Constant> constants = new HashSet<Constant>();Set<StructNode> defstructs = new HashSet<StructNode>();Set<UnionNode> defunions = new HashSet<UnionNode>();Set<TypedefNode> typedefs = new HashSet<TypedefNode>();//...一些add接口}
接下来抽象出我们的节点的基类node:
Node中没有实质内容.PrintTree方法是用来递归打印整个节点向下包含的内容结构.就是一颗抽象语法树子树.
所有的节点类型中包含了type()和origType(),type()返回这个节点包含的整体类型,而后者返回他的基础类型,比如char[]数组返回的类型就是数组,基础类型就是char.
type包里定义了一些类型类,比如说我们的指针类PointerType,char,int这些都属于这个类,因此应该包含一个保存基础类型的成员.
在设计type系列的类时候,要考虑如下几个方面:
- 类型的类要考虑能否转换.比如int可以转换成一个指针类型
- 考虑是不是同一种类型.
- 考虑两个类型是不是兼容,比如int可以兼容void.
- 复合类型需要基础类型.
- 从实体中可以抽象出他的类型,比如从一个Definedfunction中抽出他的参数列表类型,返回值类型.
解析器的启动模块
在Parser这个类里,首先编写构造函数:
构造函数中用Javacc默认的第三个构造函数,debug用来开启javacc的调试模式.
我们需要一个能解析源文件的方法和一个解析头文件的方法: