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