Bulid Own Lisp C语言项目练习笔记
chapter 7 Evaluation
前六章的学习主要围绕C语言的基础语法以及一个mpc库文件的使用,编写了一个简单的pasring.c文件实现Polish Notation语法解析。第七章实现表达式的计算。
认识解析结构 mpc_ast_t
typedef struct mpc_ast_t{
char* tag;
char* contents
mpc_state_t state;
int children_num;
struct mpc_ast_t** children;
} mpc_ast_t;
获取总结点个数(类似于求树的总结点数)
int getChildNums(Tree* p){
if(p->childNums == 0) return 1;
if(p->childNums >= 1){
int thisTotal = 1;
for(int i = 0; i < childNums; i ++){
thisTotal += getChildNums(p->child[i]);
}
return thisTotal;
}
//给定程序出口,确保程序的健壮性
return 0;
}
Evaluation 递归求解算式的值(+ - * /)
引入三个库函数 atoi(), strstr(), strcmp()
如果所属标签含有“number”,直接将字符串转化为数字
如果该标签含有“expr”又不是“number” 则一定是一个(< operator > < expr >)的结构,此时第一个孩子child[0]一定是char类型的左括号,我们直接读取第二个孩子child[1]进行递归调用,依次类推,然后逐次计算,最后得到表达式的值。
long eval(mpc_ast_t* t) {
/* If tagged as number return it directly. */
if (strstr(t->tag, "number")) {
return atoi(t->contents);
}
/* The operator is always second child. */
char* op = t->children[1]->contents;
/* We store the third child in `x` */
long x = eval(t->children[2]);
/* Iterate the remaining children and combining. */
int i = 3;
while (strstr(t->children[i]->tag, "expr")) {
x = eval_op(x, op, eval(t->children[i]));
i++;
}
return x;
}
其中的eval_op函数就是如下的一个四则运算函数。
long eval_op(long x, char* op, long y) {
if (strcmp(op, "+") == 0) { return x + y; }
if (strcmp(op, "-") == 0) { return x - y; }
if (strcmp(op, "*") == 0) { return x * y; }
if (strcmp(op, "/") == 0) { return x / y; }
return 0;
}
运行效果如下