3
3
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
4
5
5
// http://dev.w3.org/csswg/css-syntax/#parsing
6
- //
7
- // The input to the tree construction stage is a sequence of tokens
8
- // from the tokenization stage.
9
- // The output is a tree of items with a stylesheet at the root
10
- // and all other nodes being at-rules, style rules, or declarations.
6
+
7
+ /// The input to these functions needs to implement Iterator<(ComponentValue, SourceLocation)>.
8
+ /// The input is consumed to avoid doing a lot of copying.
9
+ /// A conforming input can be obtained:
10
+ ///
11
+ /// * From a string in CSS syntax, with tokenize()
12
+ /// * From a ~[(ComponentValue, SourceLocation)] vector
13
+ /// (as found in "nested" component values such as CurlyBracketBlock),
14
+ /// with v.consume_iter()
11
15
12
16
13
17
use std:: iterator:: Iterator ;
@@ -16,101 +20,67 @@ use std::ascii::eq_ignore_ascii_case;
16
20
use ast:: * ;
17
21
18
22
19
- // Work around "error: cannot borrow `*iter` as mutable more than once at a time"
20
- // when using a normal for loop.
21
- macro_rules! for_iter(
22
- ( $iter: ident, $pattern: pat, $loop_body: expr) => (
23
- loop {
24
- match $iter. next( ) { None => break , Some ( $pattern) => $loop_body }
25
- }
26
- ) ;
27
- )
23
+ /// Parse top-level of a CSS stylesheet.
24
+ /// Return a Iterator<Result<Rule, ErrorReason>>
25
+ #[ inline]
26
+ pub fn parse_stylesheet < T : Iterator < Node > > ( iter : T ) -> StylesheetParser < T > {
27
+ StylesheetParser ( iter)
28
+ }
28
29
29
30
30
- /// Call repeatedly for the top-level of a CSS stylesheet
31
- pub fn parse_stylesheet_rule < T : Iterator < Node > > ( iter : & mut T ) -> Option < Result < Rule , ErrorReason > > {
32
- for_iter ! ( iter, ( component_value, location) , {
33
- match component_value {
34
- WhiteSpace | CDO | CDC => ( ) ,
35
- AtKeyword ( name) => return Some ( Ok ( AtRule ( parse_at_rule( iter, name, location) ) ) ) ,
36
- _ => return Some ( match parse_qualified_rule( iter, ( component_value, location) ) {
37
- Ok ( rule) => Ok ( QualifiedRule ( rule) ) ,
38
- Err ( reason) => Err ( reason) ,
39
- } ) ,
40
- }
41
- } )
42
- None
31
+ /// Parse a non-top level list of rules eg. the content of an @media rule.
32
+ /// Return a Iterator<Result<Rule, ErrorReason>>
33
+ #[ inline]
34
+ pub fn parse_rule_list < T : Iterator < Node > > ( iter : T ) -> RuleListParser < T > {
35
+ RuleListParser ( iter)
43
36
}
44
37
45
38
46
- /// Call repeatedly for a non-top level list of rules eg. the content of an @media rule.
47
- /// Same as parse_stylesheet() except for the handling of top-level CDO and CDC
48
- pub fn parse_rule < T : Iterator < Node > > ( iter : & mut T ) -> Option < Result < Rule , ErrorReason > > {
49
- for_iter ! ( iter, ( component_value, location) , {
50
- match component_value {
51
- WhiteSpace => ( ) ,
52
- AtKeyword ( name) => return Some ( Ok ( AtRule ( parse_at_rule( iter, name, location) ) ) ) ,
53
- _ => return Some ( match parse_qualified_rule( iter, ( component_value, location) ) {
54
- Ok ( rule) => Ok ( QualifiedRule ( rule) ) ,
55
- Err ( reason) => Err ( reason) ,
56
- } ) ,
57
- }
58
- } )
59
- None
39
+ /// Parse a list of declarations and at-rules,
40
+ /// like @page in CSS 2.1, all declaration lists in level 3
41
+ /// Return a Iterator<Result<DeclarationListItem, ErrorReason>>
42
+ #[ inline]
43
+ pub fn parse_declaration_list < T : Iterator < Node > > ( iter : T ) -> DeclarationListParser < T > {
44
+ DeclarationListParser ( iter)
60
45
}
61
46
62
47
48
+ /// Parse a single rule.
63
49
/// Used eg. for CSSRuleList.insertRule()
64
- pub fn parse_one_rule < T : Iterator < Node > > ( iter : & mut T ) -> Result < Rule , ErrorReason > {
65
- match parse_rule ( iter) {
50
+ pub fn parse_one_rule < T : Iterator < Node > > ( iter : T ) -> Result < Rule , ErrorReason > {
51
+ let mut parser = RuleListParser ( iter) ;
52
+ match parser. next ( ) {
66
53
None => Err ( ErrEmptyInput ) ,
67
- Some ( result) => if result. is_err ( ) || next_non_whitespace ( iter) . is_none ( ) { result }
68
- else { Err ( ErrExtraInput ) }
69
- }
70
- }
71
-
72
-
73
- /// Call repeatedly of a list of declarations.
74
- /// @page in CSS 2.1, all declaration lists in level 3
75
- pub fn parse_declaration_or_at_rule < T : Iterator < Node > > ( iter : & mut T )
76
- -> Option < Result < DeclarationListItem , ErrorReason > > {
77
- for_iter ! ( iter, ( component_value, location) , {
78
- match component_value {
79
- WhiteSpace | Semicolon => ( ) ,
80
- AtKeyword ( name) => return Some ( Ok ( Decl_AtRule ( parse_at_rule( iter, name, location) ) ) ) ,
81
- _ => return Some ( match parse_declaration( iter, ( component_value, location) ) {
82
- Ok ( declaration) => Ok ( Declaration ( declaration) ) ,
83
- Err ( reason) => {
84
- // Find the end of the declaration
85
- for ( v, _) in * iter { if v == Semicolon { break } }
86
- Err ( reason)
87
- }
88
- } ) ,
54
+ Some ( result) => {
55
+ if result. is_err ( ) || next_non_whitespace ( & mut * parser) . is_none ( ) { result }
56
+ else { Err ( ErrExtraInput ) }
89
57
}
90
- } )
91
- None
58
+ }
92
59
}
93
60
94
61
62
+ /// Parse a single declaration (not an at-rule)
95
63
/// Used eg. in @supports
96
- pub fn parse_one_declaration < T : Iterator < Node > > ( iter : & mut T ) -> Result < Declaration , ErrorReason > {
97
- match next_non_whitespace ( iter) {
64
+ pub fn parse_one_declaration < T : Iterator < Node > > ( mut iter : T ) -> Result < Declaration , ErrorReason > {
65
+ match next_non_whitespace ( & mut iter) {
98
66
None => Err ( ErrEmptyInput ) ,
99
67
Some ( item) => {
100
- let result = parse_declaration ( iter, item) ;
101
- if result. is_err ( ) || next_non_whitespace ( iter) . is_none ( ) { result }
68
+ let result = parse_declaration ( & mut iter, item) ;
69
+ if result. is_err ( ) || next_non_whitespace ( & mut iter) . is_none ( ) { result }
102
70
else { Err ( ErrExtraInput ) }
103
71
}
104
72
}
105
73
}
106
74
107
75
76
+ /// Parse a single component value.
108
77
/// Used eg. in attr(foo, color)
109
- pub fn parse_one_component_value < T : Iterator < Node > > ( iter : & mut T ) -> Result < Node , ErrorReason > {
110
- match next_non_whitespace ( iter) {
78
+ pub fn parse_one_component_value < T : Iterator < Node > > ( mut iter : T )
79
+ -> Result < ComponentValue , ErrorReason > {
80
+ match next_non_whitespace ( & mut iter) {
111
81
None => Err ( ErrEmptyInput ) ,
112
- Some ( item ) => {
113
- if next_non_whitespace ( iter) . is_none ( ) { Ok ( item ) }
82
+ Some ( ( component_value , _location ) ) => {
83
+ if next_non_whitespace ( & mut iter) . is_none ( ) { Ok ( component_value ) }
114
84
else { Err ( ErrExtraInput ) }
115
85
}
116
86
}
@@ -120,6 +90,82 @@ pub fn parse_one_component_value<T: Iterator<Node>>(iter: &mut T) -> Result<Node
120
90
// *********** End of public API ***********
121
91
122
92
93
+ struct StylesheetParser < T > ( T ) ;
94
+ struct RuleListParser < T > ( T ) ;
95
+ struct DeclarationListParser < T > ( T ) ;
96
+
97
+
98
+ // Work around "error: cannot borrow `*iter` as mutable more than once at a time"
99
+ // when using a normal for loop.
100
+ macro_rules! for_iter(
101
+ ( $iter: ident, $pattern: pat, $loop_body: expr) => (
102
+ loop {
103
+ match $iter. next( ) { None => break , Some ( $pattern) => $loop_body }
104
+ }
105
+ ) ;
106
+ )
107
+
108
+
109
+ impl < T : Iterator < Node > > Iterator < Result < Rule , ErrorReason > > for StylesheetParser < T > {
110
+ fn next ( & mut self ) -> Option < Result < Rule , ErrorReason > > {
111
+ let iter = & mut * * self ;
112
+ for_iter ! ( iter, ( component_value, location) , {
113
+ match component_value {
114
+ WhiteSpace | CDO | CDC => ( ) ,
115
+ AtKeyword ( name) => return Some ( Ok ( AtRule ( parse_at_rule( iter, name, location) ) ) ) ,
116
+ _ => return Some ( match parse_qualified_rule( iter, ( component_value, location) ) {
117
+ Ok ( rule) => Ok ( QualifiedRule ( rule) ) ,
118
+ Err ( reason) => Err ( reason) ,
119
+ } ) ,
120
+ }
121
+ } )
122
+ None
123
+ }
124
+ }
125
+
126
+
127
+ impl < T : Iterator < Node > > Iterator < Result < Rule , ErrorReason > > for RuleListParser < T > {
128
+ fn next ( & mut self ) -> Option < Result < Rule , ErrorReason > > {
129
+ let iter = & mut * * self ;
130
+ for_iter ! ( iter, ( component_value, location) , {
131
+ match component_value {
132
+ WhiteSpace => ( ) ,
133
+ AtKeyword ( name) => return Some ( Ok ( AtRule ( parse_at_rule( iter, name, location) ) ) ) ,
134
+ _ => return Some ( match parse_qualified_rule( iter, ( component_value, location) ) {
135
+ Ok ( rule) => Ok ( QualifiedRule ( rule) ) ,
136
+ Err ( reason) => Err ( reason) ,
137
+ } ) ,
138
+ }
139
+ } )
140
+ None
141
+ }
142
+ }
143
+
144
+
145
+ impl < T : Iterator < Node > > Iterator < Result < DeclarationListItem , ErrorReason > >
146
+ for DeclarationListParser < T > {
147
+ fn next ( & mut self ) -> Option < Result < DeclarationListItem , ErrorReason > > {
148
+ let iter = & mut * * self ;
149
+ for_iter ! ( iter, ( component_value, location) , {
150
+ match component_value {
151
+ WhiteSpace | Semicolon => ( ) ,
152
+ AtKeyword ( name)
153
+ => return Some ( Ok ( Decl_AtRule ( parse_at_rule( iter, name, location) ) ) ) ,
154
+ _ => return Some ( match parse_declaration( iter, ( component_value, location) ) {
155
+ Ok ( declaration) => Ok ( Declaration ( declaration) ) ,
156
+ Err ( reason) => {
157
+ // Find the end of the declaration
158
+ for ( v, _) in * iter { if v == Semicolon { break } }
159
+ Err ( reason)
160
+ }
161
+ } ) ,
162
+ }
163
+ } )
164
+ None
165
+ }
166
+ }
167
+
168
+
123
169
fn parse_at_rule < T : Iterator < Node > > ( iter : & mut T , name : ~str , location : SourceLocation )
124
170
-> AtRule {
125
171
let mut prelude = ~[ ] ;
0 commit comments