您的位置:首页 > 大数据 > 人工智能

http://blog.csdn.net/lpstudy/article/details/51340537

2016-11-23 17:55 344 查看
语法树:[+]

简介

本章在上一节7的基础上对编译树进行完善。 上一节7的编译树仅仅支持算术表达式的+-基本运算,本节对其进行扩充,使其支持不仅支持基本的算术运算,还支持变量,支持语句(if, while,input, ouput),经过这次扩充,它形成的语法树已经基本具备了表达minus-C语言的能力。

简单说来,它可以表示下面的c语言代码:
a = 1
if(a>10){
a = 11
}else{
a = 7
}
print(a)

a =1
sum = 0
while(a <= 10){
sum = sum + a
a = a+1;
}
print(sum)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[/code]

根据上述的c语言代码,通过手动构建对应的语法树,然后后序遍历语法树,就可以执行代码,输出结果。本节的编译树代码并不关注如何根据c语言代码自动构建语法树(lex和yacc支持), 而是着眼于对手动构建的语法树进行遍历执行。

语句的处理

if语句

if(expr) {stmt1} else  {stmt2}
1
1
[/code]



对于if树节点,它具有3个孩子,expr,stmt1,stmt2. 当后序遍历到if节点时候,它首先判断expr是否为真,如果为真,则执行stmt1,否则执行stmt2,因此当执行后序遍历的时候,我们会有这样的代码:
if(t->kind == STMT_NODE){
if(t->kind_kind == IF_STMT){
//if条件判断结果,第二个孩子存储if成功的代码,第三个孩子存储else成功的代码
recursive_execute(t->children[0]);
if (my_mem[t->children[0]->addr] )
recursive_execute(t->children[1]);
else
recursive_execute(t->children[2]);
}//IF_STMT
}//STMT_NODE
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
[/code]

如上面的代码所示,首先根据t->kind判断是否是语句节点,然后根据子类型t->kind_kind判断是否是if节点。如果是的话,首先递归执行第一个孩子,执行完毕后,结果保存在my_mem[t->children[0]->addr]中,然后判断它的值是否为真,如果为真,则执行stmt1,否则执行stmt2。

while语句

while(expr)  {stmt}
1
1
[/code]

与if不同的是,while只有两个孩子,expr和stmt, 同时当expr为真的时候,stmt会循环执行,直到expr为假。因此遍历代码如下:
if(t->kind_kind == WHILE_STMT){
//第一个孩子存储条件判断结果,第二个孩子存储while成功的代码
recursive_execute(t->children[0]);
while (my_mem[t->children[0]->addr])
{
recursive_execute(t->children[1]);
recursive_execute(t->children[0]);
}
}
1
2
3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
[/code]

输入输出语句

输入输出相当于修改或者打印给定节点对应的内存的值,因此就非常简单,代码如下:
else if(t->kind_kind == INPUT_STMT){//input statement has one expr child
cout<<"please input data:";
cin>>my_mem[t->children[0]->addr];
}else if(t->kind_kind == PRINT_STMT){//print statement has one expr child to print.
recursive_execute(t->children[0]);
cout<<my_mem[t->children[0]->addr];
}
1
2
3
4
5
6
7
1
2
3
4
5
6
7
[/code]

复合语句

复合语句是用来包装多个简单语句的,例如如果有3个语句,它们之间是顺序执行的关系,但是最后生成是一棵树,因此需要将3个语句组合在一起,简单来说就是将这3个语句的Node作为一个复合语句Node的孩子,当遍历执行的时候,只需要逐个执行每一个孩子即可。



代码如下:
else if(t->kind_kind == COMP_STMT){//组合语句,逐个语句执行即可。
for (int i = 0; i < MAX_CHILDREN; ++i)
recursive_execute(t->children[i]);
}
1
2
3
4
1
2
3
4
[/code]

表达式语句

