入门小练习:
找出给定语句内任意子表达式的print函数的最大参数个数
#include"slp.h" #include"prog1.h" #include<stdio.h> int maxargs(A_stm stm); int maxargsexlst(A_expList expList); int maxargsex(A_exp exp); int countargs(A_expList expList); int max(int temp1, int temp2) { return temp1 > temp2 ? temp1 : temp2; } int maxargsexlst(A_expList expList) { switch (expList->kind) { case A_pairExpList: { int temp1 = maxargsexlst(expList->u.pair.tail); int temp2 = maxargsex(expList->u.pair.head); return max(temp1, temp2); } case A_lastExpList: return maxargsex(expList->u.last); default: return 0; } } int maxargsex(A_exp exp) { switch (exp->kind) { case A_opExp: { int temp1 = maxargsex(exp->u.op.left); int temp2 = maxargsex(exp->u.op.right); return max(temp1, temp2); } case A_eseqExp: { int temp3 = maxargsex(exp->u.eseq.exp); int temp4 = maxargs(exp->u.eseq.stm); return max(temp3, temp4); } default: return 0; } } int maxargs(A_stm stm) { switch (stm->kind) { case A_compoundStm: { int temp1 = maxargs(stm->u.compound.stm1); int temp2 = maxargs(stm->u.compound.stm2); return max(temp1, temp2); } case A_assignStm: { A_exp tempExp = stm->u.assign.exp; return maxargsex(tempExp); } case A_printStm: return max(maxargsexlst(stm->u.print.exps), countargs(stm->u.print.exps)); default: return 0; } } int countargs(A_expList expList) { if (expList->kind == A_pairExpList) { return 1 + countargs(expList->u.pair.tail); } else return 1; } /**********************************************************/ int main() { A_stm stm = prog(); printf("%d",maxargs(stm)); //system("pause"); return 0; }
直线式程序语言的解释可以利用语法抽象的方法,理解程序短语可以抽象为树这种数据结构来分析。利用树结构的递归性去设计解释方法。
countargs是对A_printStm参数个数的分析
maxargs maxargsex maxargsexlst 是查找A_printStm
写一个函数
void interp(A_stm);
typedef struct table{ string id; int value; struct table* tail; }*Table_; typedef struct IntAndTable{ int i; Table_ t; }*IntAndTable_; Table_ Table(Table_ t, string id, int value); int lookUp(Table_ t, string id); Table_ updateTable(Table_ t, string id, int newResult); void interp(A_stm stm); Table_ interpStm(A_stm stm, Table_ t); int getOpResult(int x, int y, int kind); IntAndTable_ interpExp(A_exp exp, Table_ t); IntAndTable_ intAndTable(int i, Table_ t); IntAndTable_ interpAndPrint(A_expList expLst, Table_ t); Table_ Table(Table_ t,string id, int value) { Table_ temp = (Table_)checked_malloc(sizeof(*t)); temp->id = id; temp->value = value; temp->tail = t; return temp; } //返回id 所对应的值 int lookUp(Table_ t, string id) { Table_ curr = t; while (curr != NULL) { if (curr->id == id) return curr->value; curr = curr->tail; } assert(!curr); return 0; } //将变量的值插入在表的开头 Table_ updateTable(Table_ t, string id, int newResult) { Table_ temp = Table(t, id, newResult); return temp; } void interp(A_stm stm) { interpStm(stm,NULL); } Table_ interpStm(A_stm stm,Table_ t) { if (stm != NULL) { switch (stm->kind) { case A_compoundStm: t = interpStm(stm->u.compound.stm1, t); t = interpStm(stm->u.compound.stm2, t); break; case A_assignStm: { IntAndTable_ intTable = intAndTable(0, t); intTable = interpExp(stm->u.assign.exp, t); t=updateTable(t, stm->u.assign.id, intTable->i); break; } case A_printStm: interpAndPrint(stm->u.print.exps,t); break; } } return t; } //解释并打印表达式结果 IntAndTable_ interpAndPrint(A_expList expLst, Table_ t) { assert(expLst); IntAndTable_ intTable = intAndTable(0,t); while (expLst->kind == A_pairExpList) { intTable = interpExp(expLst->u.pair.head, intTable->t); expLst = expLst->u.pair.tail; } intTable = interpExp(expLst->u.last, intTable->t); printf("%d\n", intTable->i); } IntAndTable_ intAndTable(int i, Table_ t) { IntAndTable_ temp = (IntAndTable_)checked_malloc(sizeof(*temp)); temp->i = i; temp->t = t; return temp; } IntAndTable_ interpExp(A_exp exp, Table_ t) { if (exp == NULL) { return NULL; } else { IntAndTable_ intTable = intAndTable(0, t); switch (exp->kind) { case A_idExp: intTable->i = lookUp(t, exp->u.id); break; case A_numExp: intTable->i = exp->u.num; break; case A_opExp: intTable= interpExp(exp->u.op.left, t); int i = intTable->i; intTable = interpExp(exp->u.op.right, intTable->t); int j = intTable->i; intTable->i = getOpResult(i,j,exp->u.op.oper); break; case A_eseqExp: t = interpStm(exp->u.eseq.stm,t); intTable = interpExp(exp->u.eseq.exp, t); break; } return intTable; } } int getOpResult(int x, int y,int kind) { switch (kind) { case A_plus:return x + y; case A_minus:return x - y; case A_div:return x / y; case A_times:return x*y; } }
interpExp(A_exp exp,Table_ t) 是对exp的解释 返回表达式的值并更新映射表
为了在赋值语句的解释中不产生其他副作用,赋值语句将不对已有变量做修改 而是利用updateTable将新值更新到映射表