#include // Expr.c #include #include typedef struct ExprStruct * Expr; typedef struct { Expr left; char op[4]; // only short operators! Expr right; } BinRec; typedef enum { tagNum, tagVar, tagBin } Tag; struct ExprStruct { //@{}@XPCL{record containing @B tagged union} Tag tag; union { long int num; // for tagNum char * name; // for tagVar BinRec bin; // for tagBin } u; //@{}@XPCL{@B {Note the @CP {struct} field label} ``@CP {u}''} }; Expr exprInt(long int n) { Expr result = malloc(sizeof(struct ExprStruct)); if ( result == NULL) return NULL; result->tag = tagNum; result->u.num = n; return result; } Expr exprVar(char * ident) { Expr result = malloc(sizeof(struct ExprStruct)); if ( result == NULL) return NULL; result->tag = tagVar; result->u.name = strdup(ident); return result; } Expr exprBin(char * op, Expr e1, Expr e2) { if ( op == NULL || strlen(op) > 3 ) return NULL; Expr result = malloc(sizeof(struct ExprStruct)); if ( result == NULL ) return NULL; result->tag = tagBin; result->u.bin.left = e1; result->u.bin.right = e2; strcpy(result->u.bin.op, op); return result; } long int exprEval(Expr e) { switch (e->tag) { case tagNum: return e->u.num; case tagBin: { long int val1 = exprEval(e->u.bin.left); long int val2 = exprEval(e->u.bin.right); switch ( e->u.bin.op[0] ) { // only for demonstration! case '+': return val1 + val2; case '-': return val1 - val2; case '*': return val1 * val2; case '/': return val1 / val2; default: fprintf(stderr,"exprEval: illegal operator `%s'\n", e->u.bin.op); }} break; case tagVar: fprintf(stderr,"exprEval: unexpected variable `%s'\n", e->u.name); break; default: fprintf(stderr,"exprEval: illegal tag\n"); } exit(1); } // all error exit goes through this