Skip to content

Iterators! Iterators everywhere! #4

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

Merged
merged 14 commits into from
Aug 13, 2013
Merged
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
12 changes: 5 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
rust-cssparser
==============

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


TODO
----

* [x] Tokenization
* [x] Declaration and rule parsing
* [ ] Detect character encoding & decode from bytes
* [ ] Track line/column number for tokens.
* [ ] Figure out float and integer overflow
* [ ] Make it fast!
* Detect character encoding & decode from bytes
* Figure out float and integer overflow
* Serialize tokens back to CSS
* Make it fast!
88 changes: 74 additions & 14 deletions ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::str::ToStr;
use std::vec;


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


pub type Node = (ComponentValue, SourceLocation); // TODO this is not a good name


#[deriving(Eq)]
pub enum ComponentValue {
// Preserved tokens. Same as in the tokenizer.
// Preserved tokens.
Ident(~str),
AtKeyword(~str),
Hash(~str),
IDHash(~str), // Hash token that is a valid ID selector.
IDHash(~str), // Hash that is a valid ID selector.
String(~str),
URL(~str),
Delim(char),
Expand All @@ -39,7 +43,7 @@ pub enum ComponentValue {
Colon, // :
Semicolon, // ;
Comma, // ,
IncludeMath, // ~=
IncludeMatch, // ~=
DashMatch, // |=
PrefixMatch, // ^=
SuffixMatch, // $=
Expand All @@ -49,12 +53,12 @@ pub enum ComponentValue {
CDC, // -->

// Function
Function(~str, ~[(ComponentValue, SourceLocation)]), // name, arguments
Function(~str, ~[ComponentValue]), // name, arguments

// Simple block
ParenthesisBlock(~[(ComponentValue, SourceLocation)]), // (…)
SquareBracketBlock(~[(ComponentValue, SourceLocation)]), // […]
CurlyBracketBlock(~[(ComponentValue, SourceLocation)]), // {…}
ParenthesisBlock(~[ComponentValue]), // (…)
SquareBracketBlock(~[ComponentValue]), // […]
CurlyBracketBlock(~[Node]), // {…}

// These are always invalid
BadURL,
Expand All @@ -69,23 +73,23 @@ pub enum ComponentValue {
pub struct Declaration {
location: SourceLocation,
name: ~str,
value: ~[(ComponentValue, SourceLocation)],
value: ~[ComponentValue],
important: bool,
}

#[deriving(Eq)]
pub struct QualifiedRule {
location: SourceLocation,
prelude: ~[(ComponentValue, SourceLocation)],
block: ~[(ComponentValue, SourceLocation)],
prelude: ~[ComponentValue],
block: ~[Node],
}

#[deriving(Eq)]
pub struct AtRule {
location: SourceLocation,
name: ~str,
prelude: ~[(ComponentValue, SourceLocation)],
block: Option<~[(ComponentValue, SourceLocation)]>,
prelude: ~[ComponentValue],
block: Option<~[Node]>,
}

#[deriving(Eq)]
Expand All @@ -101,6 +105,12 @@ pub enum Rule {
AtRule(AtRule),
}

#[deriving(Eq)]
pub struct SyntaxError {
location: SourceLocation,
reason: ErrorReason,
}

#[deriving(Eq)]
pub enum ErrorReason {
ErrEmptyInput, // Parsing a single "thing", found only whitespace.
Expand All @@ -111,6 +121,56 @@ pub enum ErrorReason {
// This is meant to be extended
}

impl ToStr for ErrorReason {
fn to_str(&self) -> ~str { fmt!("%?", self) }
impl ToStr for SyntaxError {
fn to_str(&self) -> ~str {
fmt!("%u:%u %?", self.location.line, self.location.column, self.reason)
}
}


pub trait SkipWhitespaceIterable<'self> {
pub fn skip_whitespace(self) -> SkipWhitespaceIterator<'self>;
}

impl<'self> SkipWhitespaceIterable<'self> for &'self [ComponentValue] {
pub fn skip_whitespace(self) -> SkipWhitespaceIterator<'self> {
SkipWhitespaceIterator{ iter: self.iter() }
}
}

struct SkipWhitespaceIterator<'self> {
iter: vec::VecIterator<'self, ComponentValue>,
}

impl<'self> Iterator<&'self ComponentValue> for SkipWhitespaceIterator<'self> {
fn next(&mut self) -> Option<&'self ComponentValue> {
for component_value in self.iter {
if component_value != &WhiteSpace { return Some(component_value) }
}
None
}
}


pub trait ConsumeSkipWhitespaceIterable {
pub fn consume_skip_whitespace(self) -> ConsumeSkipWhitespaceIterator;
}

impl ConsumeSkipWhitespaceIterable for ~[ComponentValue] {
pub fn consume_skip_whitespace(self) -> ConsumeSkipWhitespaceIterator {
ConsumeSkipWhitespaceIterator{ iter: self.consume_iter() }
}
}

struct ConsumeSkipWhitespaceIterator {
iter: vec::ConsumeIterator<ComponentValue>,
}

impl Iterator<ComponentValue> for ConsumeSkipWhitespaceIterator {
fn next(&mut self) -> Option<ComponentValue> {
for component_value in self.iter {
if component_value != WhiteSpace { return Some(component_value) }
}
None
}
}
6 changes: 2 additions & 4 deletions color.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ fn parse_color_hash(value: &str) -> Option<Color> {


#[inline]
fn parse_color_function(name: &str, arguments: &[(ComponentValue, SourceLocation)])
fn parse_color_function(name: &str, arguments: &[ComponentValue])
-> Option<Color> {
let lower_name = to_ascii_lower(name);

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

let mut iter = do arguments.iter().filter_map |&(ref c, _)| {
if c != &WhiteSpace { Some(c) } else { None }
};
let mut iter = arguments.skip_whitespace();
macro_rules! expect_comma(
() => ( if iter.next() != Some(&Comma) { return None } );
)
Expand Down
13 changes: 9 additions & 4 deletions cssparser.rc
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,15 @@

extern mod extra;

pub mod tokenizer;
pub mod parser;
pub mod ast;
pub mod color;
pub use ast::*;
pub use tokenizer::*;
pub use parser::*;
pub use color::*;

mod ast;
mod tokenizer;
mod parser;
mod color;

#[cfg(test)]
mod tests;
Loading