语句与复合语句结点
(sentence and complex sentence node)
(一)实例说明
在介绍语句结点之前,先来看一段小的,不完全的c代码。
代码1.1
- int main()
- {
- int i; /*定义语句*/
- i=0; /*赋值语句*/
- while (i<100){...} /*while循环语句*/
- if(i>2000){...} /*if语句*/
- 1+2+3+i*4+2; /*算术表达式语句*/
- return 0 ; /*返回语句*/
- }
代码1.1中定义了一个函数main,在main内部总共有6条不同的语句,每一条语句的类型在代码中都有说明,其中有两条为if语句和while语句,没有给出完整的代码,主要是因为if和while都是复合语句,省略其内容,是想把它当做一个整体来看待,而不去探究其内部细节。
现在从更高一层次来在看待main,代码如下:
代码1.2
- int main(){...}
代码1.2忽略了main函数其内部语句的细节,从整体上来讨论main函数,可以把main函数看作由一条复合语句组成,该复合语句又由零条或多条语句组成。
如果要为代码1.1构造其相应的语法树,则至少需要两种类型的结点:复合语句结点,语句结点。
在redy源码中复合语句结点由AstNodeStmts表示,语句结点由AstNodeStmt表示(注意这个类型名称只相差了一个s)。把它们之间的关系用uml来表示,如下图:
图1
图1的意思为:
AstNodeStmts和AstNodeStmt都继承AstObject
AstNodeStmts由0个或多个AstNodeStmt组成
AstNodeStmt由一个子结点AstObject组成
在设计AstNodeStmt时,没有采用其它类型语句继承 AstNodeStmt , 而是使用聚合的方法, AstNodeStmt 包含一个AstObject作为其子结点。虽然继承可以使用在这里,但在软件开发中尽量使用聚合来代替继承,继承的维护代价很高,当修改父类后,所有的子类都必须跟着改变。
为代码1.1函数main的内部语句,构造语法树,如下图:
图2
现在的目标是让图2语法树跑起来,图2中的root代表整个main函数内部语句的集合,在执行它时,它需要依次执行其包含的子语句。AstNodeStmts 的执行方式,用代码描述如下:
代码1.3
- AstNodeStmts.execute()
- for node in AstNodeStmts.s_chirdren /*遍历每一个子结点*/
- node.execute() /*执行子结点*/
- endfor
- end
在代码1.3中,node为AstNodeStmt类型,AstNodeStmt的执行方式很简单,它只是做为一个代理,执行其下面的子结点即可,用代码描述如下:
代码1.4:
- AstNodeStmt.execute()
- AstNodeStmt.s_sub_node.execute() /*执行子结点*/
- end
附: 代码下载: git clone git://git.code.sf.net/p/redy/code redy-code
AstNodeStmts 与AstNodeStmt 位于src/syntax/ 文件ast_node_stmts.h与ast_node_stmt.h 中