Skip to content

Update to today’s Rust #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::str::ToStr;


#[deriving(Eq)]
pub struct NumericValue {
Expand Down Expand Up @@ -108,3 +110,7 @@ pub enum ErrorReason {
ErrInvalidBangImportantSyntax,
// This is meant to be extended
}

impl ToStr for ErrorReason {
fn to_str(&self) -> ~str { fmt!("%?", self) }
}
3 changes: 2 additions & 1 deletion color.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::libc::c_float;
use std::ascii::to_ascii_lower;

use ast::*;
use super::to_ascii_lower;
use self::color_data::{COLOR_KEYWORDS, COLOR_VALUES};

mod color_data;
Expand Down
91 changes: 0 additions & 91 deletions cssparser.rc
Original file line number Diff line number Diff line change
Expand Up @@ -14,94 +14,3 @@ pub mod color;

#[cfg(test)]
mod tests;


#[cfg(not(test))]
static CFG_TEST: bool = false;

#[cfg(test)]
static CFG_TEST: bool = true;


/// Return whether `string` is an ASCII case-insensitive match for `reference`,
/// where `reference` is already in ASCII lower-case.
pub fn eq_ascii_lower(string: &str, reference: &str) -> bool {
#[inline]
fn eq(string: &str, reference: &str) -> bool {
for std::uint::range(0, string.len()) |i| {
if ASCII_LOWER_MAP[string[i]] != reference[i] {
return false
}
}
true
}

if CFG_TEST {
assert!(eq(reference, reference), ~"Reference must be ASCII lower case.");
}
string.len() == reference.len() && eq(string, reference)
}


/// Return an ASCII lower-case copy of `string`:
/// A-Z is replaced by a-z, non-ASCII letters are unchanged.
pub fn to_ascii_lower(string: &str) -> ~str {
let mut lower = string.to_owned();
for std::uint::range(0, lower.len()) |i| {
lower[i] = ASCII_LOWER_MAP[lower[i]];
}
lower
}


#[test]
fn test_ascii_lower() {
assert!(eq_ascii_lower("url()URL()uRl()Ürl", "url()url()url()Ürl"));
assert!(to_ascii_lower("url()URL()uRl()Ürl") == ~"url()url()url()Ürl");
// Dotted capital I, Kelvin sign, Sharp S.
assert!(eq_ascii_lower("HİKß", "hİKß"));
assert!(to_ascii_lower("HİKß") == ~"hİKß");

for std::uint::range(0, 128) |i| {
let c = i as char;
let lower = if 'A' <= c && c <= 'Z' { c + 'a' - 'A' } else { c };
assert!(ASCII_LOWER_MAP[i] as char == lower)
}
}


// This is UTF8-safe because only bytes in the ASCII range are affected.
static ASCII_LOWER_MAP: &'static [u8] = &[
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
];
10 changes: 5 additions & 5 deletions parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@

use std::iterator::Iterator;
use std::vec;
use std::ascii::eq_ignore_ascii_case;

use ast::*;
use tokenizer::*;
use super::eq_ascii_lower;


// TODO: Use a trait?
enum ComponentValueIterator {
ParserIter(~Parser),
VectorIter(vec::VecConsumeIterator<(ComponentValue, SourceLocation)>),
VectorIter(vec::ConsumeIterator<(ComponentValue, SourceLocation)>),
}


