Skip to content

Commit

Permalink
[css-values-4] Add generic <boolean> grammar, so the increasing numbe…
Browse files Browse the repository at this point in the history
…r of places that use boolean exprs don't have to repeat themselves. #10457
  • Loading branch information
tabatkins committed Jun 17, 2024
1 parent 6993c34 commit 720ea28
Showing 1 changed file with 95 additions and 0 deletions.
95 changes: 95 additions & 0 deletions css-values-4/Overview.bs
Original file line number Diff line number Diff line change
Expand Up @@ -5345,6 +5345,101 @@ Appendix A: Recommended Minimum Ranges and Precision of Computed Values</h2>
-->


<!-- Big Text: bools -->

<h2 id="bools">
Boolean Expressions</h2>

In several contexts, CSS allows certain boolean tests
(things that can evaluate to true or false),
and allows them to be combined with the logical operators
AND, OR, and NOT to form more complicated boolean tests.
(For example, ''@media'' or ''@supports'' rules.)

All of these locations share a common grammatical structure,
with the only difference being what "base" boolean tests
are allowed,
and whether they use simple 2-value (true/false) boolean algebra,
or 3-value (true/false/unknown) Kleene logic.

For example, in ''@media'' only <<media-condition>>s are allowed,
with Kleene logic;
in ''@supports'' only <<supports-condition>>s are allowed,
with boolean logic.

As the overall structure of these grammars is identical
across the various usages of it,
and also complex enough to be non-trivial to reproduce
(and easy to accidentally do wrong),
this specification defines <<boolean>>,
a generic grammar for all such boolean tests.

<pre class=prod>
<dfn>&lt;boolean></dfn> = <<bool-not>> | <<bool-in-parens>> [ <<bool-and>>* | <<bool-or>>* ]
<dfn>&lt;boolean-without-or></dfn> = <<bool-not>> | <<bool-in-parens>> <<bool-and>>*
<dfn>&lt;bool-not></dfn> = not <<bool-in-parens>>
<dfn>&lt;bool-and></dfn> = and <<bool-in-parens>>
<dfn>&lt;bool-or></dfn> = or <<bool-in-parens>>
<dfn>&lt;bool-in-parens></dfn> = ( <<boolean>> ) | <<bool-test>> | <<general-enclosed>>
<dfn>&lt;general-enclosed></dfn> = [ <<function-token>> <<any-value>>? ) ] | [ ( <<any-value>>? ) ]
</pre>

Each specification using <<boolean>>
must define what things are valid as <dfn>&lt;bool-test></dfn> values

This comment has been minimized.

Copy link
@LeaVerou

LeaVerou Jun 17, 2024

Member

How would that work? Would they literally define

<bool-test> = ...

?

Wouldn’t that throw Bikeshed? Where would <bool-test> link to?

This comment has been minimized.

Copy link
@tabatkins

tabatkins Jun 17, 2024

Author Member

No, they'd define <media-feature> and then say "<<media-feature>> is allowed as a <<bool-test>> in the prelude of the ''@media'' rule".

This comment has been minimized.

Copy link
@LeaVerou

LeaVerou Jun 17, 2024

Member

Heh, I think our grammars have started to need F U N C T I O N S 😅

in that context,
and whether it uses 2-value or 3-value logic.
As well, <<bool-test>> values
<em>should</em> either be wrapped in parentheses
or be functions;
if a specification needs to express some conditions in a different way,
please contact the CSSWG for review.

: If using 2-value logic

This comment has been minimized.

Copy link
@LeaVerou

LeaVerou Jun 17, 2024

Member

This seems like it would be easier to parse as a table.

::
* Every <<bool-test>> must be defined to evaluate to either true or false.
* <<general-enclosed>> evaluates to false.
* <<bool-in-parens>> evaluates to the value of its contained <<boolean>>, <<bool-test>>, or <<general-enclosed>>
* <<bool-not>> evaluates to true if its contained <<bool-in-parens>> is false,
and false otherwise.
* A <<boolean>> with only a <<bool-not>> or <<bool-in-parens>> evaluates to that.
* A <<boolean>> with multiple <<bool-in-parens>> connected with ''and''
evaluates to true if all of its <<bool-in-parens>> are true,
and false otherwise.
* A <<boolean>> with multiple <<bool-in-parens>> connected with ''or''
evaluates to true if any of its <<bool-in-parens>> are true,
and false otherwise.

: If using 3-value logic
::
* Every <<bool-test>> must be defined to evaluate to either true, false, or unknown.
* <<general-enclosed>> evaluates to unknown.
* <<bool-in-parens>> evaluates to the value of its contained <<boolean>>, <<bool-test>>, or <<general-enclosed>>
* <<bool-not>> evaluates to true if its contained <<bool-in-parens>> is false,
false if it's true,
and unknown if it's unknown.
* A <<boolean>> with only a <<bool-not>> or <<bool-in-parens>> evaluates to that.
* A <<boolean>> with multiple <<bool-in-parens>> connected with ''and''
evaluates to true if all of its <<bool-in-parens>> are true,
false if any of them are false,
and unknown otherwise
(at least one unknown, but no false).
* A <<boolean>> with multiple <<bool-in-parens>> connected with ''or''
evaluates to true if any of its <<bool-in-parens>> are true,
false if all of them are false,
and unknown otherwise
(at least one unknown, but no true).
* If a "top-level" <<boolean>> is unknown,
and the containing context uses 2-value logic
(or doesn't specify otherwise),
it instead evaluates to false.

Note: That is, unknown doesn't "escape" a 3-value expression,
similar to how NaN doesn't "escape" a [=top-level calculation=]).




<!-- Big Text: lists

█▌ ████ ███▌ █████▌ ███▌
Expand Down

0 comments on commit 720ea28

Please sign in to comment.