xref: /csrg-svn/usr.bin/pascal/pxp/rval.c (revision 62193)
148112Sbostic /*-
2*62193Sbostic  * Copyright (c) 1980, 1993
3*62193Sbostic  *	The Regents of the University of California.  All rights reserved.
448112Sbostic  *
548112Sbostic  * %sccs.include.redist.c%
622238Sdist  */
722238Sdist 
822238Sdist #ifndef lint
9*62193Sbostic static char sccsid[] = "@(#)rval.c	8.1 (Berkeley) 06/06/93";
1048112Sbostic #endif /* not lint */
1122238Sdist 
1222238Sdist /*
132864Speter  * pxp - Pascal execution profiler
142864Speter  *
152864Speter  * Bill Joy UCB
162864Speter  * Version 1.2 January 1979
172864Speter  */
182864Speter 
192864Speter #include "0.h"
202864Speter #include "tree.h"
212864Speter 
222864Speter extern	char *opnames[];
232864Speter 
242864Speter #define alph(c)		((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
252864Speter /*
262864Speter  * Rvalue reformats an expression.
272864Speter  * Par is a flag indicating that the expression
282864Speter  * should be parenthesized if it is non-atomic.
292864Speter  */
rvalue(r,par)302864Speter rvalue(r, par)
312864Speter 	register int *r;
322864Speter 	int par;
332864Speter {
342864Speter 	register int *al;
352864Speter 	register char *opname;
362864Speter 
372864Speter 	if (r == NIL) {
382864Speter 		ppid("{expr}");
392864Speter 		return;
402864Speter 	}
412864Speter 	if (r[0] <= T_IN)
422864Speter 		opname = opnames[r[0]];
432864Speter 	switch (r[0]) {
442864Speter 		case T_BINT:
452864Speter 		case T_INT:
462864Speter 		case T_FINT:
472864Speter 			ppnumb(r[2]);
482864Speter 			if (r[0] == T_BINT)
492864Speter 				ppsep("b");
502864Speter 			return;
512864Speter 		case T_NIL:
522864Speter 			ppkw("nil");
532864Speter 			return;
542864Speter 		case T_FCALL:
552864Speter 			funccod(r);
562864Speter 			return;
572864Speter 		case T_VAR:
582864Speter 			lvalue(r);
592864Speter 			return;
602864Speter 		case T_CSET:
612864Speter 			cset(r);
622864Speter 			return;
632864Speter 		case T_STRNG:
642864Speter 			ppstr(r[2]);
652864Speter 			return;
662864Speter 	}
672864Speter 	if (par)
682864Speter 		ppbra("(");
692864Speter 	switch (r[0]) {
702864Speter 		default:
712864Speter 			panic("rval");
722864Speter 		case T_PLUS:
732864Speter 		case T_MINUS:
7416274Speter 			/*
7516274Speter 			 * if child is relational (bogus) or adding operator,
7616274Speter 			 * parenthesize child.
7716274Speter 			 * this has the unaesthetic property that
7816274Speter 			 * --i prints as -(-i), but is needed to catch
7916274Speter 			 * -(a+b) which must print as -(a+b), not as -a+b.
8016274Speter 			 * otherwise child has higher precedence
8116274Speter 			 * and need not be parenthesized.
8216274Speter 			 */
832864Speter 			ppop(r[0] == T_PLUS ? "+" : "-");
842864Speter 			al = r[2];
8516274Speter 			rvalue(r[2], prec(al) <= prec(r) || full);
862864Speter 			break;
872864Speter 		case T_NOT:
8816274Speter 			/*
8916274Speter 			 * if child is of lesser precedence
9016274Speter 			 * (i.e. not another not operator)
9116274Speter 			 * parenthesize it.
9216274Speter 			 * nested not operators need not be parenthesized
9316274Speter 			 * because it's a prefix operator.
9416274Speter 			 */
952864Speter 			ppkw(opname);
962864Speter 			ppspac();
9716274Speter 			al = r[2];
9816274Speter 			rvalue(r[2], prec(al) < prec(r) || full);
992864Speter 			break;
1002864Speter 		case T_EQ:
1012864Speter 		case T_NE:
1022864Speter 		case T_GE:
1032864Speter 		case T_LE:
1042864Speter 		case T_GT:
1052864Speter 		case T_LT:
10616274Speter 			/*
10716274Speter 			 * make the aesthetic choice to
10816274Speter 			 * fully parenthesize relational expressions,
10916274Speter 			 * in spite of left to right associativity.
11016274Speter 			 * note: there are no operators with lower precedence.
11116274Speter 			 */
1122864Speter 			al = r[2];
1132864Speter 			rvalue(al, prec(al) <= prec(r) || full);
1142864Speter 			goto rest;
1152864Speter 		case T_AND:
1162864Speter 		case T_OR:
1172864Speter 		case T_MULT:
1182864Speter 		case T_ADD:
1192864Speter 		case T_SUB:
1202864Speter 		case T_DIVD:
1212864Speter 		case T_MOD:
1222864Speter 		case T_DIV:
1232864Speter 		case T_IN:
12416274Speter 			/*
12516274Speter 			 * need not parenthesize left child
12616274Speter 			 * if it has equal precedence,
12716274Speter 			 * due to left to right associativity.
12816274Speter 			 * right child needs to be parenthesized
12916274Speter 			 * if it has equal (or lesser) precedence.
13016274Speter 			 */
1312864Speter 			al = r[2];
1322864Speter 			rvalue(al, prec(al) < prec(r) || full);
1332864Speter rest:
1342864Speter 			ppspac();
1352864Speter 			if (alph(opname[0]))
1362864Speter 				ppkw(opname);
1372864Speter 			else
1382864Speter 				ppop(opname);
1392864Speter 			ppspac();
1402864Speter 			al = r[3];
1412864Speter 			rvalue(al, prec(al) <= prec(r) || full);
1422864Speter 			break;
1432864Speter 	}
1442864Speter 	if (par)
1452864Speter 		ppket(")");
1462864Speter }
1472864Speter 
1482864Speter /*
1492864Speter  * Prec returns the precedence of an operator,
1502864Speter  * with larger numbers indicating stronger binding.
1512864Speter  * This is used to determine when parenthesization
1522864Speter  * is needed on subexpressions.
1532864Speter  */
prec(r)1542864Speter prec(r)
1552864Speter 	register int *r;
1562864Speter {
1572864Speter 
1582864Speter 	if (r == NIL)
1592864Speter 		return;
1602864Speter 	switch (r[0]) {
1612864Speter 		case T_NOT:
1622864Speter 			return (3);
1632864Speter 		case T_MULT:
1642864Speter 		case T_DIVD:
1652864Speter 		case T_DIV:
1662864Speter 		case T_MOD:
1672864Speter 		case T_AND:
1682864Speter 			return (2);
1692864Speter 		case T_ADD:
1702864Speter 		case T_SUB:
1712864Speter 		case T_OR:
1722864Speter 		case T_PLUS:
1732864Speter 		case T_MINUS:
1742864Speter 			return (1);
1752864Speter 		default:
1762864Speter 			return (0);
1772864Speter 	}
1782864Speter }
179