虎书P8问题(2)——直线式程序解释器
《虎书》确实彪悍,绪论里就留给读者实践性这么强的问题,对于中文版第8页上的问题(2),我的答案如下:p8q2.h:
#ifndef P8Q2_H#define P8Q2_H#include "util.h"#include "slp.h"typedef struct table* Table_;struct table{string id; int value; Table_ tail;};Table_ Table(string id, int value, Table_ tail);Table_ interpStm(A_stm stm, Table_ t);struct intAndTable{int value; Table_ t;};typedef struct intAndTable* IntAndTable_;IntAndTable_ IntAndTable(int value, Table_ t);IntAndTable_ interpExp(A_exp exp, Table_ t);#endif
p8q2.c:
#include "p8q2.h"#include <stdio.h>#include <stdlib.h>Table_ update(string id, int value, Table_ t);IntAndTable_ interpAndPrintExp(A_exp exp, Table_ t);Table_ Table(string id, int value, Table_ tail){ Table_ t = checked_malloc(sizeof(t)); t->id = id; t->value = value; t->tail = tail; return t;}IntAndTable_ IntAndTable(int value, Table_ t){ IntAndTable_ iat = checked_malloc(sizeof(iat)); iat->value = value; iat->t = t; return iat;}Table_ interpStm(A_stm stm, Table_ t){ Table_ t1; IntAndTable_ iat; if(stm->kind == A_compoundStm){t1 = interpStm(stm->u.compound.stm1, t);return interpStm(stm->u.compound.stm2, t1); }else if(stm->kind == A_assignStm){IntAndTable_ iat = interpExp(stm->u.assign.exp, t);return update(stm->u.assign.id, iat->value, iat->t); }else if(stm->kind == A_printStm){// To support one-by-one print, interprete exp-by-expif(stm->u.print.exps->kind == A_lastExpList){ iat = interpAndPrintExp(stm->u.print.exps->u.last, t); return iat->t;}else if(stm->u.print.exps->kind == A_pairExpList){ A_expList list = stm->u.print.exps; while(list->kind == A_pairExpList){iat = interpAndPrintExp(list->u.pair.head, t);t = iat->t;list = list->u.pair.tail; } iat = interpAndPrintExp(list->u.last, t); return iat->t;}else{ printf("Invalid print exps!\n"); exit(1);} }else{printf("Statement type error!\n");exit(1); }}IntAndTable_ interpExp(A_exp exp, Table_ t){ int value1; IntAndTable_ iat1, iat2; Table_ t1; if(exp->kind == A_idExp){value1 = lookUp(exp->u.id, t);return IntAndTable(value1, t); }else if(exp->kind == A_numExp){return IntAndTable(exp->u.num, t); }else if(exp->kind == A_opExp){iat1 = interpExp(exp->u.op.left, t);iat2 = interpExp(exp->u.op.right, iat1->t);switch(exp->u.op.oper){ case A_plus:value1 = iat1->value + iat2->value;break; case A_minus:value1 = iat1->value - iat2->value;break; case A_times:value1 = iat1->value * iat2->value;break; case A_div:value1 = iat1->value / iat2->value;break; default: printf("Invalid operator!\n");exit(1);}return IntAndTable(value1, iat2->t); }else if(exp->kind == A_eseqExp){t1 = interpStm(exp->u.eseq.stm, t);return interpExp(exp->u.eseq.exp, t1); }else{printf("Invalid operation type!\n");exit(1); }}Table_ update(string id, int value, Table_ t){ return Table(id, value, t);}int lookUp(string key, Table_ t){ while(t){// The initail table was a NULLif(strcmp(key, t->id) == 0){ return t->value;}t = t->tail; } return 0;// initial with 0}IntAndTable_ interpAndPrintExp(A_exp exp, Table_ t){ IntAndTable_ iat = interpExp(exp, t); printf("%d ", iat->value); return iat;}
main.c:
#include <stdio.h>#include "util.h"#include "prog1.h"#include "slp.h"#include "p8q1.h"#include "p8q2.h"int main(){ interpStm(prog(), NULL); printf("\n"); return 0;}
输出结果:
8 7 80
页:
[1]