W3C CSS-грамматика, синтаксические причуды

Я смотрел синтаксис CSS здесь и здесь, и я был поражен, увидев как маркерные постановки, так и грамматику, замусоренную простыми декларациями. Обычно пробел определяется один раз в лексере и пропускается, и его больше не видно. То же замечание.

Я предполагаю, что ориентация на пользовательские агенты, а не на истинные компиляторы, является частью мотивации здесь, а также требование действовать в условиях ошибок, но все же кажется довольно странным.

Являются ли реальными UA-овцами, которые анализируют CSS, действительно реализуются в соответствии с этими (этими) грамматиками?

РЕДАКТИРОВАНИЕ: причина вопроса - это фактически различные варианты LESS. less.js не понимает последовательные комментарии, а lessc.exe не понимает комментарии внутри селекторов. В этом отношении они даже не могут правильно проанализировать CSS, однако это определено. Поэтому я пошел посмотреть, какова фактическая грамматика CSS и...

Ответ 1

CSS, в то время как он похож на многие языки программирования, имеет некоторые редкие случаи, когда пробелы могут быть важными.


Скажем, у нас есть следующая базовая разметка:

<html>
    <head>
        <style type="text/css">
            .blueborder { width:200px; height:200px; border: solid 2px #00f; }
            .redborder  { width:100px; height:100px; margin:50px; border: solid 2px #f00; }
        </style>
    </head>

    <body>
        <div class="blueborder">
            <div class="redborder"></div>
        </div>
    </body>

</html>

Здесь нет ничего особенного, кроме div внутри div, с некоторыми стилями на нем, чтобы вы могли видеть разницу между ними.

Теперь добавим еще один класс и идентификатор в внешний div:

<div class="blueborder MyClass" id="MyDiv">
    <div class="redborder"></div>
</div>

Если я хочу дать задний фон внешнему div следующим образом:

.MyClass#MyDiv { background: #ccc; }

... тогда пробелы становятся важными. Приведенное выше правило создает внешний div, поскольку оно анализируется иначе, чем следующее:

.MyClass #MyDiv { background: #ccc; }

... который НЕ стирает внешний div.

Чтобы узнать, как они разбираются по-разному, вы можете посмотреть, как селекторы обозначены:

Пример1:

.MyClass#MyDiv -> DELIM IDENT HASH

Пример 2:

.MyClass #MyDiv -> DELIM IDENT S HASH

Если бы мы слепо игнорировали пробелы (как это обычно делают компиляторы), мы бы пропустили эту разницу.


С учетом сказанного я не подразумеваю, что этот грамматик хорош. У меня также есть много опыта в написании грамматик, и я съеживаюсь, глядя на эту грамматику. Самым простым решением было бы добавить символы # и . в токен IDENT, а затем все остальное станет намного проще.

Однако они не решили сделать это, и необходимость в пробеле является артефактом этого решения.