Commit | Line | Data |
---|---|---|
0fc6e47b KB |
1 | /*- |
2 | * Copyright (c) 1980 The Regents of the University of California. | |
3 | * All rights reserved. | |
4 | * | |
5 | * %sccs.include.redist.c% | |
252367af DF |
6 | */ |
7 | ||
8 | #ifndef lint | |
0fc6e47b KB |
9 | static char sccsid[] = "@(#)rval.c 5.2 (Berkeley) %G%"; |
10 | #endif /* not lint */ | |
252367af | 11 | |
fc670973 PK |
12 | /* |
13 | * pxp - Pascal execution profiler | |
14 | * | |
15 | * Bill Joy UCB | |
16 | * Version 1.2 January 1979 | |
17 | */ | |
18 | ||
19 | #include "0.h" | |
20 | #include "tree.h" | |
21 | ||
22 | extern char *opnames[]; | |
23 | ||
24 | #define alph(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) | |
25 | /* | |
26 | * Rvalue reformats an expression. | |
27 | * Par is a flag indicating that the expression | |
28 | * should be parenthesized if it is non-atomic. | |
29 | */ | |
30 | rvalue(r, par) | |
31 | register int *r; | |
32 | int par; | |
33 | { | |
34 | register int *al; | |
35 | register char *opname; | |
36 | ||
37 | if (r == NIL) { | |
38 | ppid("{expr}"); | |
39 | return; | |
40 | } | |
41 | if (r[0] <= T_IN) | |
42 | opname = opnames[r[0]]; | |
43 | switch (r[0]) { | |
44 | case T_BINT: | |
45 | case T_INT: | |
46 | case T_FINT: | |
47 | ppnumb(r[2]); | |
48 | if (r[0] == T_BINT) | |
49 | ppsep("b"); | |
50 | return; | |
51 | case T_NIL: | |
52 | ppkw("nil"); | |
53 | return; | |
54 | case T_FCALL: | |
55 | funccod(r); | |
56 | return; | |
57 | case T_VAR: | |
58 | lvalue(r); | |
59 | return; | |
60 | case T_CSET: | |
61 | cset(r); | |
62 | return; | |
63 | case T_STRNG: | |
64 | ppstr(r[2]); | |
65 | return; | |
66 | } | |
67 | if (par) | |
68 | ppbra("("); | |
69 | switch (r[0]) { | |
70 | default: | |
71 | panic("rval"); | |
72 | case T_PLUS: | |
73 | case T_MINUS: | |
15771929 PK |
74 | /* |
75 | * if child is relational (bogus) or adding operator, | |
76 | * parenthesize child. | |
77 | * this has the unaesthetic property that | |
78 | * --i prints as -(-i), but is needed to catch | |
79 | * -(a+b) which must print as -(a+b), not as -a+b. | |
80 | * otherwise child has higher precedence | |
81 | * and need not be parenthesized. | |
82 | */ | |
fc670973 PK |
83 | ppop(r[0] == T_PLUS ? "+" : "-"); |
84 | al = r[2]; | |
15771929 | 85 | rvalue(r[2], prec(al) <= prec(r) || full); |
fc670973 PK |
86 | break; |
87 | case T_NOT: | |
15771929 PK |
88 | /* |
89 | * if child is of lesser precedence | |
90 | * (i.e. not another not operator) | |
91 | * parenthesize it. | |
92 | * nested not operators need not be parenthesized | |
93 | * because it's a prefix operator. | |
94 | */ | |
fc670973 PK |
95 | ppkw(opname); |
96 | ppspac(); | |
15771929 PK |
97 | al = r[2]; |
98 | rvalue(r[2], prec(al) < prec(r) || full); | |
fc670973 PK |
99 | break; |
100 | case T_EQ: | |
101 | case T_NE: | |
102 | case T_GE: | |
103 | case T_LE: | |
104 | case T_GT: | |
105 | case T_LT: | |
15771929 PK |
106 | /* |
107 | * make the aesthetic choice to | |
108 | * fully parenthesize relational expressions, | |
109 | * in spite of left to right associativity. | |
110 | * note: there are no operators with lower precedence. | |
111 | */ | |
fc670973 PK |
112 | al = r[2]; |
113 | rvalue(al, prec(al) <= prec(r) || full); | |
114 | goto rest; | |
115 | case T_AND: | |
116 | case T_OR: | |
117 | case T_MULT: | |
118 | case T_ADD: | |
119 | case T_SUB: | |
120 | case T_DIVD: | |
121 | case T_MOD: | |
122 | case T_DIV: | |
123 | case T_IN: | |
15771929 PK |
124 | /* |
125 | * need not parenthesize left child | |
126 | * if it has equal precedence, | |
127 | * due to left to right associativity. | |
128 | * right child needs to be parenthesized | |
129 | * if it has equal (or lesser) precedence. | |
130 | */ | |
fc670973 PK |
131 | al = r[2]; |
132 | rvalue(al, prec(al) < prec(r) || full); | |
133 | rest: | |
134 | ppspac(); | |
135 | if (alph(opname[0])) | |
136 | ppkw(opname); | |
137 | else | |
138 | ppop(opname); | |
139 | ppspac(); | |
140 | al = r[3]; | |
141 | rvalue(al, prec(al) <= prec(r) || full); | |
142 | break; | |
143 | } | |
144 | if (par) | |
145 | ppket(")"); | |
146 | } | |
147 | ||
148 | /* | |
149 | * Prec returns the precedence of an operator, | |
150 | * with larger numbers indicating stronger binding. | |
151 | * This is used to determine when parenthesization | |
152 | * is needed on subexpressions. | |
153 | */ | |
154 | prec(r) | |
155 | register int *r; | |
156 | { | |
157 | ||
158 | if (r == NIL) | |
159 | return; | |
160 | switch (r[0]) { | |
161 | case T_NOT: | |
162 | return (3); | |
163 | case T_MULT: | |
164 | case T_DIVD: | |
165 | case T_DIV: | |
166 | case T_MOD: | |
167 | case T_AND: | |
168 | return (2); | |
169 | case T_ADD: | |
170 | case T_SUB: | |
171 | case T_OR: | |
172 | case T_PLUS: | |
173 | case T_MINUS: | |
174 | return (1); | |
175 | default: | |
176 | return (0); | |
177 | } | |
178 | } |