Skip to content

Commit bff9dfc

Browse files
committed
Make the tokenizer an iterator.
1 parent cb67994 commit bff9dfc

File tree

4 files changed

+125
-162
lines changed

4 files changed

+125
-162
lines changed

ast.rs

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,16 @@ pub struct SourceLocation {
2121
}
2222

2323

24+
pub type Node = (ComponentValue, SourceLocation); // TODO this is not a good name
25+
26+
2427
#[deriving(Eq)]
2528
pub enum ComponentValue {
26-
// Preserved tokens. Same as in the tokenizer.
29+
// Preserved tokens.
2730
Ident(~str),
2831
AtKeyword(~str),
2932
Hash(~str),
30-
IDHash(~str), // Hash token that is a valid ID selector.
33+
IDHash(~str), // Hash that is a valid ID selector.
3134
String(~str),
3235
URL(~str),
3336
Delim(char),
@@ -50,12 +53,12 @@ pub enum ComponentValue {
5053
CDC, // -->
5154

5255
// Function
53-
Function(~str, ~[(ComponentValue, SourceLocation)]), // name, arguments
56+
Function(~str, ~[Node]), // name, arguments
5457

5558
// Simple block
56-
ParenthesisBlock(~[(ComponentValue, SourceLocation)]), // (…)
57-
SquareBracketBlock(~[(ComponentValue, SourceLocation)]), // […]
58-
CurlyBracketBlock(~[(ComponentValue, SourceLocation)]), // {…}
59+
ParenthesisBlock(~[Node]), // (…)
60+
SquareBracketBlock(~[Node]), // […]
61+
CurlyBracketBlock(~[Node]), // {…}
5962

6063
// These are always invalid
6164
BadURL,
@@ -70,23 +73,23 @@ pub enum ComponentValue {
7073
pub struct Declaration {
7174
location: SourceLocation,
7275
name: ~str,
73-
value: ~[(ComponentValue, SourceLocation)],
76+
value: ~[Node],
7477
important: bool,
7578
}
7679

7780
#[deriving(Eq)]
7881
pub struct QualifiedRule {
7982
location: SourceLocation,
80-
prelude: ~[(ComponentValue, SourceLocation)],
81-
block: ~[(ComponentValue, SourceLocation)],
83+
prelude: ~[Node],
84+
block: ~[Node],
8285
}
8386

8487
#[deriving(Eq)]
8588
pub struct AtRule {
8689
location: SourceLocation,
8790
name: ~str,
88-
prelude: ~[(ComponentValue, SourceLocation)],
89-
block: Option<~[(ComponentValue, SourceLocation)]>,
91+
prelude: ~[Node],
92+
block: Option<~[Node]>,
9093
}
9194

9295
#[deriving(Eq)]
@@ -121,24 +124,21 @@ pub trait SkipWhitespaceIterable<'self> {
121124
pub fn skip_whitespace(self) -> SkipWhitespaceIterator<'self>;
122125
}
123126

124-
impl<'self> SkipWhitespaceIterable<'self> for &'self [(ComponentValue, SourceLocation)] {
127+
impl<'self> SkipWhitespaceIterable<'self> for &'self [Node] {
125128
pub fn skip_whitespace(self) -> SkipWhitespaceIterator<'self> {
126129
SkipWhitespaceIterator{ iter: self.iter() }
127130
}
128131
}
129132

130133
struct SkipWhitespaceIterator<'self> {
131-
iter: vec::VecIterator<'self, (ComponentValue, SourceLocation)>,
134+
iter: vec::VecIterator<'self, Node>,
132135
}
133136

134137
impl<'self> Iterator<&'self ComponentValue> for SkipWhitespaceIterator<'self> {
135138
fn next(&mut self) -> Option<&'self ComponentValue> {
136-
loop {
137-
match self.iter.next() {
138-
Some(&(WhiteSpace, _)) => (),
139-
Some(&(ref component_value, _)) => return Some(component_value),
140-
None => return None
141-
}
139+
for &(ref component_value, _) in self.iter {
140+
if component_value != &WhiteSpace { return Some(component_value) }
142141
}
142+
None
143143
}
144144
}

parser.rs

Lines changed: 30 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -11,49 +11,9 @@
1111

1212

