@@ -183,7 +183,7 @@ impl<'input> CssParser<'input> {
183183 } ) )
184184 }
185185
186- fn _create_invalidated_selector ( & self , location : & Location ) -> Rc < CssSelector > {
186+ fn create_invalidated_selector ( & self , location : & Location ) -> Rc < CssSelector > {
187187 Rc :: new ( CssSelector :: Invalidated ( InvalidatedNode {
188188 location : location. clone ( ) ,
189189 } ) )
@@ -248,6 +248,8 @@ impl<'input> CssParser<'input> {
248248 self . parse_media_query ( )
249249 } else if self . peek ( Token :: CssAtFontFace ) {
250250 self . parse_font_face ( )
251+ } else if self . peek ( Token :: CssAtImport ) {
252+ self . parse_import ( )
251253 } else {
252254 self . add_syntax_error ( & self . token . 1 , DiagnosticKind :: ExpectingDirective , diagarg ! [ self . token. 0 . clone( ) ] ) ;
253255 let d = self . create_invalidated_directive ( & self . tokenizer . cursor_location ( ) ) ;
@@ -317,6 +319,25 @@ impl<'input> CssParser<'input> {
317319 } ) )
318320 }
319321
322+ fn parse_import ( & mut self ) -> Rc < CssDirective > {
323+ self . mark_location ( ) ;
324+ self . next ( ) ;
325+
326+ let mut url: Option < String > = None ;
327+ if self . consume_keyword ( "url" ) {
328+ if let Ok ( facade) = self . parse_arguments ( ) {
329+ url = Some ( facade. parse_text ( ) . 0 ) ;
330+ }
331+ }
332+
333+ self . expect ( Token :: Semicolon ) ;
334+
335+ Rc :: new ( CssDirective :: Import ( CssImport {
336+ location : self . pop_location ( ) ,
337+ url,
338+ } ) )
339+ }
340+
320341 fn parse_opt_media_query_condition ( & mut self ) -> Option < Rc < CssMediaQueryCondition > > {
321342 let mut base: Option < Rc < CssMediaQueryCondition > > = None ;
322343 if self . peek_keyword ( "only" ) {
@@ -407,20 +428,46 @@ impl<'input> CssParser<'input> {
407428 fn parse_opt_selector ( & mut self ) -> Option < Rc < CssSelector > > {
408429 let mut base = self . parse_opt_base_selector ( ) ?;
409430
410- // Parse descendant combinators
411- while let Some ( right) = self . parse_opt_base_selector ( ) {
412- self . push_location ( & base. location ( ) ) ;
413- base = Rc :: new ( CssSelector :: Combinator ( CssCombinatorSelector {
414- location : self . pop_location ( ) ,
415- left : base,
416- right,
417- combinator_type : CssCombinatorType :: Descendant ,
418- } ) ) ;
431+ // Parse combinators
432+ loop {
433+ // CssCombinatorType::Child
434+ if self . consume ( Token :: Gt ) {
435+ self . push_location ( & base. location ( ) ) ;
436+ let right: Rc < CssSelector > = self . parse_base_selector ( ) ;
437+ base = Rc :: new ( CssSelector :: Combinator ( CssCombinatorSelector {
438+ location : self . pop_location ( ) ,
439+ left : base,
440+ right,
441+ combinator_type : CssCombinatorType :: Child ,
442+ } ) ) ;
443+ // CssCombinatorType::Descendant
444+ } else if let Some ( right) = self . parse_opt_base_selector ( ) {
445+ self . push_location ( & base. location ( ) ) ;
446+ base = Rc :: new ( CssSelector :: Combinator ( CssCombinatorSelector {
447+ location : self . pop_location ( ) ,
448+ left : base,
449+ right,
450+ combinator_type : CssCombinatorType :: Descendant ,
451+ } ) ) ;
452+ } else {
453+ break ;
454+ }
419455 }
420456
421457 Some ( base)
422458 }
423459
460+ fn parse_base_selector ( & mut self ) -> Rc < CssSelector > {
461+ let s = self . tokenizer . cursor_location ( ) ;
462+ let r = self . parse_opt_base_selector ( ) ;
463+ if let Some ( r) = r {
464+ r
465+ } else {
466+ self . add_syntax_error ( & s, DiagnosticKind :: ExpectingCssSelector , diagarg ! [ ] ) ;
467+ self . create_invalidated_selector ( & s)
468+ }
469+ }
470+
424471 fn parse_opt_base_selector ( & mut self ) -> Option < Rc < CssSelector > > {
425472 self . mark_location ( ) ;
426473 let mut namespace_prefix: Option < ( String , Location ) > = None ;
@@ -473,7 +520,14 @@ impl<'input> CssParser<'input> {
473520 if self . peek ( Token :: Colon ) {
474521 self . mark_location ( ) ;
475522 self . next ( ) ;
476- if self . consume_keyword ( "not" ) {
523+ if self . consume_keyword ( "nth-child" ) {
524+ let condition = if let Ok ( a) = self . parse_arguments ( ) {
525+ a. parse_nth_child_kind ( )
526+ } else {
527+ CssNthChildKind :: Invalidated
528+ } ;
529+ return Some ( Rc :: new ( CssSelectorCondition :: NthChild ( ( condition, self . pop_location ( ) ) ) ) ) ;
530+ } else if self . consume_keyword ( "not" ) {
477531 let condition = if let Ok ( a) = self . parse_arguments ( ) {
478532 a. parse_selector_condition ( )
479533 } else {
@@ -844,4 +898,21 @@ impl<'input> CssParserFacade<'input> {
844898 parser. expect_eof ( ) ;
845899 entries
846900 }
901+
902+ pub fn parse_nth_child_kind ( & self ) -> CssNthChildKind {
903+ let mut parser = self . create_parser ( ) ;
904+ parser. next ( ) ;
905+ if parser. consume_keyword ( "odd" ) {
906+ return CssNthChildKind :: Odd ;
907+ }
908+ if parser. consume_keyword ( "even" ) {
909+ return CssNthChildKind :: Even ;
910+ }
911+ if let Token :: CssNumber { value, .. } = parser. token . 0 . clone ( ) {
912+ parser. next ( ) ;
913+ return CssNthChildKind :: Number ( value. round ( ) . to_u32 ( ) . unwrap_or ( 0 ) ) ;
914+ }
915+ parser. expect_eof ( ) ;
916+ CssNthChildKind :: Invalidated
917+ }
847918}
0 commit comments