[comp.compilers] Minimizing parentheses in a postfix->infix converter output

acmfiu@fiu.edu (ACMFIU) (04/13/91)

I have a postfix->infix converter and need to output the least number of
parentheses as possible. The resulting infix expression is kept in a
binary tree and I just traverse the tree outputting the left/right
parentheses at each level.  This was done for convenience. but now I'd
like to make it better.  As this will involve, to my knowledge, some
lookahead to test the next operator, I don't see the binary tree as the
best data structure.  What can I use to make the lookahead "not hard" and
how would I go about doing what I want?

albert chin
[It is my recollection that there is an easy way to do paren minimization,
but the details escape me. Roughly, at each level you build the expression
string, and wrap a subexpression in parens if its operator binds looser
than the one in the current expression. -John]
-- 
Send compilers articles to compilers@iecc.cambridge.ma.us or
{ima | spdcc | world}!iecc!compilers.  Meta-mail to compilers-request.

ressler@cs.cornell.edu (Gene Ressler) (04/15/91)

In article <9104130521.AA00996@fiu.edu> acmfiu@fiu.edu (ACMFIU) writes:
>I have a postfix->infix converter and need to output the least number of
>parentheses as possible. ...
>
>albert chin
>[It is my recollection that there is an easy way to do paren minimization,
>but the details escape me. Roughly, at each level you build the expression
>string, and wrap a subexpression in parens if its operator binds looser
>than the one in the current expression. -John]

As I recall, something like this is an exercise in the Dragon Book chapter
on syntax-directed translation.  John is right.  In a SDT, you can pass
down an inherited attribute consisting of the current operator.  (In a
tree-walker, of course, this is just a function parameter.)  Call this
attribute `parent'.  Then each operator's rule looks at `parent' to see if
it should emit `( E op E )', when parent binds tighter than op or just `E
op E', when it doesn't.  You also need an inherited attribute `side' that
tells whether the current operator is the left or right (or only) child of
its parent.  This allows rules for non-associative operators to
parenthesize their emitted code correctly; e.g. for A * D / (B * C), the
rule for '*' causes parens to be emitted when `*' is the right child of
'/'.

There are other details depending on the language you want to emit, and
other approaches work, too.  For instance, if you pass the code itself as
an attribute (rather than emitting a stream), then you can put parens
around everything, but strip them off when the current op binds more
loosely than the child; here you're using synthesized attributes.  The
school of hard knocks has convinced me that a the time to write out the
SDT before coding things like this is paid back many-fold.  Good luck.

Gene
-- 
Send compilers articles to compilers@iecc.cambridge.ma.us or
{ima | spdcc | world}!iecc!compilers.  Meta-mail to compilers-request.

firth@sei.cmu.edu (Robert Firth) (04/15/91)

In article <9104130521.AA00996@fiu.edu> acmfiu@fiu.edu (ACMFIU) writes:
>I have a postfix->infix converter and need to output the least number of
>parentheses as possible. The resulting infix expression is kept in a
>binary tree and I just traverse the tree outputting the left/right
>parentheses at each level.

Easy.  You need to know the priority of the operators (obviously),
and, before emittinga subtree that isn't a leaf, you compare the
priority of its operator to that of the parent node.

If the sub has a higher priority, no parens.

If the sub has a lowe priority, parens always.

If the sub has the same priority, then you use parens around the
right subtree for a left-associative operator, and the left subtree
for a right-associative operator.

Examples:

	ab*c+ => a*b+c
	ab+c* => (a+b)*c
	abc-- => a-(b-c)

Hope that helps.
-- 
Send compilers articles to compilers@iecc.cambridge.ma.us or
{ima | spdcc | world}!iecc!compilers.  Meta-mail to compilers-request.

ge@dbf.kun.nl (Ge' Weijers) (04/15/91)

In comp.compilers acmfiu@fiu.edu writes:

>I have a postfix->infix converter and need to output the least number of
>parentheses as possible. The resulting infix expression is kept in a
>binary tree and I just traverse the tree outputting the left/right
>parentheses at each level.  ...

I assume you use a recursive traversal routine on the tree. The algorithm
is not hard. Just pass a priority to this expression-printer:

prio[ADD] := 1;
prio[MUL] := 2;

PROCEDURE PrintExpression (node: EXPRESSION, ctxPrio: PRIO);
BEGIN
	IF node is primary
	THEN PrintPrimary(node);
	ELSIF node is binary operator expression
	THEN
		IF ctxPrio > prio[node^.operator]
		THEN write('(');
		END;
		PrintExpression(node^.left, prio[node^.operator]+1);
		write(repr[node^.operator]);
		PrintExpression(node^.right, prio[node^.operator]);
		IF ctxPrio > prio[node^.operator]
		THEN write(')');
		END
	ELSE
		... (* other syntactic constructs *)
	END
END PrintExpression;

This works for languages that have left-to-right binding. The algorithm can
be made more general by adding left- and right-priority arrays, for instance
for right-to-left binding X ** Y operators.

As you can see deciding whether to print the parentheses requires knowledge
of the operator one level up in the tree. In RPN this operator can
be arbitrarily far ahead in the input.
I'm afraid you have to use a tree or reading the expression backwards.
This gives an unreversed Polish or prefix representation of the tree,
which can be scanned by an algorithm quite similar to the tree traversal
algorithm.

--
Ge' Weijers                                    Internet/UUCP: ge@cs.kun.nl
Faculty of Mathematics and Computer Science,   (uunet.uu.net!cs.kun.nl!ge)
University of Nijmegen, Toernooiveld 1         
6525 ED Nijmegen, the Netherlands              tel. +3180652483 (UTC-2)
-- 
Send compilers articles to compilers@iecc.cambridge.ma.us or
{ima | spdcc | world}!iecc!compilers.  Meta-mail to compilers-request.