1313
use std::iterator::Iterator;
14-
use std::vec;
1514
use std::ascii::eq_ignore_ascii_case;
1615

1716
use ast::*;
18-
use tokenizer::*;
19-
20-
21-
// TODO: Use a trait?
22-
enum ComponentValueIterator {
23-
ParserIter(Parser),
24-
VectorIter(vec::ConsumeIterator<(ComponentValue, SourceLocation)>),
25-
}
26-
27-
28-
impl ComponentValueIterator {
29-
#[inline]
30-
pub fn from_str(input: ~str) -> ComponentValueIterator {
31-
ParserIter(Parser::from_str(input))
32-
}
33-
34-
#[inline]
35-
pub fn from_vector(values: ~[(ComponentValue, SourceLocation)]) -> ComponentValueIterator {
36-
VectorIter(values.consume_iter())
37-
}
38-
39-
#[inline]
40-
pub fn next_non_whitespace(&mut self) -> Option<(ComponentValue, SourceLocation)> {
41-
for (component_value, location) in *self {
42-
if component_value != WhiteSpace { return Some((component_value, location)) }
43-
}
44-
None
45-
}
46-
}
47-
48-
49-
impl Iterator<(ComponentValue, SourceLocation)> for ComponentValueIterator {
50-
fn next(&mut self) -> Option<(ComponentValue, SourceLocation)> {
51-
match self {
52-
&ParserIter(ref mut parser) => next_component_value(parser),
53-
&VectorIter(ref mut iter) => iter.next()
54-
}
55-
}
56-
}
5717

5818

