Ilya Zakharevich on Tue, 5 Dec 2000 17:18:43 -0500


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

Re: inequalities


On Tue, Dec 05, 2000 at 08:03:19PM +0100, Bill Allombert wrote:
> > I don't think that
> >   (a<b)<c
> > should necessarily give a warning; I think it would be nice if
> >   a<b<c
> > gave a warning.

> The problem is that the (yacc) parser eats up the parens, 
> so after parsing, there is no way to tell the difference.

But it is *your* grammar, not yacc's one, right?  So change it.  ;-)

Here is what I wrote in my "Programming and math" interview (plug:
http://www.math.ohio-state.edu/~ilya/interview/www-perl-com.html):

       Another pragmatically controlled thing may be an introduction
       of a "floating precedence" of operators. Obviously, one cannot
       design a precedence table with 20 or so levels of precedence
       which gives an "intuitively obvious" or "natural" parsing of
       parentheses-less expressions. A solution I can see is to make
       some operators have a range of precedence, and warn/die on
       expressions which do not have the same interpretation when the
       precedences of operators move in these ranges. (Think of A & B
       || C.) (I confess that I do not know how to do it with yacc, so
       this may be not so minor.)

At that time I did not know how to implement it with yacc, but now I
think I do.  Just make the production rules produce
subexpressions-with-preferences.  So instead of

  term	:	term ASSIGNOP term
			{ $$ = newASSIGNOP(OPf_STACKED, $1, $2, $3); }
	|	term POWOP term
			{ $$ = newBINOP($2, 0, scalar($1), scalar($3)); }
	|	term MULOP term
			{ $$ = newBINOP($2, 0, $1, scalar($3)); }
	|	term ADDOP term
			{ $$ = newBINOP($2, 0, $1, scalar($3)); }
	| '(' expr ')'  { $$ = sawparens($2); }

(with an appropiate precedences of assignment, power, multiplication
and addition) have it:

  term : term1 | term2_or_more

  term2_or_more : term2 | term3_or_more

  term3_or_more : term3 | term4_or_more

  term4_or_more : term4 | term5

  term1	:	term ASSIGNOP term
			{ $$ = newASSIGNOP(OPf_STACKED, $1, $2, $3); }

  term2	:	term ADDOP term
			{ $$ = newASSIGNOP(OPf_STACKED, $1, $2, $3); }

  term3	:	term MULOP term
			{ $$ = newASSIGNOP(OPf_STACKED, $1, $2, $3); }

  term4	:	term POWOP term
			{ $$ = newASSIGNOP(OPf_STACKED, $1, $2, $3); }

  term5	:	'(' term ')'
			{ $$ = sawparens($2); }

[So far it is a 1-to-1 translation of the older syntax.]

But now you can add "the sliding precedence".  Suppose you want to
make the precedence of MULOP slide between 3 and 4 (so it cannot be
used with POWOP without parentheses).  Then you change the POWOP rule to

  term3 :       term5 MULOP term5
                        { $$ = newASSIGNOP(OPf_STACKED, $1, $2, $3); }

        |	term MULOP term
                        { Report_error(); 
			  $$ = newASSIGNOP(OPf_STACKED, $1, $2, $3); }

I did not try to implement it, but I think it would work.

Ilya