Re: [SelectorsAPI] Analysis of Context-Rooted Queries

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/

Received on Thursday, 17 July 2008 11:36:19 UTC