5919
// Work around "error: cannot borrow `*iter` as mutable more than once at a time"
@@ -68,7 +28,7 @@ macro_rules! for_iter(
6828

6929

7030
/// Call repeatedly for the top-level of a CSS stylesheet
71-
pub fn parse_stylesheet_rule(iter: &mut ComponentValueIterator) -> Option<Result<Rule, ErrorReason>> {
31+
pub fn parse_stylesheet_rule<T: Iterator<Node>>(iter: &mut T) -> Option<Result<Rule, ErrorReason>> {
7232
for_iter!(iter, (component_value, location), {
7333
match component_value {
7434
WhiteSpace | CDO | CDC => (),
@@ -85,7 +45,7 @@ pub fn parse_stylesheet_rule(iter: &mut ComponentValueIterator) -> Option<Result
8545

8646
/// Call repeatedly for a non-top level list of rules eg. the content of an @media rule.
8747
/// Same as parse_stylesheet() except for the handling of top-level CDO and CDC
88-
pub fn parse_rule(iter: &mut ComponentValueIterator) -> Option<Result<Rule, ErrorReason>> {
48+
pub fn parse_rule<T: Iterator<Node>>(iter: &mut T) -> Option<Result<Rule, ErrorReason>> {
8949
for_iter!(iter, (component_value, location), {
9050
match component_value {
9151
WhiteSpace => (),
@@ -101,19 +61,19 @@ pub fn parse_rule(iter: &mut ComponentValueIterator) -> Option<Result<Rule, Erro
10161

10262

10363
/// Used eg. for CSSRuleList.insertRule()
104-
pub fn parse_one_rule(iter: &mut ComponentValueIterator) -> Result<Rule, ErrorReason> {
64+
pub fn parse_one_rule<T: Iterator<Node>>(iter: &mut T) -> Result<Rule, ErrorReason> {
10565
match parse_rule(iter) {
10666
None => Err(ErrEmptyInput),
107-
Some(result) => if result.is_err() || iter.next_non_whitespace().is_none() { result }
67+
Some(result) => if result.is_err() || next_non_whitespace(iter).is_none() { result }
10868
else { Err(ErrExtraInput) }
10969
}
11070
}
11171

11272

11373
/// Call repeatedly of a list of declarations.
11474
/// @page in CSS 2.1, all declaration lists in level 3
115-
pub fn parse_declaration_or_at_rule(iter: &mut ComponentValueIterator)
116-
-> Option<Result<DeclarationListItem, ErrorReason>> {
75+
pub fn parse_declaration_or_at_rule<T: Iterator<Node>>(iter: &mut T)
76+
-> Option<Result<DeclarationListItem, ErrorReason>> {
11777
for_iter!(iter, (component_value, location), {
11878
match component_value {
11979
WhiteSpace | Semicolon => (),
@@ -133,25 +93,24 @@ pub fn parse_declaration_or_at_rule(iter: &mut ComponentValueIterator)
13393

13494

13595
/// Used eg. in @supports
136-
pub fn parse_one_declaration(iter: &mut ComponentValueIterator) -> Result<Declaration, ErrorReason> {
137-
match iter.next_non_whitespace() {
96+
pub fn parse_one_declaration<T: Iterator<Node>>(iter: &mut T) -> Result<Declaration, ErrorReason> {
97+
match next_non_whitespace(iter) {
13898
None => Err(ErrEmptyInput),
13999
Some(item) => {
140100
let result = parse_declaration(iter, item);
141-
if result.is_err() || iter.next_non_whitespace().is_none() { result }
101+
if result.is_err() || next_non_whitespace(iter).is_none() { result }
142102
else { Err(ErrExtraInput) }
143103
}
144104
}
145105
}
146106

147107

148108
/// Used eg. in attr(foo, color)
149-
pub fn parse_one_component_value(iter: &mut ComponentValueIterator)
150-
-> Result<(ComponentValue, SourceLocation), ErrorReason> {
151-
match iter.next_non_whitespace() {
109+
pub fn parse_one_component_value<T: Iterator<Node>>(iter: &mut T) -> Result<Node, ErrorReason> {
110+
match next_non_whitespace(iter) {
152111
None => Err(ErrEmptyInput),
153112
Some(item) => {
154-
if iter.next_non_whitespace().is_none() { Ok(item) }
113+
if next_non_whitespace(iter).is_none() { Ok(item) }
155114
else { Err(ErrExtraInput) }
156115
}
157116
}
@@ -161,7 +120,7 @@ pub fn parse_one_component_value(iter: &mut ComponentValueIterator)
161120
// *********** End of public API ***********
162121

163122

164-
fn parse_at_rule(iter: &mut ComponentValueIterator, name: ~str, location: SourceLocation)
123+
fn parse_at_rule<T: Iterator<Node>>(iter: &mut T, name: ~str, location: SourceLocation)
165124
-> AtRule {
166125
let mut prelude = ~[];
167126
let mut block = None;
@@ -176,8 +135,8 @@ fn parse_at_rule(iter: &mut ComponentValueIterator, name: ~str, location: Source
176135
}
177136

178137

179-
fn parse_qualified_rule(iter: &mut ComponentValueIterator, first: (ComponentValue, SourceLocation))
180-
-> Result<QualifiedRule, ErrorReason> {
138+
fn parse_qualified_rule<T: Iterator<Node>>(iter: &mut T, first: Node)
139+
-> Result<QualifiedRule, ErrorReason> {
181140
match first {
182141
(CurlyBracketBlock(content), location)
183142
=> return Ok(QualifiedRule { location: location, prelude: ~[], block: content }),
@@ -195,13 +154,13 @@ fn parse_qualified_rule(iter: &mut ComponentValueIterator, first: (ComponentValu
195154
}
196155

197156

198-
fn parse_declaration(iter: &mut ComponentValueIterator, first: (ComponentValue, SourceLocation))
199-
-> Result<Declaration, ErrorReason> {
157+
fn parse_declaration<T: Iterator<Node>>(iter: &mut T, first: Node)
158+
-> Result<Declaration, ErrorReason> {
200159
let (name, location) = match first {
201160
(Ident(name), location) => (name, location),
202161
_ => return Err(ErrInvalidDeclarationSyntax)
203162
};
204-
match iter.next_non_whitespace() {
163+
match next_non_whitespace(iter) {
205164
Some((Colon, _)) => (),
206165
_ => return Err(ErrInvalidDeclarationSyntax),
207166
}
@@ -224,15 +183,24 @@ fn parse_declaration(iter: &mut ComponentValueIterator, first: (ComponentValue,
224183

225184

226185
#[inline]
227-
fn parse_declaration_important(iter: &mut ComponentValueIterator) -> bool {
228-
let ident_value = match iter.next_non_whitespace() {
186+
fn parse_declaration_important<T: Iterator<Node>>(iter: &mut T) -> bool {
187+
let ident_value = match next_non_whitespace(iter) {
229188
Some((Ident(value), _)) => value,
230189
_ => return false,
231190
};
232191
if !eq_ignore_ascii_case(ident_value, "important") { return false }
233-
match iter.next_non_whitespace() {
192+
match next_non_whitespace(iter) {
234193
Some((Semicolon, _)) => true,
235194
None => true,
236195
_ => false
237196
}
238197
}
198+
199+
200+
#[inline]
201+
fn next_non_whitespace<T: Iterator<Node>>(iter: &mut T) -> Option<Node> {
202+
for (component_value, location) in *iter {
203+
if component_value != WhiteSpace { return Some((component_value, location)) }
204+
}
205+
None
206+
}

tests.rs

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use extra::{tempfile, json};
77
use extra::json::ToJson;
88

99
use ast::*;
10-
use tokenizer::*;
10+
use tokenizer::tokenize;
1111
use parser::*;
1212
use color::*;
1313

@@ -79,14 +79,8 @@ fn run_json_tests(json_data: &str, parse: &fn (input: ~str) -> json::Json) {
7979
#[test]
8080
fn component_value_list() {
8181
do run_json_tests(include_str!("css-parsing-tests/component_value_list.json")) |input| {
82-
let parser = &mut Parser::from_str(input);
8382
let mut results = ~[];
84-
loop {
85-
match next_component_value(parser) {
86-
Some((c, _)) => results.push(c),
87-
None => break,
88-
}
89-
}
83+
for (c, _) in &mut tokenize(input) { results.push(c) }
9084
results.to_json()
9185
}
9286
}
@@ -95,16 +89,16 @@ fn component_value_list() {
9589
#[test]
9690
fn one_component_value() {
9791
do run_json_tests(include_str!("css-parsing-tests/one_component_value.json")) |input| {
98-
let iter = &mut ComponentValueIterator::from_str(input);
99-
result_to_json(parse_one_component_value(iter).chain(|(c, _)| Ok(c)))
92+
let result = parse_one_component_value(&mut tokenize(input));
93+
result_to_json(result.chain(|(c, _)| Ok(c)))
10094
}
10195
}
10296
10397
10498
#[test]
10599
fn declaration_list() {
106100
do run_json_tests(include_str!("css-parsing-tests/declaration_list.json")) |input| {
107-
let iter = &mut ComponentValueIterator::from_str(input);
101+
let iter = &mut tokenize(input);
108102
let mut declarations = ~[];
109103
loop {
110104
match parse_declaration_or_at_rule(iter) {
@@ -120,15 +114,15 @@ fn declaration_list() {
120114
#[test]
121115
fn one_declaration() {
122116
do run_json_tests(include_str!("css-parsing-tests/one_declaration.json")) |input| {
123-
result_to_json(parse_one_declaration(&mut ComponentValueIterator::from_str(input)))
117+
result_to_json(parse_one_declaration(&mut tokenize(input)))
124118
}
125119
}
126120
127121
128122
#[test]
129123
fn rule_list() {
130124
do run_json_tests(include_str!("css-parsing-tests/rule_list.json")) |input| {
131-
let iter = &mut ComponentValueIterator::from_str(input);
125+
let iter = &mut tokenize(input);
132126
let mut rules = ~[];
133127
loop {
134128
match parse_rule(iter) {
@@ -144,14 +138,14 @@ fn rule_list() {
144138
#[test]
145139
fn one_rule() {
146140
do run_json_tests(include_str!("css-parsing-tests/one_rule.json")) |input| {
147-
result_to_json(parse_one_rule(&mut ComponentValueIterator::from_str(input)))
141+
result_to_json(parse_one_rule(&mut tokenize(input)))
148142
}
149143
}
150144
151145
152146
fn run_color_tests(json_data: &str, to_json: &fn(result: Option<Color>) -> json::Json) {
153147
do run_json_tests(json_data) |input| {
154-
match parse_one_component_value(&mut ComponentValueIterator::from_str(input)) {
148+
match parse_one_component_value(&mut tokenize(input)) {
155149
Ok((component_value, _location)) => to_json(parse_color(&component_value)),
156150
Err(_reason) => json::Null,
157151
}

0 commit comments

Comments
 (0)