Root/
Source at commit 809e8142b53ba7227241d39d2c4057f7201087a9 created 9 years 2 months ago. By Werner Almesberger, gui.c (change_world): don't change color of the active frame | |
---|---|
1 | /* |
2 | * unparse.c - Dump an expression tree into a string |
3 | * |
4 | * Written 2009, 2012 by Werner Almesberger |
5 | * Copyright 2009, 2012 by Werner Almesberger |
6 | * |
7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by |
9 | * the Free Software Foundation; either version 2 of the License, or |
10 | * (at your option) any later version. |
11 | */ |
12 | |
13 | /* |
14 | * This is crazily inefficient but who cares :-) |
15 | */ |
16 | |
17 | #include <stdlib.h> |
18 | #include <stdio.h> |
19 | |
20 | #include "util.h" |
21 | #include "expr.h" |
22 | #include "unparse.h" |
23 | |
24 | |
25 | enum prec { |
26 | prec_add, |
27 | prec_mult, |
28 | prec_unary, |
29 | prec_primary, |
30 | }; |
31 | |
32 | |
33 | static int precedence(op_type op) |
34 | { |
35 | if (op == op_add || op == op_sub) |
36 | return prec_add; |
37 | if (op == op_mult || op == op_div) |
38 | return prec_mult; |
39 | if (op == op_minus) |
40 | return prec_unary; |
41 | if (op == op_num || op == op_string || op == op_var || |
42 | op == op_sin || op == op_cos || op == op_sqrt || op == op_floor) |
43 | return prec_primary; |
44 | abort(); |
45 | } |
46 | |
47 | |
48 | static char *merge3(char *a, const char *op, char *b) |
49 | { |
50 | char *buf; |
51 | |
52 | buf = alloc_size(strlen(op)+strlen(a)+strlen(b)+1); |
53 | sprintf(buf, "%s%s%s", a, op, b); |
54 | free(a); |
55 | free(b); |
56 | return buf; |
57 | } |
58 | |
59 | |
60 | static char *merge2(const char *op, char *a) |
61 | { |
62 | char *buf; |
63 | |
64 | buf = alloc_size(strlen(op)+strlen(a)+1); |
65 | sprintf(buf, "%s%s", op, a); |
66 | free(a); |
67 | return buf; |
68 | } |
69 | |
70 | |
71 | static char *unparse_op(const struct expr *expr, enum prec prec); |
72 | |
73 | |
74 | static char *unparse_fn(const char *name, const struct expr *expr) |
75 | { |
76 | char *buf, *tmp; |
77 | |
78 | tmp = unparse_op(expr->u.op.a, prec_add); |
79 | buf = alloc_size(strlen(name)+strlen(tmp)+3); |
80 | sprintf(buf, "%s(%s)", name, tmp); |
81 | free(tmp); |
82 | return buf; |
83 | } |
84 | |
85 | |
86 | static char *unparse_op(const struct expr *expr, enum prec prec) |
87 | { |
88 | char tmp[100]; |
89 | char *buf, *temp; |
90 | |
91 | if (prec > precedence(expr->op)) { |
92 | temp = unparse_op(expr, prec_add); |
93 | buf = alloc_size(strlen(temp)+3); |
94 | sprintf(buf, "(%s)", temp); |
95 | free(temp); |
96 | return buf; |
97 | } |
98 | if (expr->op == op_num) { |
99 | snprintf(tmp, sizeof(tmp), "%lg%s", |
100 | expr->u.num.n, str_unit(expr->u.num)); |
101 | return stralloc(tmp); |
102 | } |
103 | if (expr->op == op_string) |
104 | return stralloc_printf("\"%s\"", expr->u.str); |
105 | if (expr->op == op_var) |
106 | return stralloc(expr->u.var); |
107 | if (expr->op == op_minus) |
108 | return merge2("-", unparse_op(expr->u.op.a, prec_unary)); |
109 | if (expr->op == op_add) |
110 | return merge3(unparse_op(expr->u.op.a, prec_add), "+", |
111 | unparse_op(expr->u.op.b, prec_add)); |
112 | if (expr->op == op_sub) |
113 | return merge3(unparse_op(expr->u.op.a, prec_add), "-", |
114 | unparse_op(expr->u.op.b, prec_mult)); |
115 | if (expr->op == op_mult) |
116 | return merge3(unparse_op(expr->u.op.a, prec_mult), "*", |
117 | unparse_op(expr->u.op.b, prec_mult)); |
118 | if (expr->op == op_div) |
119 | return merge3(unparse_op(expr->u.op.a, prec_mult), "/", |
120 | unparse_op(expr->u.op.b, prec_primary)); |
121 | if (expr->op == op_sin) |
122 | return unparse_fn("sin", expr); |
123 | if (expr->op == op_cos) |
124 | return unparse_fn("cos", expr); |
125 | if (expr->op == op_sqrt) |
126 | return unparse_fn("sqrt", expr); |
127 | if (expr->op == op_floor) |
128 | return unparse_fn("floor", expr); |
129 | abort(); |
130 | } |
131 | |
132 | |
133 | char *unparse(const struct expr *expr) |
134 | { |
135 | return expr ? unparse_op(expr, prec_add) : stralloc(""); |
136 | } |
137 |
Branches:
master