表达式语句就是基本的表达式后面加上分号,例如b=1;这就是一个语句,它是一个赋值表达式然后加上分号构成的语句。为了简单起见,对于表达式语句,它只有一个孩子就是表达式,因此表达式语句的执行就是执行它的孩子(表达式)

代码如下:
else if(t->kind_kind == EXPR_STMT){
recursive_execute(t->children[0]);
}
1
2
3
1
2
3
[/code]

表达式的处理

表达式有很多种,例如二元的加减乘除,逻辑运算与或非,比较运算符,一元的取非,自增自减等等,以及还是纯粹的数字,变量表达式。简单起见,本代码只考虑支持基本的二元运算以及数字和变量表达式,它的执行代码比较简单,不具体阐述,示意如下:
if (t->kind == EXPR_NODE){          // 表达式结点
recursive_execute(t->children[0]);
recursive_execute(t->children[1]);

if (t->kind_kind == OP_EXPR) {      // 运算类型表达式
if (t->attr.op == PLUS)         // 加法表达式
// 从内存(my_mem)中取出两个孩子的值,进行加法,结果写回内存
my_mem[t->addr] = my_mem[t->children[0]->addr] + my_mem[t->children[1]->addr];
else if (t->attr.op == MINUS)   // 减法的处理类似加法
my_mem[t->addr] = my_mem[t->children[0]->addr] - my_mem[t->children[1]->addr];
else if (t->attr.op == TIMES)
my_mem[t->addr] = my_mem[t->children[0]->addr] * my_mem[t->children[1]->addr];
else if (t->attr.op == OVER){
if(my_mem[t->children[1]->addr] == 0){
cout<<"error: divide by zero"<<endl;
my_mem[t->addr] = 0;
}else{
my_mem[t->addr] = my_mem[t->children[0]->addr] / my_mem[t->children[1]->addr];
}
}
else if (t->attr.op == AND)
my_mem[t->addr] = my_mem[t->children[0]->addr] && my_mem[t->children[1]->addr];
else if (t->attr.op == OR)
my_mem[t->addr] = my_mem[t->children[0]->addr] || my_mem[t->children[1]->addr];
else if (t->attr.op == EQ)
my_mem[t->addr] = (my_mem[t->children[0]->addr] == my_mem[t->children[1]->addr]);
else if (t->attr.op == GT)
my_mem[t->addr] = my_mem[t->children[0]->addr] > my_mem[t->children[1]->addr];
else if (t->attr.op == LT)
my_mem[t->addr] = (my_mem[t->children[0]->addr] < my_mem[t->children[1]->addr]);
else if (t->attr.op == NE)
my_mem[t->addr] = !(my_mem[t->children[0]->addr] == my_mem[t->children[1]->addr]);
else if (t->attr.op == GE)
my_mem[t->addr] = (my_mem[t->children[0]->addr] > my_mem[t->children[1]->addr]) || (my_mem[t->children[0]->addr] == my_mem[t->children[1]->addr]);
else if (t->attr.op == LE)
my_mem[t->addr] = (my_mem[t->children[0]->addr] < my_mem[t->children[1]->addr]) || (my_mem[t->children[0]->addr] == my_mem[t->children[1]->addr]);
else if(t->attr.op == ASSIGN){
my_mem[t->addr] = my_mem[t->children[0]->addr] = my_mem[t->children[1]->addr];
}
}
else if (t->kind_kind == CONST_EXPR)    // 常量表达式,将值(在vali中)保存至分配的内存中
my_mem[t->addr] = t->attr.vali;
else if(t->kind_kind == ID_EXPR){
//do nothing
}

}//EXPR_NODE
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
[/code]

其中比较特别就是对于ID_EXPR(变量)类型,不作处理。这是因为此代码并没有支持符号表,变量节点的内存直接存储的是变量的值,而不是如正规的符号表中存储是变量所处于的符号表的位置。 当碰到ID_EXPR类型,不需要进行额外的处理,变量的内存更新由具体的赋值运算决定。

