Re: [csswg-drafts] [css-values-5] What is the MVP for inline conditionals on custom properties? (#10064)

The problem with omitting `else` (or something similar) is grammatical, and fundamental.

* The catch-all value might be empty, so we need to be able to distinguish between "has an empty catch-all" and "doesn't have a catch-all, is IACVT if nothing matches".
* `<declaration-value>` is *really* wide syntactically, so you can't distinguish it from other grammars. It needs an unambiguous marker preceding it to indicate "okay now it's time for decl-value".

In theory, we could address the first by the presence/absence of the argument separator. That is, `if(foo(): bar)` and `if(foo(): bar,)` could indicate the two states - the first is IACVT if `foo()` doesn't match, the second has an empty catch-all if `foo()` doens't match. But that's a tiny, difficult-to-distinguish syntax difference, absolutely a language-design no-no almost all of the time.

The second, tho, is unresolvable. In `if(foo(): bar, baz(): qux)`, `baz(): qux` is a perfectly valid `<declaration-value>`! So it's impossible to tell whether it was meant to be "two clauses with no catch-all, evaluating to either `bar`, `qux`, or IACVT" or "one clause with a catch-all, evaluating to either `foo` or `baz(): qux`".

Without an explicit and required start-of-clause syntax before the `<declaration-value>`, it's impossible to separate these two cases. A `<declaration-value>` simply cannot be directly preceded by a repetition or an optional value, ever, unless you explicitly specify that it's not allowed to match the grammar it's ambiguous with. 

So, we either need to remove the grammar, or require a prefix. Removing the grammar requires that we either carefully carve out the existing syntax only (which makes it potentially dangerous to evolve things in the future, or handle errors), or carve out a wide syntax (like, basically banning `<general-enclosed>: ` from the start) and that still somewhat limits our future evolution potential. Requiring a prefix has no such downsides; the prefix doesn't *have* to be spelled `else`, but if we don't use that, we'd be fighting against the headwind of *nearly every conditional syntax in the world*.

-------

While writing this comment, I realized that neither syntax can handle "single condition with a comma in its value, and no catch-all" well. That is, if you write `if(foo(): bar, baz)` it can't be interpreted as having a single condition with the value `bar, baz`; under the `else:` grammar it's just invalid syntax (`baz` isn't a valid condition/value pair), while under the implicit catch-all it's a value of `foo` and a catch-all value of `bar`. In both cases, you need to supply a second always-false condition to give yourself the opportunity to put a semicolon in and force the comma to be part of the value.

We should fix this with another special clause, I guess - say, just `else none`. Also a catch-all, but, resolves to IACVT, so you could write `if(foo(): bar, baz; else none)`. You *could* do this in other cases, to make it clear that you know your conditions aren't exhaustive and might not match, but normally you'd just say nothing and let it implicitly trigger IACVT.

(Note the lack of a `:` in the `else none`; required to make it unambiguous.)

-- 
GitHub Notification of comment by tabatkins
Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/10064#issuecomment-2327150180 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Tuesday, 3 September 2024 18:21:19 UTC