skip to Main Content

According to the specs:

The <declaration-value> production matches any sequence of one
or more tokens, so long as the sequence does not contain
<bad-string-token>, <bad-url-token>,
unmatched <)-token>, <]-token>, or <}-token>,
or top-level <semicolon-token> tokens or <delim-token>
tokens with a value of !. It represents the entirety of what a valid
declaration can have as its value.

The <any-value> production is identical to
<declaration-value>, but also allows top-level
<semicolon-token> tokens and <delim-token> tokens with
a value of !. It represents the entirety of what valid CSS can be in
any context.

From that and the list of possible tokens defined at § 4. Tokenization, I came up with this grammar (whitespace are ignored):

function-token = ident-token '(' any-value ')'  # Different from the specs
delim-token = <whatever cannot be parsed as other tokens>
any-value = (
    ident-token | function-token | at-keyword-token | hash-token |
    string-token | url-token | delim-token | number-token |
    percentage-token | dimension-token | unicode-range-token |
    '<!--' | '-->' | ':' | ';' | ',' |
    '(' any-value ')' | '[' any-value ']' | '{' any-value '}'
)*

As you can see, I’m demanding that brackets be matched. As stated, a token cannot have unmatched closing brackets. However, it is not clear whether unmatched opening brackets are allowed.

Is my interpretation correct? If not, then what is wrong?

2

Answers


  1. Chosen as BEST ANSWER

    As far as I'm aware, the answer by @t.niese is correct, but I think the grammar in my question is also correct.

    That is, if you are parsing according to the CSS selector grammar (the actual context that I failed to mention in the question, and for that I'm sorry):

    <pseudo-class-selector> = ':' <ident-token> |
                              ':' <function-token> <any-value> ')'
    

    <any-value> cannot yield any unmatched closing brackets, which means that:

    • If the bracket stack ends with either a [ or a {, the last ) will be unmatched.

      div:has(span[foo="bar")
      
      'div' ':has(' 'span' '[' 'foo' '=' '"bar"' ')'
                                                 ^^^
      
    • If the bracket stack ends with a (, a <pseudo-class-selector> cannot be constructed since it lacks a closing ).

      div:has(span:has()
      
      'div' ':has(' {'span' ':has(' ')'}
                                         ^^^
      

    In conclusion, if "unmatched" here means the same thing as "mismatched", <any-value> must be balanced.


  2. I might be wrong, but that the specs only talks about prohibiting not matching closing braces is related to this part in the specs: 2.2. Error Handling

    If the stylesheet ends while any rule, declaration, function, string, etc. are still open, everything is automatically closed. This doesn’t make them invalid, though they may be incomplete and thus thrown away when they are verified against their grammar.

    So my interpretation there would be that if only the matching closing braces at the end of the stylesheet are missing, but besides that the <declaration-value> would be valid and complete when the auto close of those is performed, then that value would still be used.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search