node_modules/gulp-sass/node_modules/node-sass/src/libsass/src/parser.cpp
// a complex selector combines a compound selector with another
// complex selector, with one of four combinator operations.
// the compound selector (head) is optional, since the combinator
// can come first in the whole selector sequence (like `> DIV').
a complex selector combines a compound selector with another
complex selector, with one of four combinator operations.
the compound selector (head) is optional, since the combinator
can come first in the whole selector sequence (like `> DIV').
a complex selector combines a compound selector with another complex selector with one of four combinator operations . the compound selector ( head ) is optional since the combinator can come first in the whole selector sequence ( like ` > DIV ' ) .
Complex_Selector* Parser::parse_complex_selector(bool in_root)
  {
    String* reference = 0;
    lex < block_comment >();
    Compound_Selector* lhs = 0;
    if (!peek_css< class_char < selector_combinator_ops > >()) {
      lhs = parse_compound_selector();
    }
    if (peek < end_of_file >()) return 0;
    Complex_Selector::Combinator combinator;
    if      (lex< exactly<'+'> >()) combinator = Complex_Selector::ADJACENT_TO;
    else if (lex< exactly<'~'> >()) combinator = Complex_Selector::PRECEDES;
    else if (lex< exactly<'>'> >()) combinator = Complex_Selector::PARENT_OF;
    else if (lex< sequence < exactly<'/'>, negate < exactly < '*' > > > >()) {
      combinator = Complex_Selector::REFERENCE;
      if (!lex < re_reference_combinator >()) return 0;
      reference = SASS_MEMORY_NEW(ctx.mem, String_Constant, pstate, lexed);
      if (!lex < exactly < '/' > >()) return 0; 
    }
    else    combinator = Complex_Selector::ANCESTOR_OF;
    if (!lhs && combinator == Complex_Selector::ANCESTOR_OF) return 0;
    Complex_Selector* sel = SASS_MEMORY_NEW(ctx.mem, Complex_Selector, pstate, combinator, lhs);
    sel->media_block(last_media_block);
    if (combinator == Complex_Selector::REFERENCE) sel->reference(reference);
    sel->has_line_break(peek_newline());
    if (!peek_css< class_char < complex_selector_delims > >()) {
      sel->tail(parse_complex_selector(true));
      if (sel->tail()) {
        if (sel->tail()->has_reference()) sel->has_reference(true);
        if (sel->tail()->has_placeholder()) sel->has_placeholder(true);
      }
    }
    if (!sel->has_reference() && !in_at_root && !in_root) {
      Parent_Selector* parent = SASS_MEMORY_NEW(ctx.mem, Parent_Selector, pstate);
      parent->media_block(last_media_block);
      Compound_Selector* head = SASS_MEMORY_NEW(ctx.mem, Compound_Selector, pstate);
      head->media_block(last_media_block);
      (*head) << parent;
      if (!sel->head()) { sel->head(head); }
      else {
        sel = SASS_MEMORY_NEW(ctx.mem, Complex_Selector, pstate, Complex_Selector::ANCESTOR_OF, head, sel);
        sel->media_block(last_media_block);
      }
    }
    return sel;
  }
Complex_Selector * Parser :: parse_complex_selector ( bool in_root ) { String * reference = 0 ; lex < block_comment > ( ) ; Compound_Selector * lhs = 0 ; if ( ! peek_css < class_char < selector_combinator_ops > > ( ) ) { lhs = parse_compound_selector ( ) ; } if ( peek < end_of_file > ( ) ) return 0 ; Complex_Selector :: Combinator combinator ; if ( lex < exactly < ' ' > > ( ) ) combinator = Complex_Selector :: ADJACENT_TO ; else if ( lex < exactly < ' ' > > ( ) ) combinator = Complex_Selector :: PRECEDES ; else if ( lex < exactly < ' ' > > ( ) ) combinator = Complex_Selector :: PARENT_OF ; else if ( lex < sequence < exactly < ' ' > , negate < exactly < ' ' > > > > ( ) ) { combinator = Complex_Selector :: REFERENCE ; if ( ! lex < re_reference_combinator > ( ) ) return 0 ; reference = SASS_MEMORY_NEW ( ctx . mem , String_Constant , pstate , lexed ) ; if ( ! lex < exactly < ' ' > > ( ) ) return 0 ; } else combinator = Complex_Selector :: ANCESTOR_OF ; if ( ! lhs && combinator == Complex_Selector :: ANCESTOR_OF ) return 0 ; Complex_Selector * sel = SASS_MEMORY_NEW ( ctx . mem , Complex_Selector , pstate , combinator , lhs ) ; sel -> media_block ( last_media_block ) ; if ( combinator == Complex_Selector :: REFERENCE ) sel -> reference ( reference ) ; sel -> has_line_break ( peek_newline ( ) ) ; if ( ! peek_css < class_char < complex_selector_delims > > ( ) ) { sel -> tail ( parse_complex_selector ( true ) ) ; if ( sel -> tail ( ) ) { if ( sel -> tail ( ) -> has_reference ( ) ) sel -> has_reference ( true ) ; if ( sel -> tail ( ) -> has_placeholder ( ) ) sel -> has_placeholder ( true ) ; } } if ( ! sel -> has_reference ( ) && ! in_at_root && ! in_root ) { Parent_Selector * parent = SASS_MEMORY_NEW ( ctx . mem , Parent_Selector , pstate ) ; parent -> media_block ( last_media_block ) ; Compound_Selector * head = SASS_MEMORY_NEW ( ctx . mem , Compound_Selector , pstate ) ; head -> media_block ( last_media_block ) ; ( * head ) << parent ; if ( ! sel -> head ( ) ) { sel -> head ( head ) ; } else { sel = SASS_MEMORY_NEW ( ctx . mem , Complex_Selector , pstate , Complex_Selector :: ANCESTOR_OF , head , sel ) ; sel -> media_block ( last_media_block ) ; } } return sel ; }
a complex selector combines a compound selector with another
complex selector, with one of four combinator operations.
a complex selector combines a compound selector with another complex selector with one of four combinator operations .
// parse the left hand side // special case if it starts with combinator ([+~>]) // parse the left hand side // check for end of file condition // parse combinator between lhs and rhs // comments are allowed, but not spaces? // ToDo: error msg? /* if (lex< zero >()) */ // lex < block_comment >(); // source position of a complex selector points to the combinator // ToDo: make sure we update pstate for ancestor of (lex < zero >()); // has linfeed after combinator? // sel->has_line_feed(has_line_feed); // check if we got the abort condition (ToDo: optimize) // parse next selector in sequence // ToDo: move this logic below into tail setter // add a parent selector if we are not in a root // also skip adding parent ref if we only have refs // create the objects to wrap parent selector reference // add simple selector // selector may not have any head yet // otherwise we need to create a new complex selector and set the old one as its tail // peek for linefeed and remember result on head // if (peek_newline()) head->has_line_break(true); // complex selector