@@ -6,7 +6,6 @@ use std::ops::Range;
6
6
use std:: ascii:: AsciiExt ;
7
7
use std:: ops:: BitOr ;
8
8
use std:: borrow:: Cow ;
9
- use std:: ops;
10
9
use tokenizer:: { self , Token , NumericValue , PercentageValue , Tokenizer , SourceLocation } ;
11
10
12
11
@@ -61,46 +60,21 @@ impl<'a, T> ParseError<'a, T> {
61
60
}
62
61
}
63
62
64
- /// Like std::borrow::Cow, except the borrowed variant contains a mutable
65
- /// reference.
66
- enum MaybeOwned < ' a , T : ' a > {
67
- Owned ( T ) ,
68
- Borrowed ( & ' a mut T ) ,
69
- }
70
-
71
- impl < ' a , T > ops:: Deref for MaybeOwned < ' a , T > {
72
- type Target = T ;
73
-
74
- fn deref < ' b > ( & ' b self ) -> & ' b T {
75
- match * self {
76
- MaybeOwned :: Owned ( ref t) => t,
77
- MaybeOwned :: Borrowed ( ref pointer) => & * * pointer,
78
- }
79
- }
80
- }
81
-
82
- impl < ' a , T > ops:: DerefMut for MaybeOwned < ' a , T > {
83
- fn deref_mut < ' b > ( & ' b mut self ) -> & ' b mut T {
84
- match * self {
85
- MaybeOwned :: Owned ( ref mut t) => t,
86
- MaybeOwned :: Borrowed ( ref mut pointer) => & mut * * pointer,
87
- }
88
- }
89
- }
63
+ /// The owned input for a parser.
64
+ pub struct ParserInput < ' t > ( Tokenizer < ' t > ) ;
90
65
91
- impl < ' a , T > Clone for MaybeOwned < ' a , T > where T : Clone {
92
- fn clone ( & self ) -> MaybeOwned < ' a , T > {
93
- MaybeOwned :: Owned ( ( * * self ) . clone ( ) )
66
+ impl < ' t > ParserInput < ' t > {
67
+ /// Create a new input for a parser.
68
+ pub fn new ( input : & ' t str ) -> ParserInput < ' t > {
69
+ ParserInput ( Tokenizer :: new ( input) )
94
70
}
95
71
}
96
72
97
-
98
73
/// A CSS parser that borrows its `&str` input,
99
74
/// yields `Token`s,
100
75
/// and keeps track of nested blocks and functions.
101
- #[ derive( Clone ) ]
102
76
pub struct Parser < ' i : ' t , ' t > {
103
- tokenizer : MaybeOwned < ' t , Tokenizer < ' i > > ,
77
+ tokenizer : & ' t mut ParserInput < ' i > ,
104
78
/// If `Some(_)`, .parse_nested_block() can be called.
105
79
at_start_of : Option < BlockType > ,
106
80
/// For parsers from `parse_until` or `parse_nested_block`
@@ -203,12 +177,12 @@ impl Delimiters {
203
177
}
204
178
}
205
179
206
- impl < ' i , ' t > Parser < ' i , ' t > {
180
+ impl < ' i : ' t , ' t > Parser < ' i , ' t > {
207
181
/// Create a new parser
208
182
#[ inline]
209
- pub fn new ( input : & ' i str ) -> Parser < ' i , ' i > {
183
+ pub fn new ( input : & ' t mut ParserInput < ' i > ) -> Parser < ' i , ' t > {
210
184
Parser {
211
- tokenizer : MaybeOwned :: Owned ( Tokenizer :: new ( input) ) ,
185
+ tokenizer : input,
212
186
at_start_of : None ,
213
187
stop_before : Delimiter :: None ,
214
188
}
@@ -244,7 +218,7 @@ impl<'i, 't> Parser<'i, 't> {
244
218
#[ inline]
245
219
pub fn position ( & self ) -> SourcePosition {
246
220
SourcePosition {
247
- position : self . tokenizer . position ( ) ,
221
+ position : ( self . tokenizer . 0 ) . position ( ) ,
248
222
at_start_of : self . at_start_of ,
249
223
}
250
224
}
@@ -255,35 +229,35 @@ impl<'i, 't> Parser<'i, 't> {
255
229
/// Should only be used with `SourcePosition` values from the same `Parser` instance.
256
230
#[ inline]
257
231
pub fn reset ( & mut self , new_position : SourcePosition ) {
258
- self . tokenizer . reset ( new_position. position ) ;
232
+ ( self . tokenizer . 0 ) . reset ( new_position. position ) ;
259
233
self . at_start_of = new_position. at_start_of ;
260
234
}
261
235
262
236
/// Start looking for `var()` functions. (See the `.seen_var_functions()` method.)
263
237
#[ inline]
264
238
pub fn look_for_var_functions ( & mut self ) {
265
- self . tokenizer . look_for_var_functions ( )
239
+ ( self . tokenizer . 0 ) . look_for_var_functions ( )
266
240
}
267
241
268
242
/// Return whether a `var()` function has been seen by the tokenizer since
269
243
/// either `look_for_var_functions` was called, and stop looking.
270
244
#[ inline]
271
245
pub fn seen_var_functions ( & mut self ) -> bool {
272
- self . tokenizer . seen_var_functions ( )
246
+ ( self . tokenizer . 0 ) . seen_var_functions ( )
273
247
}
274
248
275
249
/// Start looking for viewport percentage lengths. (See the `seen_viewport_percentages`
276
250
/// method.)
277
251
#[ inline]
278
252
pub fn look_for_viewport_percentages ( & mut self ) {
279
- self . tokenizer . look_for_viewport_percentages ( )
253
+ ( self . tokenizer . 0 ) . look_for_viewport_percentages ( )
280
254
}
281
255
282
256
/// Return whether a `vh`, `vw`, `vmin`, or `vmax` dimension has been seen by the tokenizer
283
257
/// since `look_for_viewport_percentages` was called, and stop looking.
284
258
#[ inline]
285
259
pub fn seen_viewport_percentages ( & mut self ) -> bool {
286
- self . tokenizer . seen_viewport_percentages ( )
260
+ ( self . tokenizer . 0 ) . seen_viewport_percentages ( )
287
261
}
288
262
289
263
/// Execute the given closure, passing it the parser.
@@ -304,25 +278,25 @@ impl<'i, 't> Parser<'i, 't> {
304
278
/// Return a slice of the CSS input
305
279
#[ inline]
306
280
pub fn slice ( & self , range : Range < SourcePosition > ) -> & ' i str {
307
- self . tokenizer . slice ( range. start . position ..range. end . position )
281
+ ( self . tokenizer . 0 ) . slice ( range. start . position ..range. end . position )
308
282
}
309
283
310
284
/// Return a slice of the CSS input, from the given position to the current one.
311
285
#[ inline]
312
286
pub fn slice_from ( & self , start_position : SourcePosition ) -> & ' i str {
313
- self . tokenizer . slice_from ( start_position. position )
287
+ ( self . tokenizer . 0 ) . slice_from ( start_position. position )
314
288
}
315
289
316
290
/// Return the line and column number within the input for the current position.
317
291
#[ inline]
318
292
pub fn current_source_location ( & self ) -> SourceLocation {
319
- self . tokenizer . current_source_location ( )
293
+ ( self . tokenizer . 0 ) . current_source_location ( )
320
294
}
321
295
322
296
/// Return the line and column number within the input for the given position.
323
297
#[ inline]
324
298
pub fn source_location ( & self , target : SourcePosition ) -> SourceLocation {
325
- self . tokenizer . source_location ( target. position )
299
+ ( self . tokenizer . 0 ) . source_location ( target. position )
326
300
}
327
301
328
302
/// Return the next token in the input that is neither whitespace or a comment,
@@ -363,13 +337,13 @@ impl<'i, 't> Parser<'i, 't> {
363
337
/// comments should always be ignored between tokens.
364
338
pub fn next_including_whitespace_and_comments ( & mut self ) -> Result < Token < ' i > , BasicParseError < ' i > > {
365
339
if let Some ( block_type) = self . at_start_of . take ( ) {
366
- consume_until_end_of_block ( block_type, & mut * self . tokenizer ) ;
340
+ consume_until_end_of_block ( block_type, & mut self . tokenizer . 0 ) ;
367
341
}
368
- let byte = self . tokenizer . next_byte ( ) ;
342
+ let byte = ( self . tokenizer . 0 ) . next_byte ( ) ;
369
343
if self . stop_before . contains ( Delimiters :: from_byte ( byte) ) {
370
344
return Err ( BasicParseError :: EndOfInput )
371
345
}
372
- let token = try!( self . tokenizer . next ( ) . map_err ( |( ) | BasicParseError :: EndOfInput ) ) ;
346
+ let token = try!( ( self . tokenizer . 0 ) . next ( ) . map_err ( |( ) | BasicParseError :: EndOfInput ) ) ;
373
347
if let Some ( block_type) = BlockType :: opening ( & token) {
374
348
self . at_start_of = Some ( block_type) ;
375
349
}
@@ -400,10 +374,10 @@ impl<'i, 't> Parser<'i, 't> {
400
374
/// or if a closure call leaves some input before the next comma or the end of the input.
401
375
#[ inline]
402
376
pub fn parse_comma_separated < F , T , E > ( & mut self , mut parse_one : F ) -> Result < Vec < T > , ParseError < ' i , E > >
403
- where F : for < ' ii , ' tt > FnMut ( & mut Parser < ' ii , ' tt > ) -> Result < T , ParseError < ' ii , E > > {
377
+ where F : for < ' tt > FnMut ( & mut Parser < ' i , ' tt > ) -> Result < T , ParseError < ' i , E > > {
404
378
let mut values = vec ! [ ] ;
405
379
loop {
406
- values. push ( try!( self . parse_until_before ( Delimiter :: Comma , |parser| parse_one ( parser ) ) ) ) ;
380
+ values. push ( try!( self . parse_until_before ( Delimiter :: Comma , & mut parse_one) ) ) ;
407
381
match self . next ( ) {
408
382
Err ( _) => return Ok ( values) ,
409
383
Ok ( Token :: Comma ) => continue ,
@@ -426,31 +400,7 @@ impl<'i, 't> Parser<'i, 't> {
426
400
#[ inline]
427
401
pub fn parse_nested_block < F , T , E > ( & mut self , parse : F ) -> Result < T , ParseError < ' i , E > >
428
402
where F : for < ' tt > FnOnce ( & mut Parser < ' i , ' tt > ) -> Result < T , ParseError < ' i , E > > {
429
- let block_type = self . at_start_of . take ( ) . expect ( "\
430
- A nested parser can only be created when a Function, \
431
- ParenthesisBlock, SquareBracketBlock, or CurlyBracketBlock \
432
- token was just consumed.\
433
- ") ;
434
- let closing_delimiter = match block_type {
435
- BlockType :: CurlyBracket => ClosingDelimiter :: CloseCurlyBracket ,
436
- BlockType :: SquareBracket => ClosingDelimiter :: CloseSquareBracket ,
437
- BlockType :: Parenthesis => ClosingDelimiter :: CloseParenthesis ,
438
- } ;
439
- let result;
440
- // Introduce a new scope to limit duration of nested_parser’s borrow
441
- {
442
- let mut nested_parser = Parser {
443
- tokenizer : MaybeOwned :: Borrowed ( & mut * self . tokenizer ) ,
444
- at_start_of : None ,
445
- stop_before : closing_delimiter,
446
- } ;
447
- result = nested_parser. parse_entirely ( parse) ;
448
- if let Some ( block_type) = nested_parser. at_start_of {
449
- consume_until_end_of_block ( block_type, & mut * nested_parser. tokenizer ) ;
450
- }
451
- }
452
- consume_until_end_of_block ( block_type, & mut * self . tokenizer ) ;
453
- result
403
+ parse_nested_block ( self , parse)
454
404
}
455
405
456
406
/// Limit parsing to until a given delimiter. (E.g. a semicolon for a property value.)
@@ -464,34 +414,7 @@ impl<'i, 't> Parser<'i, 't> {
464
414
pub fn parse_until_before < F , T , E > ( & mut self , delimiters : Delimiters , parse : F )
465
415
-> Result < T , ParseError < ' i , E > >
466
416
where F : for < ' tt > FnOnce ( & mut Parser < ' i , ' tt > ) -> Result < T , ParseError < ' i , E > > {
467
- let delimiters = self . stop_before | delimiters;
468
- let result;
469
- // Introduce a new scope to limit duration of nested_parser’s borrow
470
- {
471
- let mut delimited_parser = Parser {
472
- tokenizer : MaybeOwned :: Borrowed ( & mut * self . tokenizer ) ,
473
- at_start_of : self . at_start_of . take ( ) ,
474
- stop_before : delimiters,
475
- } ;
476
- result = delimited_parser. parse_entirely ( parse) ;
477
- if let Some ( block_type) = delimited_parser. at_start_of {
478
- consume_until_end_of_block ( block_type, & mut * delimited_parser. tokenizer ) ;
479
- }
480
- }
481
- // FIXME: have a special-purpose tokenizer method for this that does less work.
482
- loop {
483
- if delimiters. contains ( Delimiters :: from_byte ( self . tokenizer . next_byte ( ) ) ) {
484
- break
485
- }
486
- if let Ok ( token) = self . tokenizer . next ( ) {
487
- if let Some ( block_type) = BlockType :: opening ( & token) {
488
- consume_until_end_of_block ( block_type, & mut * self . tokenizer ) ;
489
- }
490
- } else {
491
- break
492
- }
493
- }
494
- result
417
+ parse_until_before ( self , delimiters, parse)
495
418
}
496
419
497
420
/// Like `parse_until_before`, but also consume the delimiter token.
@@ -727,6 +650,87 @@ impl<'i, 't> Parser<'i, 't> {
727
650
}
728
651
}
729
652
653
+ pub fn parse_until_before < ' i : ' t , ' t , F , T , E > ( parser : & mut Parser < ' i , ' t > ,
654
+ delimiters : Delimiters ,
655
+ parse : F )
656
+ -> Result < T , ParseError < ' i , E > >
657
+ where F : for < ' tt > FnOnce ( & mut Parser < ' i , ' tt > ) -> Result < T , ParseError < ' i , E > > {
658
+ let delimiters = parser. stop_before | delimiters;
659
+ let result;
660
+ // Introduce a new scope to limit duration of nested_parser’s borrow
661
+ {
662
+ let mut delimited_parser = Parser {
663
+ tokenizer : parser. tokenizer ,
664
+ at_start_of : parser. at_start_of . take ( ) ,
665
+ stop_before : delimiters,
666
+ } ;
667
+ result = delimited_parser. parse_entirely ( parse) ;
668
+ if let Some ( block_type) = delimited_parser. at_start_of {
669
+ consume_until_end_of_block ( block_type, & mut delimited_parser. tokenizer . 0 ) ;
670
+ }
671
+ }
672
+ // FIXME: have a special-purpose tokenizer method for this that does less work.
673
+ loop {
674
+ if delimiters. contains ( Delimiters :: from_byte ( ( parser. tokenizer . 0 ) . next_byte ( ) ) ) {
675
+ break
676
+ }
677
+ if let Ok ( token) = ( parser. tokenizer . 0 ) . next ( ) {
678
+ if let Some ( block_type) = BlockType :: opening ( & token) {
679
+ consume_until_end_of_block ( block_type, & mut parser. tokenizer . 0 ) ;
680
+ }
681
+ } else {
682
+ break
683
+ }
684
+ }
685
+ result
686
+ }
687
+
688
+ pub fn parse_until_after < ' i : ' t , ' t , F , T , E > ( parser : & mut Parser < ' i , ' t > ,
689
+ delimiters : Delimiters ,
690
+ parse : F )
691
+ -> Result < T , ParseError < ' i , E > >
692
+ where F : for < ' tt > FnOnce ( & mut Parser < ' i , ' tt > ) -> Result < T , ParseError < ' i , E > > {
693
+ let result = parser. parse_until_before ( delimiters, parse) ;
694
+ let next_byte = ( parser. tokenizer . 0 ) . next_byte ( ) ;
695
+ if next_byte. is_some ( ) && !parser. stop_before . contains ( Delimiters :: from_byte ( next_byte) ) {
696
+ debug_assert ! ( delimiters. contains( Delimiters :: from_byte( next_byte) ) ) ;
697
+ ( parser. tokenizer . 0 ) . advance ( 1 ) ;
698
+ if next_byte == Some ( b'{' ) {
699
+ consume_until_end_of_block ( BlockType :: CurlyBracket , & mut parser. tokenizer . 0 ) ;
700
+ }
701
+ }
702
+ result
703
+ }
704
+
705
+ pub fn parse_nested_block < ' i : ' t , ' t , F , T , E > ( parser : & mut Parser < ' i , ' t > , parse : F )
706
+ -> Result < T , ParseError < ' i , E > >
707
+ where F : for < ' tt > FnOnce ( & mut Parser < ' i , ' tt > ) -> Result < T , ParseError < ' i , E > > {
708
+ let block_type = parser. at_start_of . take ( ) . expect ( "\
709
+ A nested parser can only be created when a Function, \
710
+ ParenthesisBlock, SquareBracketBlock, or CurlyBracketBlock \
711
+ token was just consumed.\
712
+ ") ;
713
+ let closing_delimiter = match block_type {
714
+ BlockType :: CurlyBracket => ClosingDelimiter :: CloseCurlyBracket ,
715
+ BlockType :: SquareBracket => ClosingDelimiter :: CloseSquareBracket ,
716
+ BlockType :: Parenthesis => ClosingDelimiter :: CloseParenthesis ,
717
+ } ;
718
+ let result;
719
+ // Introduce a new scope to limit duration of nested_parser’s borrow
720
+ {
721
+ let mut nested_parser = Parser {
722
+ tokenizer : parser. tokenizer ,
723
+ at_start_of : None ,
724
+ stop_before : closing_delimiter,
725
+ } ;
726
+ result = nested_parser. parse_entirely ( parse) ;
727
+ if let Some ( block_type) = nested_parser. at_start_of {
728
+ consume_until_end_of_block ( block_type, & mut nested_parser. tokenizer . 0 ) ;
729
+ }
730
+ }
731
+ consume_until_end_of_block ( block_type, & mut parser. tokenizer . 0 ) ;
732
+ result
733
+ }
730
734
731
735
fn consume_until_end_of_block ( block_type : BlockType , tokenizer : & mut Tokenizer ) {
732
736
let mut stack = vec ! [ block_type] ;
@@ -747,20 +751,3 @@ fn consume_until_end_of_block(block_type: BlockType, tokenizer: &mut Tokenizer)
747
751
}
748
752
}
749
753
}
750
-
751
- pub fn parse_until_after < ' i , ' t , F , T , E > ( parser : & mut Parser < ' i , ' t > ,
752
- delimiters : Delimiters ,
753
- parse : F )
754
- -> Result < T , ParseError < ' i , E > >
755
- where F : for < ' tt > FnOnce ( & mut Parser < ' i , ' tt > ) -> Result < T , ParseError < ' i , E > > {
756
- let result = parser. parse_until_before ( delimiters, parse) ;
757
- let next_byte = parser. tokenizer . next_byte ( ) ;
758
- if next_byte. is_some ( ) && !parser. stop_before . contains ( Delimiters :: from_byte ( next_byte) ) {
759
- debug_assert ! ( delimiters. contains( Delimiters :: from_byte( next_byte) ) ) ;
760
- parser. tokenizer . advance ( 1 ) ;
761
- if next_byte == Some ( b'{' ) {
762
- consume_until_end_of_block ( BlockType :: CurlyBracket , & mut * parser. tokenizer ) ;
763
- }
764
- }
765
- result
766
- }
0 commit comments