| 1136 | } |
| 1137 | |
| 1138 | void expr_print(struct expr *e, |
| 1139 | void (*fn)(void *, struct symbol *, const char *), |
| 1140 | void *data, int prevtoken) |
| 1141 | { |
| 1142 | if (!e) { |
| 1143 | fn(data, NULL, "y"); |
| 1144 | return; |
| 1145 | } |
| 1146 | |
| 1147 | if (expr_compare_type(prevtoken, e->type) > 0) |
| 1148 | fn(data, NULL, "("); |
| 1149 | switch (e->type) { |
| 1150 | case E_SYMBOL: |
| 1151 | if (e->left.sym->name) |
| 1152 | fn(data, e->left.sym, e->left.sym->name); |
| 1153 | else |
| 1154 | fn(data, NULL, "<choice>"); |
| 1155 | break; |
| 1156 | case E_NOT: |
| 1157 | fn(data, NULL, "!"); |
| 1158 | expr_print(e->left.expr, fn, data, E_NOT); |
| 1159 | break; |
| 1160 | case E_EQUAL: |
| 1161 | if (e->left.sym->name) |
| 1162 | fn(data, e->left.sym, e->left.sym->name); |
| 1163 | else |
| 1164 | fn(data, NULL, "<choice>"); |
| 1165 | fn(data, NULL, "="); |
| 1166 | fn(data, e->right.sym, e->right.sym->name); |
| 1167 | break; |
| 1168 | case E_LEQ: |
| 1169 | case E_LTH: |
| 1170 | if (e->left.sym->name) |
| 1171 | fn(data, e->left.sym, e->left.sym->name); |
| 1172 | else |
| 1173 | fn(data, NULL, "<choice>"); |
| 1174 | fn(data, NULL, e->type == E_LEQ ? "<=" : "<"); |
| 1175 | fn(data, e->right.sym, e->right.sym->name); |
| 1176 | break; |
| 1177 | case E_GEQ: |
| 1178 | case E_GTH: |
| 1179 | if (e->left.sym->name) |
| 1180 | fn(data, e->left.sym, e->left.sym->name); |
| 1181 | else |
| 1182 | fn(data, NULL, "<choice>"); |
| 1183 | fn(data, NULL, e->type == E_GEQ ? ">=" : ">"); |
| 1184 | fn(data, e->right.sym, e->right.sym->name); |
| 1185 | break; |
| 1186 | case E_UNEQUAL: |
| 1187 | if (e->left.sym->name) |
| 1188 | fn(data, e->left.sym, e->left.sym->name); |
| 1189 | else |
| 1190 | fn(data, NULL, "<choice>"); |
| 1191 | fn(data, NULL, "!="); |
| 1192 | fn(data, e->right.sym, e->right.sym->name); |
| 1193 | break; |
| 1194 | case E_OR: |
| 1195 | expr_print(e->left.expr, fn, data, E_OR); |
no test coverage detected