Skip to content

Commit e7208c1

Browse files
committed
Small changes to ensure that we can output the original source.
This is almost complete now - only quotes appear to be incorrect.
1 parent 9707ade commit e7208c1

File tree

7 files changed

+105
-159
lines changed

7 files changed

+105
-159
lines changed

src/ast.rs

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,22 @@
22
* License, v. 2.0. If a copy of the MPL was not distributed with this
33
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44

5-
use std::str;
65
use std::fmt;
76
use std::slice;
87
use std::vec;
98
use serialize::{json};
109
use serialize::json::ToJson;
1110

1211

13-
#[deriving(PartialEq)]
12+
#[deriving(PartialEq, Show)]
1413
pub struct NumericValue {
1514
pub representation: String,
1615
pub value: f64,
1716
pub int_value: Option<i64>,
1817
}
1918

2019

21-
#[deriving(PartialEq)]
20+
#[deriving(PartialEq, Show)]
2221
pub struct SourceLocation {
2322
pub line: uint, // First line is 1
2423
pub column: uint, // First character of a line is at column 1
@@ -28,7 +27,7 @@ pub struct SourceLocation {
2827
pub type Node = (ComponentValue, SourceLocation); // TODO this is not a good name
2928

3029

31-
#[deriving(PartialEq)]
30+
#[deriving(PartialEq, Show)]
3231
pub enum ComponentValue {
3332
// Preserved tokens.
3433
Ident(String),
@@ -42,7 +41,7 @@ pub enum ComponentValue {
4241
Percentage(NumericValue),
4342
Dimension(NumericValue, String),
4443
UnicodeRange(u32, u32), // (start, end) of range
45-
WhiteSpace,
44+
WhiteSpace(String),
4645
Colon, // :
4746
Semicolon, // ;
4847
Comma, // ,
@@ -72,40 +71,41 @@ pub enum ComponentValue {
7271
}
7372

7473

75-
#[deriving(PartialEq)]
74+
#[deriving(PartialEq, Show)]
7675
pub struct Declaration {
7776
pub location: SourceLocation,
7877
pub name: String,
7978
pub value: Vec<ComponentValue>,
8079
pub important: bool,
8180
}
8281

83-
#[deriving(PartialEq)]
82+
#[deriving(PartialEq, Show)]
8483
pub struct QualifiedRule {
8584
pub location: SourceLocation,
8685
pub prelude: Vec<ComponentValue>,
8786
pub block: Vec<Node>,
8887
}
8988

90-
#[deriving(PartialEq)]
89+
#[deriving(PartialEq, Show)]
9190
pub struct AtRule {
9291
pub location: SourceLocation,
9392
pub name: String,
9493
pub prelude: Vec<ComponentValue>,
9594
pub block: Option<Vec<Node>>,
9695
}
9796

98-
#[deriving(PartialEq)]
97+
#[deriving(PartialEq, Show)]
9998
pub enum DeclarationListItem {
10099
Declaration(Declaration),
101100
// A better idea for a name that means "at-rule" but is not "AtRule"?
102101
DeclAtRule(AtRule),
103102
}
104103

105-
#[deriving(PartialEq)]
104+
#[deriving(PartialEq, Show)]
106105
pub enum Rule {
107106
QualifiedRule(QualifiedRule),
108107
AtRule(AtRule),
108+
NonRule(ComponentValue)
109109
}
110110

111111
#[deriving(PartialEq)]
@@ -114,7 +114,7 @@ pub struct SyntaxError {
114114
pub reason: ErrorReason,
115115
}
116116

117-
#[deriving(PartialEq)]
117+
#[deriving(PartialEq, Show)]
118118
pub enum ErrorReason {
119119
ErrEmptyInput, // Parsing a single "thing", found only whitespace.
120120
ErrExtraInput, // Found more non-whitespace after parsing a single "thing".
@@ -149,7 +149,10 @@ pub struct SkipWhitespaceIterator<'a> {
149149
impl<'a> Iterator<&'a ComponentValue> for SkipWhitespaceIterator<'a> {
150150
fn next(&mut self) -> Option<&'a ComponentValue> {
151151
for component_value in self.iter_with_whitespace {
152-
if component_value != &WhiteSpace { return Some(component_value) }
152+
match component_value {
153+
&WhiteSpace(_) => (),
154+
_ => return Some(component_value)
155+
}
153156
}
154157
None
155158
}
@@ -173,7 +176,10 @@ pub struct MoveSkipWhitespaceIterator {
173176
impl Iterator<ComponentValue> for MoveSkipWhitespaceIterator {
174177
fn next(&mut self) -> Option<ComponentValue> {
175178
for component_value in self.iter_with_whitespace {
176-
if component_value != WhiteSpace { return Some(component_value) }
179+
match component_value {
180+
WhiteSpace(_) => (),
181+
_ => return Some(component_value)
182+
}
177183
}
178184
None
179185
}
@@ -269,6 +275,7 @@ impl ToJson for Rule {
269275
match *self {
270276
QualifiedRule(ref rule) => rule.to_json(),
271277
AtRule(ref rule) => rule.to_json(),
278+
NonRule(ref component_value) => component_value.to_json()
272279
}
273280
}
274281
}
@@ -302,7 +309,7 @@ impl ToJson for ComponentValue {
302309
String(ref value) => JList!(JString!("string"), value.to_json()),
303310
URL(ref value) => JList!(JString!("url"), value.to_json()),
304311
Delim('\\') => JString!("\\"),
305-
Delim(value) => json::String(str::from_char(value)),
312+
Delim(value) => json::String(String::from_char(1, value)),
306313

307314
Number(ref value) => json::List(vec!(JString!("number")) + numeric(value)),
308315
Percentage(ref value) => json::List(vec!(JString!("percentage")) + numeric(value)),
@@ -312,7 +319,7 @@ impl ToJson for ComponentValue {
312319
UnicodeRange(start, end)
313320
=> JList!(JString!("unicode-range"), start.to_json(), end.to_json()),
314321

315-
WhiteSpace => JString!(" "),
322+
WhiteSpace(ref value) => JString!(value.to_json()),
316323
Colon => JString!(":"),
317324
Semicolon => JString!(";"),
318325
Comma => JString!(","),

src/bin/rust-less.rs

Lines changed: 64 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -2,167 +2,101 @@
22
* License, v. 2.0. If a copy of the MPL was not distributed with this
33
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44

5-
#![feature(macro_rules, globs)]
5+
#![feature(macro_rules, globs, phase)]
6+
7+
#[phase(plugin, link)] extern crate log;
68

79
extern crate serialize;
810
extern crate encoding;
911
extern crate cssparser;
1012

11-
use std::{io, task};
12-
use std::io::{File, Command, Writer, TempDir};
13-
use serialize::{json};
14-
use serialize::json::ToJson;
15-
16-
use encoding::label::encoding_from_whatwg_label;
13+
use std::io;
14+
use std::io::{File, Writer};
1715

1816
use cssparser::*;
1917
use cssparser::ast::*;
2018

21-
fn write_whole_file(path: &Path, data: &str) {
22-
match File::open_mode(path, io::Open, io::Write) {
23-
Ok(mut writer) => { writer.write(data.as_bytes()).unwrap(); },
24-
_ => fail!("could not open file"),
25-
}
26-
}
19+
macro_rules! try_write(
20+
($buf:expr, $($args:tt)*) => (match write!($buf, $($args)*) { Ok(e) => e, Err(_e) => return Err(()) })
21+
)
2722

23+
fn print_css(mut rules: Vec<Result<Rule, SyntaxError>>) -> Result<String, ()> {
24+
let mut buffer = io::MemWriter::new();
2825

29-
fn almost_equals(a: &json::Json, b: &json::Json) -> bool {
30-
match (a, b) {
31-
(&json::Number(a), &json::Number(b)) => (a - b).abs() < 1e-6,
32-
(&json::String(ref a), &json::String(ref b)) => a == b,
33-
(&json::Boolean(a), &json::Boolean(b)) => a == b,
34-
(&json::List(ref a), &json::List(ref b))
35-
=> a.iter().zip(b.iter()).all(|(ref a, ref b)| almost_equals(*a, *b)),
36-
(&json::Object(_), &json::Object(_)) => fail!("Not implemented"),
37-
(&json::Null, &json::Null) => true,
38-
_ => false,
26+
fn print_prelude(buffer: &mut io::MemWriter,
27+
prelude: &mut Vec<ComponentValue>) -> Result<(), ()> {
28+
for p in prelude.mut_iter() {
29+
try_write!(buffer, "{}", p.to_css());
30+
}
31+
Ok(())
3932
}
40-
}
4133

34+
fn print_block(buffer: &mut io::MemWriter,
35+
block: &mut Vec<Node>) -> Result<(), ()> {
36+
try_write!(buffer, "{{");
37+
for &(ref mut b, _) in block.mut_iter() {
38+
try_write!(buffer, "{}", b.to_css());
39+
}
40+
try_write!(buffer, "}}");
4241

43-
fn assert_json_eq(results: json::Json, expected: json::Json, message: String) {
44-
if !almost_equals(&results, &expected) {
45-
let temp = TempDir::new("rust-cssparser-tests").unwrap();
46-
let results = results.to_pretty_str().append("\n");
47-
let expected = expected.to_pretty_str().append("\n");
48-
task::try(proc() {
49-
let mut result_path = temp.path().clone();
50-
result_path.push("results.json");
51-
let mut expected_path = temp.path().clone();
52-
expected_path.push("expected.json");
53-
write_whole_file(&result_path, results.as_slice());
54-
write_whole_file(&expected_path, expected.as_slice());
55-
Command::new("colordiff")
56-
.arg("-u1000")
57-
.arg(result_path)
58-
.arg(expected_path)
59-
.status().unwrap_or_else(|e| fail!("Failed to get status of colordiff: {}", e));
60-
}).unwrap_or_else(|_e| fail!("Failed to execute task"));
61-
62-
fail!(message)
42+
Ok(())
6343
}
64-
}
6544

66-
67-
fn run_raw_json_tests(json_data: &str, run: |json::Json, json::Json|) {
68-
let items = match json::from_str(json_data) {
69-
Ok(json::List(items)) => items,
70-
_ => fail!("Invalid JSON")
71-
};
72-
assert!(items.len() % 2 == 0);
73-
let mut input = None;
74-
for item in items.move_iter() {
75-
match (&input, item) {
76-
(&None, json_obj) => input = Some(json_obj),
77-
(&Some(_), expected) => {
78-
let input = input.take_unwrap();
79-
run(input, expected)
45+
for r in rules.mut_iter() {
46+
match *r {
47+
Ok(ref mut rule) => {
48+
match *rule {
49+
QualifiedRule(ref mut q) => {
50+
try!(print_prelude(&mut buffer, &mut q.prelude));
51+
try!(print_block(&mut buffer, &mut q.block));
52+
},
53+
AtRule(ref mut a) => {
54+
//try_write!(buffer, "{}\n", a);
55+
try_write!(buffer, "@{}", a.name);
56+
try!(print_prelude(&mut buffer, &mut a.prelude));
57+
match a.block {
58+
None => (),
59+
Some(ref mut b) => try!(print_block(&mut buffer, b))
60+
}
61+
},
62+
NonRule(ref mut component_value) => {
63+
try_write!(buffer, "{}", component_value.to_css());
64+
}
65+
}
8066
},
67+
Err(e) => {
68+
try_write!(buffer, "Err: {}", e);
69+
}
8170
};
8271
}
83-
}
84-
85-
86-
fn run_json_tests<T: ToJson>(json_data: &str, parse: |input: &str| -> T) {
87-
run_raw_json_tests(json_data, |input, expected| {
88-
match input {
89-
json::String(input) => {
90-
let result = parse(input.as_slice()).to_json();
91-
assert_json_eq(result, expected, input);
92-
},
93-
_ => fail!("Unexpected JSON")
94-
}
95-
});
96-
}
97-
9872

99-
100-
#[test]
101-
fn stylesheet() {
102-
/*run_json_tests(include_str!("../css-parsing-tests/stylesheet.json"), |input| {
103-
parse_stylesheet_rules(tokenize(input)).collect::<Vec<Result<Rule, SyntaxError>>>()
104-
});*/
73+
String::from_utf8(buffer.unwrap())
74+
.map_err(|_| ())
10575
}
10676

107-
#[test]
108-
fn stylesheet_from_bytes() {
109-
/*run_raw_json_tests(include_str!("../css-parsing-tests/stylesheet_bytes.json"),
110-
|input, expected| {
111-
let map = match input {
112-
json::Object(map) => map,
113-
_ => fail!("Unexpected JSON")
114-
};
115-
116-
let result = {
117-
let css = get_string(&map, &"css_bytes".to_string()).unwrap().chars().map(|c| {
118-
assert!(c as u32 <= 0xFF);
119-
c as u8
120-
}).collect::<Vec<u8>>();
121-
let protocol_encoding_label = get_string(&map, &"protocol_encoding".to_string());
122-
let environment_encoding = get_string(&map, &"environment_encoding".to_string())
123-
.and_then(encoding_from_whatwg_label);
124-
125-
let (mut rules, used_encoding) = parse_stylesheet_rules_from_bytes(
126-
css.as_slice(), protocol_encoding_label, environment_encoding);
127-
128-
(rules.collect::<Vec<Result<Rule, SyntaxError>>>(), used_encoding.name().to_string()).to_json()
129-
};
130-
assert_json_eq(result, expected, json::Object(map).to_pretty_str());
131-
});
132-
133-
fn get_string<'a>(map: &'a json::Object, key: &String) -> Option<&'a str> {
134-
match map.find(key) {
135-
Some(&json::String(ref s)) => Some(s.as_slice()),
136-
Some(&json::Null) => None,
137-
None => None,
138-
_ => fail!("Unexpected JSON"),
139-
}
140-
}*/
77+
fn print_json(rules: &Vec<Result<Rule, SyntaxError>>) {
78+
use serialize::json::ToJson;
79+
debug!("{}", rules.to_json());
14180
}
14281

143-
144-
fn run_color_tests(json_data: &str, to_json: |result: Option<Color>| -> json::Json) {
145-
run_json_tests(json_data, |input| {
146-
match parse_one_component_value(tokenize(input)) {
147-
Ok(component_value) => to_json(Color::parse(&component_value)),
148-
Err(_reason) => json::Null,
149-
}
150-
});
151-
}
152-
153-
15482
fn main() {
155-
let contents = File::open(&Path::new("test/less/css.less")).read_to_end();
83+
let contents = File::open(&Path::new("test/less/variables.less")).read_to_end();
15684

15785
let contents = match contents {
15886
Err(e) => fail!(e),
15987
Ok(c) => c
16088
};
16189

162-
println!("{}", contents);
90+
let (css_unicode, _encoding) = decode_stylesheet_bytes(contents.as_slice(), None, None);
91+
92+
let tokens = tokenize(css_unicode.as_slice());
93+
let mut rules = parse_stylesheet_rules(tokens);
16394

164-
let (mut rules, used_encoding) = cssparser::parse_stylesheet_rules_from_bytes(
165-
contents.as_slice(), None, None);
95+
let rules = rules.collect::<Vec<Result<Rule, SyntaxError>>>();
96+
print_json(&rules);
16697

167-
println!("{}", rules.collect::<Vec<Result<Rule, SyntaxError>>>().to_json());
98+
match print_css(rules) {
99+
Ok(res) => println!("{}", res),
100+
Err(e) => println!("Err: {}", e)
101+
}
168102
}

src/from_bytes.rs

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

55
use std::cmp;
6-
use std::str;
76

87
use encoding::label::encoding_from_whatwg_label;
98
use encoding::all::UTF_8;
@@ -50,7 +49,7 @@ pub fn decode_stylesheet_bytes(css: &[u8], protocol_encoding_label: Option<&str>
5049
Some(label_length)
5150
=> if css.slice_from(10 + label_length).starts_with("\";".as_bytes()) {
5251
let label = css.slice(10, 10 + label_length);
53-
let label = str::from_chars(label.iter().map(|&b| b as char).collect::<Vec<char>>().as_slice());
52+
let label = String::from_chars(label.iter().map(|&b| b as char).collect::<Vec<char>>().as_slice());
5453
match encoding_from_whatwg_label(label.as_slice()) {
5554
None => (),
5655
Some(fallback) => match fallback.name() {

0 commit comments

Comments
 (0)