Expand All @@ -43,7 +43,7 @@ impl ComponentValueIterator {

#[inline]
pub fn next_non_whitespace(&mut self) -> Option<(ComponentValue, SourceLocation)> {
for self.advance |(component_value, location)| {
for (component_value, location) in *self {
if component_value != WhiteSpace { return Some((component_value, location)) }
}
None
Expand Down Expand Up @@ -127,7 +127,7 @@ pub fn parse_declaration_or_at_rule(iter: &mut ComponentValueIterator)
Ok(declaration) => Ok(Declaration(declaration)),
Err(reason) => {
// Find the end of the declaration
for iter.advance |(v, _)| { if v == Semicolon { break } }
for (v, _) in *iter { if v == Semicolon { break } }
Err(reason)
}
}),
Expand Down Expand Up @@ -234,7 +234,7 @@ fn parse_declaration_important(iter: &mut ComponentValueIterator) -> bool {
Some((Ident(value), _)) => value,
_ => return false,
};
if !eq_ascii_lower(ident_value, "important") { return false }
if !eq_ignore_ascii_case(ident_value, "important") { return false }
match iter.next_non_whitespace() {
Some((Semicolon, _)) => true,
None => true,
Expand Down
8 changes: 4 additions & 4 deletions tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ fn almost_equals(a: &json::Json, b: &json::Json) -> bool {

fn assert_json_eq(results: json::Json, expected: json::Json, message: ~str) {
if !almost_equals(&results, &expected) {
let temp = tempfile::mkdtemp(&os::tmpdir(), "rust-cssparser-tests").get();
let temp_ = copy temp;
let temp = tempfile::mkdtemp(&os::tmpdir(), "rust-cssparser-tests").unwrap();
let temp_ = temp.clone();
let results = json::to_pretty_str(&results) + "\n";
let expected = json::to_pretty_str(&expected) + "\n";
do task::try {
Expand All @@ -62,11 +62,11 @@ fn run_json_tests(json_data: &str, parse: &fn (input: ~str) -> json::Json) {
};
assert!(items.len() % 2 == 0);
let mut input: Option<~str> = None;
for items.consume_iter().advance |item| {
for item in items.consume_iter() {
match (&input, item) {
(&None, json::String(string)) => input = Some(string),
(&Some(_), expected) => {
let input = input.swap_unwrap();
let input = input.take_unwrap();
let result = parse(input.to_owned());
assert_json_eq(result, expected, input);
},
Expand Down
21 changes: 7 additions & 14 deletions tokenizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
// http://dev.w3.org/csswg/css3-syntax/#tokenization

use std::{str, u32, i64, f64};
use std::ascii::eq_ignore_ascii_case;

use ast::*;
use super::eq_ascii_lower;


struct Parser {
Expand Down Expand Up @@ -43,7 +43,7 @@ macro_rules! is_match(
pub fn next_component_value(parser: &mut Parser) -> Option<(ComponentValue, SourceLocation)> {
consume_comments(parser);
if parser.is_eof() {
if CFG_TEST {
if cfg!(test) {
assert!(parser.line == parser.input.split_iter('\n').len_(),
"The tokenizer is missing a parser.new_line() call somewhere.")
}
Expand Down Expand Up @@ -197,13 +197,6 @@ pub fn next_component_value(parser: &mut Parser) -> Option<(ComponentValue, Sour
// *********** End of public API ***********


#[cfg(not(test))]
static CFG_TEST: bool = false;

#[cfg(test)]
static CFG_TEST: bool = true;


#[inline]
fn preprocess(input: &str) -> ~str {
// TODO: Is this faster if done in one pass?
Expand Down Expand Up @@ -246,7 +239,7 @@ impl Parser {

#[inline]
fn new_line(&mut self) {
if CFG_TEST {
if cfg!(test) {
assert!(self.input.char_at(self.position - 1) == '\n')
}
self.line += 1;
Expand Down Expand Up @@ -347,7 +340,7 @@ fn is_ident_start(parser: &mut Parser) -> bool {
fn consume_ident_like(parser: &mut Parser) -> ComponentValue {
let value = consume_name(parser);
if !parser.is_eof() && parser.current_char() == '(' {
if eq_ascii_lower(value, "url") { consume_url(parser) }
if eq_ignore_ascii_case(value, "url") { consume_url(parser) }
else { Function(value, consume_block(parser, CloseParenthesis)) }
} else {
Ident(value)
Expand Down Expand Up @@ -429,9 +422,9 @@ fn consume_numeric(parser: &mut Parser) -> ComponentValue {
i64::from_str(representation)
} else {
i64::from_str(representation.slice_from(1))
}.get()
}.unwrap()
)} else { None },
value: f64::from_str(representation).get(),
value: f64::from_str(representation).unwrap(),
representation: representation,
};
if !parser.is_eof() && parser.current_char() == '%' {
Expand Down Expand Up @@ -599,5 +592,5 @@ fn consume_escape(parser: &mut Parser) -> char {

#[inline]
fn char_from_hex(hex: &str) -> char {
u32::from_str_radix(hex, 16).get() as char
u32::from_str_radix(hex, 16).unwrap() as char
}