Changed color parsing to return an option instead of defaulting to black

This commit is contained in:
Margaret Meyerhofer 2012-07-19 13:13:05 -07:00
parent ed99449f52
commit 830a41ad94
2 changed files with 74 additions and 69 deletions

View file

@ -157,16 +157,17 @@ impl parser_methods of parser_methods for TokenReader {
alt tok { alt tok {
EndDescription { break; } EndDescription { break; }
Description(prop, val) { Description(prop, val) {
alt prop { let desc = alt prop {
// TODO: have color parsing return an option instead of a real value // TODO: have color parsing return an option instead of a real value
~"background-color" { push(desc_list, BackgroundColor(parse_color(val))); } ~"background-color" { parse_color(val).map(|res| BackgroundColor(res)) }
~"color" { push(desc_list, TextColor(parse_color(val))); } ~"color" { parse_color(val).map(|res| TextColor(res)) }
~"display" { parse_display_type(val).map(|res| push(desc_list, Display(res))); } ~"display" { parse_display_type(val).map(|res| Display(res)) }
~"font-size" { parse_font_size(val).map(|res| push(desc_list, FontSize(res))); } ~"font-size" { parse_font_size(val).map(|res| FontSize(res)) }
~"height" { parse_size(val).map(|res| push(desc_list, Height(res))); } ~"height" { parse_size(val).map(|res| Height(res)) }
~"width" { parse_size(val).map(|res| push(desc_list, Width(res))); } ~"width" { parse_size(val).map(|res| Width(res)) }
_ { #debug["Recieved unknown style property '%s'", val]; } _ { #debug["Recieved unknown style property '%s'", val]; none }
} };
desc.map(|res| push(desc_list, res));
} }
Eof { ret none; } Eof { ret none; }
StartDescription | Descendant | Child | Sibling | Comma | Element(_) | Attr(_) { StartDescription | Descendant | Child | Sibling | Comma | Element(_) | Attr(_) {

View file

@ -66,16 +66,14 @@ impl methods for Color {
mod parsing { mod parsing {
export parse_color; export parse_color;
// TODO, fail by ignoring the rule instead of setting the fn fail_unrecognized(col : ~str) -> option<Color> {
// color to black
fn fail_unrecognized(col : ~str) -> Color {
#warn["Unrecognized color %s", col]; #warn["Unrecognized color %s", col];
ret black(); ret none;
} }
#[doc="Match an exact color keyword."] #[doc="Match an exact color keyword."]
fn parse_by_name(color : ~str) -> Color { fn parse_by_name(color : ~str) -> option<Color> {
alt color.to_lower() { let col = alt color.to_lower() {
~"black" { black() } ~"black" { black() }
~"silver" { silver() } ~"silver" { silver() }
~"gray" { gray() } ~"gray" { gray() }
@ -93,12 +91,14 @@ mod parsing {
~"blue" { blue() } ~"blue" { blue() }
~"teal" { teal() } ~"teal" { teal() }
~"aqua" { aqua() } ~"aqua" { aqua() }
_ { fail_unrecognized(color) } _ { ret fail_unrecognized(color) }
} };
ret some(col);
} }
#[doc="Parses a color specification in the form rgb(foo,bar,baz)"] #[doc="Parses a color specification in the form rgb(foo,bar,baz)"]
fn parse_rgb(color : ~str) -> Color { fn parse_rgb(color : ~str) -> option<Color> {
// Shave off the rgb( and the ) // Shave off the rgb( and the )
let only_colors = color.substr(4u, color.len() - 5u); let only_colors = color.substr(4u, color.len() - 5u);
@ -108,13 +108,13 @@ mod parsing {
alt (u8::from_str(cols[0]), u8::from_str(cols[1]), alt (u8::from_str(cols[0]), u8::from_str(cols[1]),
u8::from_str(cols[2])) { u8::from_str(cols[2])) {
(some(r), some(g), some(b)) { rgb(r, g, b) } (some(r), some(g), some(b)) { some(rgb(r, g, b)) }
_ { fail_unrecognized(color) } _ { fail_unrecognized(color) }
} }
} }
#[doc="Parses a color specification in the form rgba(foo,bar,baz,qux)"] #[doc="Parses a color specification in the form rgba(foo,bar,baz,qux)"]
fn parse_rgba(color : ~str) -> Color { fn parse_rgba(color : ~str) -> option<Color> {
// Shave off the rgba( and the ) // Shave off the rgba( and the )
let only_vals = color.substr(5u, color.len() - 6u); let only_vals = color.substr(5u, color.len() - 6u);
@ -124,13 +124,13 @@ mod parsing {
alt (u8::from_str(cols[0]), u8::from_str(cols[1]), alt (u8::from_str(cols[0]), u8::from_str(cols[1]),
u8::from_str(cols[2]), float::from_str(cols[3])) { u8::from_str(cols[2]), float::from_str(cols[3])) {
(some(r), some(g), some(b), some(a)) { rgba(r, g, b, a) } (some(r), some(g), some(b), some(a)) { some(rgba(r, g, b, a)) }
_ { fail_unrecognized(color) } _ { fail_unrecognized(color) }
} }
} }
#[doc="Parses a color specification in the form hsl(foo,bar,baz)"] #[doc="Parses a color specification in the form hsl(foo,bar,baz)"]
fn parse_hsl(color : ~str) -> Color { fn parse_hsl(color : ~str) -> option<Color> {
// Shave off the hsl( and the ) // Shave off the hsl( and the )
let only_vals = color.substr(4u, color.len() - 5u); let only_vals = color.substr(4u, color.len() - 5u);
@ -140,13 +140,13 @@ mod parsing {
alt (float::from_str(vals[0]), float::from_str(vals[1]), alt (float::from_str(vals[0]), float::from_str(vals[1]),
float::from_str(vals[2])) { float::from_str(vals[2])) {
(some(h), some(s), some(l)) { hsl(h, s, l) } (some(h), some(s), some(l)) { some(hsl(h, s, l)) }
_ { fail_unrecognized(color) } _ { fail_unrecognized(color) }
} }
} }
#[doc="Parses a color specification in the form hsla(foo,bar,baz,qux)"] #[doc="Parses a color specification in the form hsla(foo,bar,baz,qux)"]
fn parse_hsla(color : ~str) -> Color { fn parse_hsla(color : ~str) -> option<Color> {
// Shave off the hsla( and the ) // Shave off the hsla( and the )
let only_vals = color.substr(5u, color.len() - 6u); let only_vals = color.substr(5u, color.len() - 6u);
@ -155,7 +155,7 @@ mod parsing {
alt (float::from_str(vals[0]), float::from_str(vals[1]), alt (float::from_str(vals[0]), float::from_str(vals[1]),
float::from_str(vals[2]), float::from_str(vals[3])) { float::from_str(vals[2]), float::from_str(vals[3])) {
(some(h), some(s), some(l), some(a)) { hsla(h, s, l, a) } (some(h), some(s), some(l), some(a)) { some(hsla(h, s, l, a)) }
_ { fail_unrecognized(color) } _ { fail_unrecognized(color) }
} }
} }
@ -163,7 +163,7 @@ mod parsing {
// Currently colors are supported in rgb(a,b,c) form and also by // Currently colors are supported in rgb(a,b,c) form and also by
// keywords for several common colors. // keywords for several common colors.
// TODO: extend this // TODO: extend this
fn parse_color(color : ~str) -> Color { fn parse_color(color : ~str) -> option<Color> {
alt color { alt color {
c if c.starts_with(~"rgb(") { parse_rgb(c) } c if c.starts_with(~"rgb(") { parse_rgb(c) }
c if c.starts_with(~"rgba(") { parse_rgba(c) } c if c.starts_with(~"rgba(") { parse_rgba(c) }
@ -177,58 +177,62 @@ mod parsing {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
import css_colors::*; import css_colors::*;
import option::unwrap;
import parsing::parse_color; import parsing::parse_color;
#[test] #[test]
fn test_parse_by_name() { fn test_parse_by_name() {
assert red().eq(parse_color(~"red")); assert red().eq(unwrap(parse_color(~"red")));
assert lime().eq(parse_color(~"Lime")); assert lime().eq(unwrap(parse_color(~"Lime")));
assert blue().eq(parse_color(~"BLUE")); assert blue().eq(unwrap(parse_color(~"BLUE")));
assert green().eq(parse_color(~"GreEN")); assert green().eq(unwrap(parse_color(~"GreEN")));
assert white().eq(parse_color(~"white")); assert white().eq(unwrap(parse_color(~"white")));
assert black().eq(parse_color(~"Black")); assert black().eq(unwrap(parse_color(~"Black")));
assert gray().eq(parse_color(~"Gray")); assert gray().eq(unwrap(parse_color(~"Gray")));
assert silver().eq(parse_color(~"SiLvEr")); assert silver().eq(unwrap(parse_color(~"SiLvEr")));
assert maroon().eq(parse_color(~"maroon")); assert maroon().eq(unwrap(parse_color(~"maroon")));
assert purple().eq(parse_color(~"PURPLE")); assert purple().eq(unwrap(parse_color(~"PURPLE")));
assert fuchsia().eq(parse_color(~"FUCHSIA")); assert fuchsia().eq(unwrap(parse_color(~"FUCHSIA")));
assert olive().eq(parse_color(~"oLiVe")); assert olive().eq(unwrap(parse_color(~"oLiVe")));
assert yellow().eq(parse_color(~"yellow")); assert yellow().eq(unwrap(parse_color(~"yellow")));
assert navy().eq(parse_color(~"NAVY")); assert navy().eq(unwrap(parse_color(~"NAVY")));
assert teal().eq(parse_color(~"Teal")); assert teal().eq(unwrap(parse_color(~"Teal")));
assert aqua().eq(parse_color(~"Aqua")); assert aqua().eq(unwrap(parse_color(~"Aqua")));
assert none == parse_color(~"foobarbaz");
} }
#[test] #[test]
fn test_parsing_rgb() { fn test_parsing_rgb() {
assert red().eq(parse_color(~"rgb(255,0,0)")); assert red().eq(unwrap(parse_color(~"rgb(255,0,0)")));
assert red().eq(parse_color(~"rgba(255,0,0,1.0)")); assert red().eq(unwrap(parse_color(~"rgba(255,0,0,1.0)")));
assert red().eq(parse_color(~"rgba(255,0,0,1)")); assert red().eq(unwrap(parse_color(~"rgba(255,0,0,1)")));
assert lime().eq(parse_color(~"rgba(0,255,0,1.00)")); assert lime().eq(unwrap(parse_color(~"rgba(0,255,0,1.00)")));
assert rgb(1u8,2u8,3u8).eq(parse_color(~"rgb(1,2,03)")); assert rgb(1u8,2u8,3u8).eq(unwrap(parse_color(~"rgb(1,2,03)")));
assert rgba(15u8,250u8,3u8,0.5).eq(parse_color(~"rgba(15,250,3,.5)")); assert rgba(15u8,250u8,3u8,0.5).eq(unwrap(parse_color(~"rgba(15,250,3,.5)")));
assert rgba(15u8,250u8,3u8,0.5).eq(parse_color(~"rgba(15,250,3,0.5)")); assert rgba(15u8,250u8,3u8,0.5).eq(unwrap(parse_color(~"rgba(15,250,3,0.5)")));
assert none == parse_color(~"rbga(1,2,3)");
} }
#[test] #[test]
fn test_parsing_hsl() { fn test_parsing_hsl() {
assert red().eq(parse_color(~"hsl(0,1,.5)")); assert red().eq(unwrap(parse_color(~"hsl(0,1,.5)")));
assert lime().eq(parse_color(~"hsl(120.0,1.0,.5)")); assert lime().eq(unwrap(parse_color(~"hsl(120.0,1.0,.5)")));
assert blue().eq(parse_color(~"hsl(240.0,1.0,.5)")); assert blue().eq(unwrap(parse_color(~"hsl(240.0,1.0,.5)")));
assert green().eq(parse_color(~"hsl(120.0,1.0,.25)")); assert green().eq(unwrap(parse_color(~"hsl(120.0,1.0,.25)")));
assert white().eq(parse_color(~"hsl(1.0,1.,1.0)")); assert white().eq(unwrap(parse_color(~"hsl(1.0,1.,1.0)")));
assert white().eq(parse_color(~"hsl(129.0,0.3,1.0)")); assert white().eq(unwrap(parse_color(~"hsl(129.0,0.3,1.0)")));
assert black().eq(parse_color(~"hsl(231.2,0.75,0.0)")); assert black().eq(unwrap(parse_color(~"hsl(231.2,0.75,0.0)")));
assert black().eq(parse_color(~"hsl(11.2,0.0,0.0)")); assert black().eq(unwrap(parse_color(~"hsl(11.2,0.0,0.0)")));
assert gray().eq(parse_color(~"hsl(0.0,0.0,0.5)")); assert gray().eq(unwrap(parse_color(~"hsl(0.0,0.0,0.5)")));
assert maroon().eq(parse_color(~"hsl(0.0,1.0,0.25)")); assert maroon().eq(unwrap(parse_color(~"hsl(0.0,1.0,0.25)")));
assert purple().eq(parse_color(~"hsl(300.0,1.0,0.25)")); assert purple().eq(unwrap(parse_color(~"hsl(300.0,1.0,0.25)")));
assert fuchsia().eq(parse_color(~"hsl(300,1.0,0.5)")); assert fuchsia().eq(unwrap(parse_color(~"hsl(300,1.0,0.5)")));
assert olive().eq(parse_color(~"hsl(60.,1.0,0.25)")); assert olive().eq(unwrap(parse_color(~"hsl(60.,1.0,0.25)")));
assert yellow().eq(parse_color(~"hsl(60.,1.0,0.5)")); assert yellow().eq(unwrap(parse_color(~"hsl(60.,1.0,0.5)")));
assert navy().eq(parse_color(~"hsl(240.0,1.0,.25)")); assert navy().eq(unwrap(parse_color(~"hsl(240.0,1.0,.25)")));
assert teal().eq(parse_color(~"hsl(180.0,1.0,.25)")); assert teal().eq(unwrap(parse_color(~"hsl(180.0,1.0,.25)")));
assert aqua().eq(parse_color(~"hsl(180.0,1.0,.5)")); assert aqua().eq(unwrap(parse_color(~"hsl(180.0,1.0,.5)")));
assert none == parse_color(~"hsl(1,2,3,.4)");
} }
} }