xref: /original-bsd/usr.bin/pascal/pxp/rval.c (revision a95f03a8)
1 /*-
2  * Copyright (c) 1980 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)rval.c	5.2 (Berkeley) 04/16/91";
10 #endif /* not lint */
11 
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:
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 			 */
83 			ppop(r[0] == T_PLUS ? "+" : "-");
84 			al = r[2];
85 			rvalue(r[2], prec(al) <= prec(r) || full);
86 			break;
87 		case T_NOT:
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 			 */
95 			ppkw(opname);
96 			ppspac();
97 			al = r[2];
98 			rvalue(r[2], prec(al) < prec(r) || full);
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:
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 			 */
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:
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 			 */
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 }
179