Skip to content

Commit 7e130b8

Browse files
committed
Merge pull request #5 from SimonSapin/an+b
Add <An+B> parsing.
2 parents fc4a1cc + 55e49cd commit 7e130b8

File tree

12 files changed

+927
-502
lines changed

12 files changed

+927
-502
lines changed

Makefile.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ RUST_SRC=$(shell find $(VPATH)/. -type f -name '*.rs') $(COLOR_DATA_RS)
1414
all: libcssparser.dummy
1515

1616
libcssparser.dummy: cssparser.rc $(RUST_SRC)
17-
$(RUSTC) $(RUSTFLAGS) $< -o $@
17+
$(RUSTC) $(RUSTFLAGS) $<
1818
touch $@
1919

2020
cssparser-test: cssparser.rc $(RUST_SRC)

README.md

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
rust-cssparser
22
==============
33

4-
WIP rust implementation of the 2013 version of
4+
Rust implementation of the 2013 version of
55
[css3-syntax](http://dev.w3.org/csswg/css3-syntax/)
66

77

88
TODO
99
----
1010

11-
* [x] Tokenization
12-
* [x] Declaration and rule parsing
13-
* [ ] Detect character encoding & decode from bytes
14-
* [ ] Track line/column number for tokens.
15-
* [ ] Figure out float and integer overflow
16-
* [ ] Make it fast!
11+
* Detect character encoding & decode from bytes
12+
* Figure out float and integer overflow
13+
* Serialize tokens back to CSS
14+
* Make it fast!

ast.rs

Lines changed: 74 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44

55
use std::str::ToStr;
6+
use std::vec;
67

78

89
#[deriving(Eq)]
@@ -20,13 +21,16 @@ pub struct SourceLocation {
2021
}
2122

2223

24+
pub type Node = (ComponentValue, SourceLocation); // TODO this is not a good name
25+
26+
2327
#[deriving(Eq)]
2428
pub enum ComponentValue {
25-
// Preserved tokens. Same as in the tokenizer.
29+
// Preserved tokens.
2630
Ident(~str),
2731
AtKeyword(~str),
2832
Hash(~str),
29-
IDHash(~str), // Hash token that is a valid ID selector.
33+
IDHash(~str), // Hash that is a valid ID selector.
3034
String(~str),
3135
URL(~str),
3236
Delim(char),
@@ -39,7 +43,7 @@ pub enum ComponentValue {
3943
Colon, // :
4044
Semicolon, // ;
4145
Comma, // ,
42-
IncludeMath, // ~=
46+
IncludeMatch, // ~=
4347
DashMatch, // |=
4448
PrefixMatch, // ^=
4549
SuffixMatch, // $=
@@ -49,12 +53,12 @@ pub enum ComponentValue {
4953
CDC, // -->
5054

5155
// Function
52-
Function(~str, ~[(ComponentValue, SourceLocation)]), // name, arguments
56+
Function(~str, ~[ComponentValue]), // name, arguments
5357

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

5963
// These are always invalid
6064
BadURL,
@@ -69,23 +73,23 @@ pub enum ComponentValue {
6973
pub struct Declaration {
7074
location: SourceLocation,
7175
name: ~str,
72-
value: ~[(ComponentValue, SourceLocation)],
76+
value: ~[ComponentValue],
7377
important: bool,
7478
}
7579

7680
#[deriving(Eq)]
7781
pub struct QualifiedRule {
7882
location: SourceLocation,
79-
prelude: ~[(ComponentValue, SourceLocation)],
80-
block: ~[(ComponentValue, SourceLocation)],
83+
prelude: ~[ComponentValue],
84+
block: ~[Node],
8185
}
8286

8387
#[deriving(Eq)]
8488
pub struct AtRule {
8589
location: SourceLocation,
8690
name: ~str,
87-
prelude: ~[(ComponentValue, SourceLocation)],
88-
block: Option<~[(ComponentValue, SourceLocation)]>,
91+
prelude: ~[ComponentValue],
92+
block: Option<~[Node]>,
8993
}
9094

9195
#[deriving(Eq)]
@@ -101,6 +105,12 @@ pub enum Rule {
101105
AtRule(AtRule),
102106
}
103107

108+
#[deriving(Eq)]
109+
pub struct SyntaxError {
110+
location: SourceLocation,
111+
reason: ErrorReason,
112+
}
113+
104114
#[deriving(Eq)]
105115
pub enum ErrorReason {
106116
ErrEmptyInput, // Parsing a single "thing", found only whitespace.
@@ -111,6 +121,56 @@ pub enum ErrorReason {
111121
// This is meant to be extended
112122
}
113123

114-
impl ToStr for ErrorReason {
115-
fn to_str(&self) -> ~str { fmt!("%?", self) }
124+
impl ToStr for SyntaxError {
125+
fn to_str(&self) -> ~str {
126+
fmt!("%u:%u %?", self.location.line, self.location.column, self.reason)
127+
}
128+
}
129+
130+
131+
pub trait SkipWhitespaceIterable<'self> {
132+
pub fn skip_whitespace(self) -> SkipWhitespaceIterator<'self>;
133+
}
134+
135+
impl<'self> SkipWhitespaceIterable<'self> for &'self [ComponentValue] {
136+
pub fn skip_whitespace(self) -> SkipWhitespaceIterator<'self> {
137+
SkipWhitespaceIterator{ iter_with_whitespace: self.iter() }
138+
}
139+
}
140+
141+
pub struct SkipWhitespaceIterator<'self> {
142+
iter_with_whitespace: vec::VecIterator<'self, ComponentValue>,
143+
}
144+
145+
impl<'self> Iterator<&'self ComponentValue> for SkipWhitespaceIterator<'self> {
146+
fn next(&mut self) -> Option<&'self ComponentValue> {
147+
for component_value in self.iter_with_whitespace {
148+
if component_value != &WhiteSpace { return Some(component_value) }
149+
}
150+
None
151+
}
152+
}
153+
154+
155+
pub trait MoveSkipWhitespaceIterable {
156+
pub fn move_skip_whitespace(self) -> MoveSkipWhitespaceIterator;
157+
}
158+
159+
impl MoveSkipWhitespaceIterable for ~[ComponentValue] {
160+
pub fn move_skip_whitespace(self) -> MoveSkipWhitespaceIterator {
161+
MoveSkipWhitespaceIterator{ iter_with_whitespace: self.move_iter() }
162+
}
163+
}
164+
165+
pub struct MoveSkipWhitespaceIterator {
166+
iter_with_whitespace: vec::MoveIterator<ComponentValue>,
167+
}
168+
169+
impl Iterator<ComponentValue> for MoveSkipWhitespaceIterator {
170+
fn next(&mut self) -> Option<ComponentValue> {
171+
for component_value in self.iter_with_whitespace {
172+
if component_value != WhiteSpace { return Some(component_value) }
173+
}
174+
None
175+
}
116176
}

color.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
15
use std::libc::c_float;
26
use std::ascii::to_ascii_lower;
37

@@ -76,7 +80,7 @@ fn parse_color_hash(value: &str) -> Option<Color> {
7680

7781

7882
#[inline]
79-
fn parse_color_function(name: &str, arguments: &[(ComponentValue, SourceLocation)])
83+
fn parse_color_function(name: &str, arguments: &[ComponentValue])
8084
-> Option<Color> {
8185
let lower_name = to_ascii_lower(name);
8286

@@ -87,9 +91,7 @@ fn parse_color_function(name: &str, arguments: &[(ComponentValue, SourceLocation
8791
else if "hsla" == lower_name { (false, true) }
8892
else { return None };
8993

90-
let mut iter = do arguments.iter().filter_map |&(ref c, _)| {
91-
if c != &WhiteSpace { Some(c) } else { None }
92-
};
94+
let mut iter = arguments.skip_whitespace();
9395
macro_rules! expect_comma(
9496
() => ( if iter.next() != Some(&Comma) { return None } );
9597
)

css-parsing-tests/An+B.json

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
[
2+
3+
"", null,
4+
" \n", null,
5+
6+
"odd", [2, 1],
7+
"even", [2, 0],
8+
"ödd", null,
9+
"éven", null,
10+
" /**/\t OdD /**/\n", [2, 1],
11+
" /**/\t EveN /**/\n", [2, 0],
12+
13+
14+
"3", [0, 3],
15+
"+2 ", [0, 2],
16+
" -14 ", [0, -14],
17+
"+ 2 ", null,
18+
"- 14 ", null,
19+
"3.1", null,
20+
21+
"3N", [3, 0],
22+
"+2N ", [2, 0],
23+
" -14n ", [-14, 0],
24+
"+ 2N ", null,
25+
"- 14N ", null,
26+
"3.1N", null,
27+
"3 n", null,
28+
29+
" N", [1, 0],
30+
" +n", [1, 0],
31+
" -n", [-1, 0],
32+
"+ n", null,
33+
"- n", null,
34+
35+
36+
"3N+1", [3, 1],
37+
"+2n+1 ", [2, 1],
38+
" -14n+1 ", [-14, 1],
39+
"+ 2N+1 ", null,
40+
"- 14n+1 ", null,
41+
"3.1n+1", null,
42+
"3 n+1", null,
43+
44+
" n+1", [1, 1],
45+
" +N+1", [1, 1],
46+
" -n+1", [-1, 1],
47+
"+ N+1", null,
48+
"- N+1", null,
49+
50+
"3n-1", [3, -1],
51+
"+2N-1 ", [2, -1],
52+
" -14n-1 ", [-14, -1],
53+
"+ 2N-1 ", null,
54+
"- 14N-1 ", null,
55+
"3.1n-1", null,
56+
"3 n-1", null,
57+
58+
" n-1", [1, -1],
59+
" +n-1", [1, -1],
60+
" -n-1", [-1, -1],
61+
"+ n-1", null,
62+
"- n-1", null,
63+
64+
65+
"3N +1", [3, 1],
66+
"+2N +1 ", [2, 1],
67+
" -14n +1 ", [-14, 1],
68+
"+ 2N +1 ", null,
69+
"- 14n +1 ", null,
70+
"3.1N +1", null,
71+
"3 n +1", null,
72+
73+
" n +1", [1, 1],
74+
" +N +1", [1, 1],
75+
" -n +1", [-1, 1],
76+
"+ n +1", null,
77+
"- N +1", null,
78+
79+
"3N -1", [3, -1],
80+
"+2n -1 ", [2, -1],
81+
" -14n -1 ", [-14, -1],
82+
"+ 2n -1 ", null,
83+
"- 14N -1 ", null,
84+
"3.1N -1", null,
85+
"3 N -1", null,
86+
87+
" N -1", [1, -1],
88+
" +N -1", [1, -1],
89+
" -n -1", [-1, -1],
90+
"+ n -1", null,
91+
"- n -1", null,
92+
93+
94+
"3n+ 1", [3, 1],
95+
"+2n+ 1 ", [2, 1],
96+
" -14n+ 1 ", [-14, 1],
97+
"+ 2n+ 1 ", null,
98+
"- 14N+ 1 ", null,
99+
"3.1n+ 1", null,
100+
"3 N+ 1", null,
101+
102+
" N+ 1", [1, 1],
103+
" +N+ 1", [1, 1],
104+
" -N+ 1", [-1, 1],
105+
"+ n+ 1", null,
106+
"- N+ 1", null,
107+
108+
"3n- 1", [3, -1],
109+
"+2N- 1 ", [2, -1],
110+
" -14N- 1 ", [-14, -1],
111+
"+ 2N- 1 ", null,
112+
"- 14n- 1 ", null,
113+
"3.1n- 1", null,
114+
"3 n- 1", null,
115+
116+
" N- 1", [1, -1],
117+
" +N- 1", [1, -1],
118+
" -n- 1", [-1, -1],
119+
"+ n- 1", null,
120+
"- N- 1", null,
121+
122+
123+
"3N + 1", [3, 1],
124+
"+2N + 1 ", [2, 1],
125+
" -14n + 1 ", [-14, 1],
126+
"+ 2n + 1 ", null,
127+
"- 14N + 1 ", null,
128+
"3.1n + 1", null,
129+
"3 N + 1", null,
130+
131+
" n + 1", [1, 1],
132+
" +n + 1", [1, 1],
133+
" -N + 1", [-1, 1],
134+
"+ N + 1", null,
135+
"- N + 1", null,
136+
137+
"3N - 1", [3, -1],
138+
"+2n - 1 ", [2, -1],
139+
" -14n - 1 ", [-14, -1],
140+
"+ 2N - 1 ", null,
141+
"- 14N - 1 ", null,
142+
"3.1N - 1", null,
143+
"3 n - 1", null,
144+
145+
" N - 1", [1, -1],
146+
" +n - 1", [1, -1],
147+
" -n - 1", [-1, -1],
148+
"+ N - 1", null,
149+
"- N - 1", null
150+
151+
]

css-parsing-tests/README.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,17 @@ associated with the expected result.
102102
are between 0 and 255.
103103
This file is generated the ``make_color3_keywords.py`` Python script.
104104

105+
``an+b.json``
106+
Tests the `an+b <http://dev.w3.org/csswg/css-syntax/#the-anb-type>`_
107+
syntax defined in CSS Syntax Level 3.
108+
This `differs <http://dev.w3.org/csswg/css-syntax/#changes>`_ from the
109+
`nth grammar rule <http://www.w3.org/TR/css3-selectors/#nth-child-pseudo>`_
110+
in Selectors Level 3 only in that
111+
``-`` charecters and digits can be escaped in some cases.
112+
The Unicode input is represented by a JSON string,
113+
the output as null for invalid syntax,
114+
or an array of two integers ``[A, B]``.
115+
105116

106117
Result representation
107118
=====================

0 commit comments

Comments
 (0)