Maciej Stachowiak wrote:
On May 5, 2008, at 2:13 PM, Lachlan Hunt wrote:
Define the methods to behave as if an implicit :scope selector and
descendant combinator were prepended to each selector in the group.
 ... Consider the following selector:

">strong, >em"

The expectation would be for this to become:

":scope >strong, :scope >em"

The question is how to parse and convert it.

... then prepending ":scope " and inserting " :scope " after every
comma before parsing would work. I believe this is currently true of
Selectors, though it may change in the future. I would guess the only
likely place for commas to appear would be in parameters to function-like pseudo-classes, in which case the algorithm above but excluding commas nested inside parentheses would be more
future-proof. Detail of the algorithm:

1. Initialize nesting level to 0
2. Initialize the output string to the empty string
3. While characters in the input string remain:
    3.a. read the current character
    3.b. if the current character is:
",": if the nesting level is 0, append ", :scope " to the output string "(": increase the nesting level by 1, and append "(" to the output string ")": decrease the nesting level by 1, and append ")" to the output string
       anything else: append the current character to the output string
     3.c. advance to the next character
4. return the output string

I started looking into this for the possibility of introducing queryScopedSelector(), or similar, into version 2, but it seems that this proposed pre-parse doesn't handle enough cases to be relible enough.

The solution would need to handle all of the following more complex cases involving escaped chars:

span[title="\""]
span[title='\'']
span[title="\\"]
span[title=\"\(\)]
span[title=\'\"]
div:foo(x,y)
div:foo(\(\))

Plus many other varations.

One possible solution would be to define that it uses a slightly modified grammar from ordinary Selectors. It would have everything the same, except that the selector production would become:

selector
: combinator? simple_selector_sequence [ combinator simple_selector_sequence ]*
  ;

http://www.w3.org/TR/css3-selectors/#w3cselgrammar

Then instead of requiring a pre-parse, inserting :scope and then parsing with the normal selector parser, implementations would modify their selector parsers to handle the optional combinator at the beginning and then I would define that :scope (or equivalent) is to be implied at the beginning of each selector.

Another solution is to use a slightly more complicated pre-parse than the one proposed above. I believe the following would work, unless I made a mistake.

1. Initialise nesting level to 0
2. Initialise the output string to the empty string
3. Initialise the escape flag to false
4. Begin tokenising in the Normal state

Normal state:
  Consume the next input character

  -> U+002C COMMA ","
If the escape flag is true, append "," to the output string and set the flag to false Otherwise, if the nesting level is 0, append ", :scope " to the output string
      Otherwise, treat it as per the "anything else" entry below.

  -> U+0022 QUOTATION MARK '"'
      Append '"' to the output string
      If the escape flag is true, set the flag to false
      Otherwise, switch to the Double-quoted string state

  -> U+0027 APOSTROPHE "'"
      Append "'" to the output string
      If the escape flag is true, set the flag to false
      Otherwise, switch to the Single-quoted string state

  -> U+0028 LEFT PARENTHESIS "("
      Append "(" to the output string
      If the escape flag is true, set the flag to false
      Otherwise, increase the nesting level by 1

  -> U+0029 RIGHT PARENTHESIS "("
      Append "(" to the output string
      If the escape flag is true, set the flag to false
      Otherwise, if the nesting level is greater than zero, decrease by 1

  -> U+005C REVERSE SOLIDUS "\"
      Append "\" to the output string
      If the escape flag is true, set the flag to false
      Otherwise, set the escape flag to true

  -> EOF
      Return the output string

  -> Anything Else
      If the escape flag is true, set the flag to false
      Append the current character to the output string


Double-quoted string state:
  Consume the next input character

  -> U+005C REVERSE SOLIDUS "\"
      Append "\" to the output string
      If the escape flag is true, set the flag to false
      Otherwise, set the escape flag to true

  -> U+0022 QUOTATION MARK '"'
      Append '"' to the output string
      If the escape flag is true, set the flag to false
      Otherwise, switch to the Normal state

  -> Anything Else
      Append the current character to the output string


Single-quoted string state:
  Consume the next input character

  -> U+005C REVERSE SOLIDUS "\"
      Append "\" to the output string
      If the escape flag is true, set the flag to false
      Otherwise, set the escape flag to true

  -> U+0027 APOSTROPHE "'"
      Append "'" to the output string
      If the escape flag is true, set the flag to false
      Otherwise, switch to the Normal state

  -> Anything Else
      Append the current character to the output string
      If the escape flag is true, set the flag to false


--
Lachlan Hunt - Opera Software
http://lachy.id.au/
http://www.opera.com/

Reply via email to