树构建代码

先针对一个具体的while例子,说明如何构建一颗语法树,可以表达while语句。

要表达的while语句如下:
a =1
sum = 0
while(a <= 10){
sum = sum + a
a = a+1;
}
print(sum)
1
2
3
4
5
6
7
1
2
3
4
5
6
7
[/code]

它包含2个变量,输出结果是1+2+…+10。

对应的构建语法树的代码:
void whileTest()
{
tree expr;
Node *p, *q, *r, *s, *o, *u, *t,*p1,*q1;
p = createId(expr);//a
q = createId(expr);//sum
p1 = createAssignStmt(expr,p, 1);//a=1
q1 = createAssignStmt(expr, q, 0);//sum=0

Node *a, *b, *c, *d, *e, *f, *g;
a = createOpExpr(expr, p, createConst(expr, 10), LE);//a<=10
b = createOpExpr(expr, p, q, PLUS);//sum+a
c = createAssignStmt(expr, q, b);//sum = sum+a

d = createOpExpr(expr, p, createConst(expr, 1), PLUS);
e = createAssignStmt(expr, p, d);   //a=a+1
f = createCompStmt(expr, c, e); //{sum = sum+a, a= a+1}
r = createWhileStmt(expr, a,  f);//while

t = createOutStmt(expr, q);//print sum

o = createCompStmt(expr, p1, q1, r, t);

executeTree(expr, o);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
[/code]

上面有很多createXXX的函数,并不需要关注其具体实现也可以读懂上面的构建代码。

首先创建两个变量,然后创建两个赋值语句p1, q1,随后创建while语句r和print语句t,最后将4个语句组装成一个组合语句o并将o作为语法树的根,启动execute执行。

实现代码

考虑到便于大家自己扩充,我将我自己扩充的版本放在这里,大家可以根据自己的想法继续扩充,例如实现多种一元运算符,实现for循环等等。大家将下面的代码直接粘贴到vs工程中,编译就可以执行。注意main函数中有多种test,可以专注于某一种情况的测试
#include <iostream>
#include <malloc.h>
using namespace std;

#define MAX_CHILDREN 4
int my_mem[100]; // “内存”
int offset;

enum // 结点类型——kind
{
STMT_NODE = 0,
EXPR_NODE,
DECL_NODE
};

enum // 语句结点子类型——kindkind
{
IF_STMT = 0,
WHILE_STMT,
INPUT_STMT,
PRINT_STMT,
COMP_STMT,
EXPR_STMT, //只是一个包装而已
};

enum // 表达式结点子类型——kindkind
{
TYPE_EXPR = 0,
OP_EXPR,
NOT_EXPR,
ARRAY_EXPR,
CONST_EXPR,
ID_EXPR,
};

enum // 声明结点子类型——kindkind
{
VAR_DECL = 0,
ARRAY_DECL
};

enum // 运算——op
{
//加减乘除,算术运算符
PLUS = 0,
MINUS,
TIMES,
OVER,
//与或,逻辑运算符
AND,
OR,
//比较运算符
EQ,
LT,
GT,
GE,
LE,
NE,
ASSIGN,
};
enum
{
Integer = 0,
};

union NodeAttr {
int op; // 表达式结点,子类型是运算类型时,用op保存具体运算
double vali; // 表达式结点,常量表达式时,用vali保存整型常量值
char valc; // 字符值

NodeAttr(void) { op = 0; } // 几种构造函数
NodeAttr(int i) { op = i; }
NodeAttr(double i) { vali = i; }
NodeAttr(char c) { valc = c; }
};

struct Node
{
struct Node *children[MAX_CHILDREN]; // 孩子结点
int kind; // 结点类型
int kind_kind; // 子类型
NodeAttr attr; // 结点属性
int addr; // 分配的内存空间(数组下标)
};

class tree // 语法树类
{
private:
Node *root; // 根结点

private:
void recursive_get_addr(Node *t); // 为临时变量(如表达式)分配存储空间
void recursive_execute(Node *t); // 遍历树,执行源程序

public:
void setRoot(Node* p){root = p;}
Node *NewRoot(int kind, int kind_kind, NodeAttr attr, int type,
Node *child1 = NULL, Node *child2 = NULL, Node *child3 = NULL, Node *child4 = NULL); // 创建一个结点,设置其属性,连接孩子结点
void get_addr(void); // 分配空间和执行代码的接口
void execute(void);
};

Node * tree::NewRoot(int kind, int kind_kind, NodeAttr attr, int type,
Node *child1, Node *child2, Node *child3 , Node *child4)
{
Node* node = new Node();
node->kind = kind;
node->kind_kind = kind_kind;
node->attr = attr;
node->children[0] = child1;
node->children[1] = child2;
node->children[2] = child3;
node->children[3] = child4;

return node;
}

void tree::get_addr(void)
{
cout << "allocate memory..." << endl;
offset = 0;
recursive_get_addr(root); // 接口函数直接调用实际分配空间的递归函数
}

void tree::recursive_get_addr(Node *t)
{
if (t) { // 空指针什么也不做
if (t->kind == EXPR_NODE) { // 为表达式结点分配存储空间
t->addr = offset++;
//cout << t->addr << endl;
}
for (int i = 0; i < MAX_CHILDREN; i++) // 递归处理所有子树——先序遍历
recursive_get_addr(t->children[i]);
}
}

void tree::execute(void)
{
cout << "execute..." << endl;
recursive_execute(root); // 接口函数调用递归函数
//cout << my_mem[root->addr] << endl; // 从内存取出执行结果,输出
}
/*
功能逐步添加摘要:
if条件判断功能:
根据if的condition来决定是否执行statement代码,因此不能首先对其所有的孩子进行后续遍历,需要根据第一个孩子的执行结果来决定是否执行第二个孩子。
while循环功能:
此功能框架代码与if功能相似,只是多了一个while循环而已
变量赋值:
读取用户输入,并赋值到变量,支持input(a),它将用户的输入赋值到变量a,a为其第一个孩子。
赋值语句:
支持a=2,包括两个孩子,左边为变量,右边为值,当前值为左边的值。
输入功能:
能够接收用户输入,并赋值到变量中,前提需要增加赋值功能
输出功能:
构建输出语句,它只有一个孩子,即要输出的变量。
*/
void tree::recursive_execute(Node *t)
{
if (t) {
if(t->kind == STMT_NODE){
if(t->kind_kind == IF_STMT){
//if条件判断结果,第二个孩子存储if成功的代码,第三个孩子存储else成功的代码
recursive_execute(t->children[0]);
if (my_mem[t->children[0]->addr] )
recursive_execute(t->children[1]);
else
recursive_execute(t->children[2]);
}else if(t->kind_kind == WHILE_STMT){ //第一个孩子存储条件判断结果,第二个孩子存储while成功的代码 recursive_execute(t->children[0]); while (my_mem[t->children[0]->addr]) { recursive_execute(t->children[1]); recursive_execute(t->children[0]); } }else if(t->kind_kind == INPUT_STMT){//input statement has one expr child cout<<"please input data:"; cin>>my_mem[t->children[0]->addr]; }else if(t->kind_kind == PRINT_STMT){//print statement has one expr child to print. recursive_execute(t->children[0]); cout<<my_mem[t->children[0]->addr]; }else if(t->kind_kind == COMP_STMT){//组合语句,逐个语句执行即可。 for (int i = 0; i < MAX_CHILDREN; ++i) recursive_execute(t->children[i]); }else if(t->kind_kind == EXPR_STMT){ recursive_execute(t->children[0]); }
}
if (t->kind == EXPR_NODE){ // 表达式结点 recursive_execute(t->children[0]); recursive_execute(t->children[1]); if (t->kind_kind == OP_EXPR) { // 运算类型表达式 if (t->attr.op == PLUS) // 加法表达式 // 从内存(my_mem)中取出两个孩子的值,进行加法,结果写回内存 my_mem[t->addr] = my_mem[t->children[0]->addr] + my_mem[t->children[1]->addr]; else if (t->attr.op == MINUS) // 减法的处理类似加法 my_mem[t->addr] = my_mem[t->children[0]->addr] - my_mem[t->children[1]->addr]; else if (t->attr.op == TIMES) my_mem[t->addr] = my_mem[t->children[0]->addr] * my_mem[t->children[1]->addr]; else if (t->attr.op == OVER){ if(my_mem[t->children[1]->addr] == 0){ cout<<"error: divide by zero"<<endl; my_mem[t->addr] = 0; }else{ my_mem[t->addr] = my_mem[t->children[0]->addr] / my_mem[t->children[1]->addr]; } } else if (t->attr.op == AND) my_mem[t->addr] = my_mem[t->children[0]->addr] && my_mem[t->children[1]->addr]; else if (t->attr.op == OR) my_mem[t->addr] = my_mem[t->children[0]->addr] || my_mem[t->children[1]->addr]; else if (t->attr.op == EQ) my_mem[t->addr] = (my_mem[t->children[0]->addr] == my_mem[t->children[1]->addr]); else if (t->attr.op == GT) my_mem[t->addr] = my_mem[t->children[0]->addr] > my_mem[t->children[1]->addr]; else if (t->attr.op == LT) my_mem[t->addr] = (my_mem[t->children[0]->addr] < my_mem[t->children[1]->addr]); else if (t->attr.op == NE) my_mem[t->addr] = !(my_mem[t->children[0]->addr] == my_mem[t->children[1]->addr]); else if (t->attr.op == GE) my_mem[t->addr] = (my_mem[t->children[0]->addr] > my_mem[t->children[1]->addr]) || (my_mem[t->children[0]->addr] == my_mem[t->children[1]->addr]); else if (t->attr.op == LE) my_mem[t->addr] = (my_mem[t->children[0]->addr] < my_mem[t->children[1]->addr]) || (my_mem[t->children[0]->addr] == my_mem[t->children[1]->addr]); else if(t->attr.op == ASSIGN){ my_mem[t->addr] = my_mem[t->children[0]->addr] = my_mem[t->children[1]->addr]; } } else if (t->kind_kind == CONST_EXPR) // 常量表达式,将值(在vali中)保存至分配的内存中 my_mem[t->addr] = t->attr.vali; else if(t->kind_kind == ID_EXPR){ //do nothing } }//EXPR_NODE
}
}

/*
if: st_if -> (condition, action)
while: st_while->(condition, action)
*/
void basicTest()
{
tree expr;
Node *p, *q, *r;

// 创建结点a
p = expr.NewRoot(EXPR_NODE, CONST_EXPR, NodeAttr(9), Integer);
// 创建结点5
q = expr.NewRoot(EXPR_NODE, CONST_EXPR, NodeAttr(5), Integer);
// 创建减法结点,孩子结点为9和5
r = expr.NewRoot(EXPR_NODE, OP_EXPR, NodeAttr(MINUS), Integer, p, q);
// q = expr.NewRoot(EXPR_NODE, CONST_EXPR, NodeAttr(2), Integer);
// p = expr.NewRoot(EXPR_NODE, OP_EXPR, NodeAttr(PLUS), Integer, r, q);
expr.setRoot(r);
expr.get_addr(); // 为(子)表达式(们)分配存储空间
expr.execute(); // 执行代码
}
void assignTest()
{
/*
a = 1
output(a)

两个语句
*/

tree expr;
Node *p, *q, *r, *s, *o, *u, *t;

//构建赋值语句
// 创建结点a
p = expr.NewRoot(EXPR_NODE, ID_EXPR, NodeAttr(0), Integer);
// 创建结点1
q = expr.NewRoot(EXPR_NODE, CONST_EXPR, NodeAttr(5), Integer);
//赋值
r = expr.NewRoot(EXPR_NODE, OP_EXPR, NodeAttr(ASSIGN), Integer, p, q);
s = expr.NewRoot(STMT_NODE, EXPR_STMT, NodeAttr(0), Integer, r);//赋值语句:孩子赋值表达式

//构建输出语句
t = expr.NewRoot(STMT_NODE, PRINT_STMT, NodeAttr(), Integer, p);

//构建组合语句
o = expr.NewRoot(STMT_NODE, COMP_STMT, NodeAttr(), Integer, s, t);

expr.setRoot(o);
expr.get_addr(); // 为(子)表达式(们)分配存储空间
expr.execute(); // 执行代码
cout<<endl;
}

Node* createOpExpr(tree& expr, Node* p, Node* q, int type)
{
Node* p1;
p1 = expr.NewRoot(EXPR_NODE, OP_EXPR, NodeAttr(type), Integer, p,q);
return p1;
}
Node* createId(tree& expr)
{
Node* p;
p = expr.NewRoot(EXPR_NODE, ID_EXPR, NodeAttr(0), Integer);
return p;
}
Node* createConst(tree& expr, double value)
{
Node* q2;
q2 = expr.NewRoot(EXPR_NODE, CONST_EXPR, NodeAttr(value), Integer);
return q2;
}
Node* createSTMT(tree& expr, int type, Node* p1, Node* p2=NULL, Node* p3 = NULL, Node* p4=NULL)
{
Node* r;
r = expr.NewRoot(STMT_NODE, type, NodeAttr(), Integer, p1,p2,p3,p4);

return r;
}
Node* createIfStmt(tree& expr,Node* p1, Node* p2, Node* p3 = NULL )
{
return createSTMT(expr, IF_STMT, p1, p2, p3);
}
Node* createWhileStmt(tree& expr, Node* p1, Node* p2)
{
return createSTMT(expr, WHILE_STMT, p1, p2);
}
Node* createInputStmt(tree& expr, Node* p)
{
return createSTMT(expr, INPUT_STMT, p);
}
Node* createOutStmt(tree& expr, Node* p)
{
return createSTMT(expr, PRINT_STMT, p);
}
Node* createExprStmt(tree& expr, Node* p)
{
return expr.NewRoot(STMT_NODE, EXPR_STMT, NodeAttr(0), Integer, p);//xxxx; xxxx为表达式,组合成语句
}
Node* createAssignStmt(tree& expr, Node* variable, int value)
{
Node* p = variable;
Node *q, *r, *s;
q = createConst(expr, value);
r = createOpExpr(expr, p,q, ASSIGN);

return createExprStmt(expr, r);
}
Node* createAssignStmt(tree& expr, Node* variable, Node* q)
{
Node* p = variable;
Node *r, *s;
r = createOpExpr(expr, p,q, ASSIGN);

return createExprStmt(expr, r);
}
Node* createCompStmt(tree& expr, Node* p1, Node* p2=NULL, Node* p3 = NULL, Node* p4=NULL)
{
return createSTMT(expr, COMP_STMT, p1,p2,p3,p4);
}
void executeTree(tree& expr, Node* root)
{
expr.setRoot(root);
expr.get_addr(); // 为(子)表达式(们)分配存储空间
expr.execute(); // 执行代码
cout<<endl;
}
void inputOutTest()
{
/*
input(a)
output(a)
*/
tree expr;
Node *p, *q, *r, *s, *o, *u, *t;

//输入语句
// 创建结点a
p = expr.NewRoot(EXPR_NODE, ID_EXPR, NodeAttr(0), Integer);
s = createInputStmt(expr, p);
q = createOutStmt(expr, p);
o = createCompStmt(expr, s, q);

executeTree(expr, o);
}
void ifTest()
{
/*
a = 1
if(a>10){
a = 11
}else{
a = 7
}
print(a)
*/
tree expr;
Node *p, *q, *r, *s, *o, *u, *t;

//输入语句
// 创建结点a
p = expr.NewRoot(EXPR_NODE, ID_EXPR, NodeAttr(0), Integer);
s = createAssignStmt(expr, p, 1);//a=1

//if语句
q = createOpExpr(expr, p, createConst(expr, 10), GT);//a>10
r = createIfStmt(expr, q, createAssignStmt(expr, p, 11), createAssignStmt(expr, p, 7));//if(a>10) a=11 else a=7

//构建输出语句
t = createOutStmt(expr, p);//print(a)

//构建组合语句
o = createCompStmt(expr,s ,r, t );

executeTree(expr , o);
}
void whileTest()
{
/*
a =1
sum = 0
while(a <= 10){
sum = sum + a
a = a+1;
}
print(sum)
*/

tree expr;
Node *p, *q, *r, *s, *o, *u, *t,*p1,*q1;
p = createId(expr);//a
q = createId(expr);//sum
p1 = createAssignStmt(expr,p, 1);//a=1
q1 = createAssignStmt(expr, q, 0);//sum=0

Node *a, *b, *c, *d, *e, *f, *g;
a = createOpExpr(expr, p, createConst(expr, 10), LE);//a<=10
b = createOpExpr(expr, p, q, PLUS);//sum+a
c = createAssignStmt(expr, q, b);//sum = sum+a

d = createOpExpr(expr, p, createConst(expr, 1), PLUS);
e = createAssignStmt(expr, p, d); //a=a+1
f = createCompStmt(expr, c, e); //{sum = sum+a, a= a+1}
r = createWhileStmt(expr, a, f);//while

t = createOutStmt(expr, q);//print sum

o = createCompStmt(expr, p1, q1, r, t);

executeTree(expr, o);
}

void whileInputTest()
{
/*
a = 1
sum = 0
input(x)
while(a <= x){
sum = sum + a
a = a+1;
}
print(sum)
*/

tree expr;
Node *p, *q, *r, *s, *o, *u, *t,*p1,*q1;
p = createId(expr);//a
q = createId(expr);//sum
p1 = createAssignStmt(expr, p, 1);//a=1
q1 = createAssignStmt(expr, q, 0);//sum=0

Node *a, *b, *c, *d, *e, *f, *g;
g = createId(expr);//x
f = createInputStmt(expr,g);
u = createCompStmt(expr, p1, q1, f);//first 3 sentences. because Comp not support more than 4 children.

a = createOpExpr(expr, p, g, LE);//a<=x, x from input
b = createOpExpr(expr, p, q, PLUS);//sum+a
c = createAssignStmt(expr, q, b);//sum = sum+a

d = createOpExpr(expr, p, createConst(expr, 1), PLUS);
e = createAssignStmt(expr, p, d); //a=a+1
f = createCompStmt(expr, c, e); //{sum = sum+a, a= a+1}
r = createWhileStmt(expr, a, f);//while

t = createOutStmt(expr, q);//print sum

o = createCompStmt(expr, u, r, t);

executeTree(expr, o);
}
int main(int argc, char *argv[])
{
//assignTest();
//inputOutTest();
//ifTest();

//whileTest();
whileInputTest();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
[/code]

实现效果

最后放上一个支持用户输入的while循环,它支持用户手动输入一个值x,然后程序会计算1+2+…+x的结果,并打印输出。它对应的c语言代码如下:
a = 1
sum = 0
input(x)
while(a <= x){
sum = sum + a
a = a+1;
}
print(sum)
1
2
3
4
5
6
7
8
1
2
3
4
5
6
7
8
[/code]

效果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  语法树