Re: [css3-values] Adding min() and max() into calc() grammar

On Wednesday 17 February 2010 18:18:17 Zack Weinberg wrote:
> Bert Bos <bert@w3.org> wrote:
> > On Wednesday 16 December 2009 22:17:48 L. David Baron wrote:
> > > In http://www.w3.org/mid/4A71E157.20600@inkedblade.net the
> > > working group resolved to add min() and max() to calc(), as well
> > > as allowing them at the top level where calc() is allowed.  I
> > > don't think anybody has drafted any of the text for this yet,
> > > though, so here's an attempt at the grammar, which seems to me to
> > > be the main interesting part.
> >
> > [...]
> >
> > > (I don't see any reason to add min() and max() to <number-term>.)
> >
> > No reason, except maybe consistency. I don't mind either way.
>
> To minimize Web author confusion, I think the syntax - that is, the
> formulas allowed - should be independent of units to the maximum
> extent possible, and improper mixing of units should be a semantic
> error rather than a parse error.  Thus, I'm in favor of allowing
> min()/max() on unitless numbers, even though all current uses may be
> redundant.

That makes sense, and on looking at my grammar I see that there is 
another area where it is not consistent. It allows "3em + 5pc" but 
not "3 + 5".

And I forgot the PERCENTAGE token.

> Also, definitely -(expr) should be allowed.

Combining the above indeed leads to a simpler grammar, but one in which 
the semantic constraints are not expressed at all:

S       : calc | min | max;
calc    : "calc(" S* sum ")" S*;
min     : "min(" S* sum [ "," S* sum ]* ")" S*;
max     : "max(" S* sum [ "," S* sum ]* ")" S*;
sum     : product [ [ "+" | "-" ] S* product ]*;
product : unit [ [ "*" | "/" | "mod" ] S* unit ]*;
unit    : ["+"|"-"]? [ NUMBER S* | DIMENSION S* | PERCENTAGE S* |
          min | max | "(" S* sum ")" S* ];

The semantic constraints are as follows:

The context of the expression imposes a target type, which is one of 
length, frequency, angle, time, or number. Any PERCENTAGE token in the 
expression also has that type. The NUMBER tokens obviously are of type 
number, and the DIMENSION tokens have types that depend on their units 
(cm, px, deg, etc.). At each operator, the types of the left and right 
side have to be compared and, if compatible, they yield a result type, 
roughly as follows. (The following ignores precedence rules on the 
operators for simplicity.)

1) At ",", "+", "-":
   check: both sides have the same type
   return: that type
2) At "*":
   check: at least one side is "number"
   return: the type of the other side
3) At "/":
   check: either right side is "number," or both have the same type
   return: if the former, type of left side; otherwise "number"
4) At "mod"
   check: both sides have the same type
   return: "number"

It's easier to express in code than in English :-) I just tested it in 
Yacc with semantic actions. It's straightforward and short.

The type constraints can be tested at parse time and the declaration can 
thus be ignored if the type is not correct.

What cannot be tested at parse time is division by zero, because (unlike 
in the current draft) it is possible to divide by other things than 
constant numbers and thus it is possible to divide by something which 
turns out to be zero at run time.



Bert
-- 
  Bert Bos                                ( W 3 C ) http://www.w3.org/
  http://www.w3.org/people/bos                               W3C/ERCIM
  bert@w3.org                             2004 Rt des Lucioles / BP 93
  +33 (0)4 92 38 76 92            06902 Sophia Antipolis Cedex, France

Received on Thursday, 18 February 2010 21:21:15 UTC