zen.c (4015B)
1 #include "zen.h" 2 #include "schema.h" 3 #include "gardener.h" 4 5 typedef enum { 6 OP_START, 7 OP_FILL, 8 OP_DONE, 9 OP_SUB, 10 OP_SUP, 11 OP_NOOP 12 } op_type; 13 14 struct garden { 15 gardener *gardener; 16 garden_status status; 17 op_type next; 18 symbol a; 19 symbol b; 20 }; 21 22 char* 23 next_symbol_meaning(garden_status s, op_type next) 24 { 25 if (s == ERROR) return "enlightenment"; 26 if (s == WAITING_FOR_OP) return "operation"; 27 28 switch (next) { 29 case OP_NOOP: 30 return "nothing"; 31 case OP_FILL: 32 if (s == WAITING_FOR_B) 33 return "key"; 34 else 35 return "value"; 36 case OP_START: 37 return "constructor"; 38 case OP_DONE: 39 return "enlightenment"; 40 case OP_SUB: 41 if (s == WAITING_FOR_B) 42 return "key"; 43 else 44 return "constructor"; 45 case OP_SUP: 46 if (s == WAITING_FOR_B) 47 return "constructor"; 48 else 49 return "key"; 50 } 51 return "enlightenment"; 52 } 53 54 void 55 display_garden(FILE *f, garden *g) 56 { 57 show(f, g->gardener); 58 fprintf(f, "\nWaiting for %s.\n", 59 next_symbol_meaning(g->status, g->next)); 60 } 61 62 garden* 63 new_garden(schema* s) 64 { 65 garden *g = malloc(sizeof(garden)); 66 g->gardener = new_gardener(s); 67 g->status = WAITING_FOR_OP; 68 return g; 69 } 70 71 garden_status 72 get_status(garden *g) 73 { 74 return g->status; 75 } 76 77 op_type 78 symbol_to_op(symbol s) 79 { 80 if (s == intern("start") || s == intern("@")) 81 return OP_START; 82 else if (s == intern("fill") || s == intern("!")) 83 return OP_FILL; 84 else if (s == intern("done") || s == intern("}")) 85 return OP_DONE; 86 else if (s == intern("sub") || s == intern("{")) 87 return OP_SUB; 88 else if (s == intern("sup") || s == intern("^")) 89 return OP_SUP; 90 else 91 return OP_NOOP; 92 } 93 94 garden_status 95 next_status_for_op(op_type op) 96 { 97 switch (op) { 98 case OP_NOOP: 99 return ERROR; 100 case OP_START: 101 return WAITING_FOR_A; 102 case OP_FILL: 103 return WAITING_FOR_B; 104 case OP_DONE: 105 return WAITING_FOR_OP; 106 case OP_SUB: 107 return WAITING_FOR_B; 108 case OP_SUP: 109 return WAITING_FOR_B; 110 } 111 return ERROR; 112 } 113 114 void 115 end_op(garden *g) 116 { 117 if (get_error(g->gardener) != OK) 118 g->status = ERROR; 119 else 120 g->status = WAITING_FOR_OP; 121 } 122 123 void 124 exec_op(garden *g) 125 { 126 switch (g->next) { 127 128 case OP_START: 129 start(g->gardener, g->a); 130 end_op(g); 131 break; 132 133 case OP_FILL: 134 fill(g->gardener, g->b, g->a); 135 end_op(g); 136 break; 137 138 case OP_NOOP: 139 g->status = ERROR; 140 break; 141 142 case OP_DONE: 143 done(g->gardener); 144 end_op(g); 145 break; 146 147 case OP_SUB: 148 sub(g->gardener, g->b, g->a); 149 end_op(g); 150 break; 151 152 case OP_SUP: 153 sup(g->gardener, g->b, g->a); 154 end_op(g); 155 break; 156 } 157 } 158 159 void 160 check_b(garden *g) 161 { 162 switch (g->next) { 163 164 case OP_START: 165 g->status = ERROR; 166 break; 167 168 case OP_NOOP: 169 g->status = ERROR; 170 break; 171 172 case OP_FILL: 173 if (has_key(get_cur_schema(g->gardener), 174 get_cur_constructor(g->gardener), 175 g->b) && 176 takes_leaf(get_cur_schema(g->gardener), 177 get_cur_constructor(g->gardener), 178 g->b)) { 179 g->status = WAITING_FOR_A; 180 } else { 181 g->status = ERROR; 182 } 183 break; 184 185 case OP_DONE: 186 g->status = ERROR; 187 break; 188 189 case OP_SUB: 190 if (has_key(get_cur_schema(g->gardener), 191 get_cur_constructor(g->gardener), 192 g->b)) { 193 g->status = WAITING_FOR_A; 194 } else { 195 g->status = ERROR; 196 } 197 break; 198 199 case OP_SUP: 200 if (is_constructor(get_cur_schema(g->gardener), 201 g->b)) { 202 g->status = WAITING_FOR_A; 203 } else { 204 g->status = ERROR; 205 } 206 } 207 } 208 209 bool 210 takes_args(op_type op) 211 { 212 switch (op) { 213 case OP_FILL: 214 case OP_SUB: 215 case OP_SUP: 216 case OP_START: 217 return true; 218 case OP_NOOP: 219 case OP_DONE: 220 /* FALLTHROUGH */ 221 } 222 return false; 223 } 224 225 void 226 instruct(garden *g, symbol s) 227 { 228 (void)s; 229 switch (g->status) { 230 231 case WAITING_FOR_OP: 232 g->next = symbol_to_op(s); 233 if (takes_args(g->next)) { 234 g->status = next_status_for_op(g->next); 235 } else { 236 exec_op(g); 237 } 238 break; 239 240 case WAITING_FOR_A: 241 g->a = s; 242 exec_op(g); 243 break; 244 245 case WAITING_FOR_B: 246 g->b = s; 247 check_b(g); 248 break; 249 250 case ERROR: 251 break; 252 253 } 254 }