aboutsummaryrefslogtreecommitdiffstats
path: root/src/servo/parser/css_builder.rs
diff options
context:
space:
mode:
authorMargaret Meyerhofer <mmeyerhofer@mozilla.com>2012-06-28 16:01:36 -0700
committerMargaret Meyerhofer <mmeyerhofer@mozilla.com>2012-07-19 10:56:59 -0700
commited99449f52f5d927893408448a56f9c247f8e098 (patch)
tree1247bb5b4b0af32ca630f2ff7fa473308dfc48d2 /src/servo/parser/css_builder.rs
parent0c5aefa88fdf712a309be4301ede87adff4693e7 (diff)
downloadservo-ed99449f52f5d927893408448a56f9c247f8e098.tar.gz
servo-ed99449f52f5d927893408448a56f9c247f8e098.zip
Added width and height parsing
Diffstat (limited to 'src/servo/parser/css_builder.rs')
-rw-r--r--src/servo/parser/css_builder.rs278
1 files changed, 144 insertions, 134 deletions
diff --git a/src/servo/parser/css_builder.rs b/src/servo/parser/css_builder.rs
index 370380c3c8c..81cab772dc7 100644
--- a/src/servo/parser/css_builder.rs
+++ b/src/servo/parser/css_builder.rs
@@ -1,27 +1,30 @@
-#[doc="Constructs a list of style rules from a token stream"]
+#[doc="Constructs a list of css style rules from a token stream"]
// TODO: fail according to the css spec instead of failing when things
// are not as expected
import dom::style;
-import style::{DisInline, DisBlock, DisNone, Display, TextColor, BackgroundColor, FontSize};
+import style::{DisInline, DisBlock, DisNone, Display, TextColor, BackgroundColor, FontSize,
+ Height, Width, StyleDeclaration, Selector};
import parser::css_lexer::{Token, StartDescription, EndDescription,
Descendant, Child, Sibling,
Comma, Element, Attr, Description,
Eof};
import comm::recv;
-import option::is_none;
+import option::{map, is_none};
+import vec::push;
+import parser::parser_util::{parse_display_type, parse_font_size, parse_size};
import util::color::parsing::parse_color;
import vec::push;
type TokenReader = {stream : port<Token>, mut lookahead : option<Token>};
-trait methods {
+trait util_methods {
fn get() -> Token;
fn unget(-tok : Token);
}
-impl methods of methods for TokenReader {
+impl util_methods of util_methods for TokenReader {
fn get() -> Token {
alt copy self.lookahead {
some(tok) { self.lookahead = none; copy tok }
@@ -35,153 +38,160 @@ impl methods of methods for TokenReader {
}
}
-fn parse_element(reader : TokenReader) -> option<~style::Selector> {
- // Get the current element type
- let elmt_name = alt reader.get() {
- Element(tag) { copy tag }
- Eof { ret none; }
- _ { fail ~"Expected an element" }
- };
-
- let mut attr_list = ~[];
+trait parser_methods {
+ fn parse_element() -> option<~style::Selector>;
+ fn parse_selector() -> option<~[~Selector]>;
+ fn parse_description() -> option<~[StyleDeclaration]>;
+ fn parse_rule() -> option<~style::Rule>;
+}
- // Get the attributes associated with that element
- loop {
- let tok = reader.get();
- alt tok {
- Attr(attr) { push(attr_list, copy attr); }
- StartDescription | Descendant | Child | Sibling | Comma {
- reader.unget(tok);
- break;
- }
- Eof { ret none; }
- Element(_) { fail ~"Unexpected second element without "
- + ~"relation to first element"; }
- EndDescription { fail ~"Unexpected '}'"; }
- Description(_, _) { fail ~"Unexpected description"; }
- }
+impl parser_methods of parser_methods for TokenReader {
+ fn parse_element() -> option<~style::Selector> {
+ // Get the current element type
+ let elmt_name = alt self.get() {
+ Element(tag) { copy tag }
+ Eof { ret none; }
+ _ { fail ~"Expected an element" }
+ };
+
+ let mut attr_list = ~[];
+
+ // Get the attributes associated with that element
+ loop {
+ let tok = self.get();
+ alt tok {
+ Attr(attr) { push(attr_list, copy attr); }
+ StartDescription | Descendant | Child | Sibling | Comma {
+ self.unget(tok);
+ break;
+ }
+ Eof { ret none; }
+ Element(_) { fail ~"Unexpected second element without relation to first element"; }
+ EndDescription { fail ~"Unexpected '}'"; }
+ Description(_, _) { fail ~"Unexpected description"; }
+ }
+ }
+ ret some(~style::Element(elmt_name, attr_list));
}
-
- ret some(~style::Element(elmt_name, attr_list));
-}
-fn parse_rule(reader : TokenReader) -> option<~style::Rule> {
- let mut sel_list = ~[];
- let mut desc_list = ~[];
+ fn parse_selector() -> option<~[~Selector]> {
+ let mut sel_list = ~[];
- // Collect all the selectors that this rule applies to
- loop {
- let mut cur_sel;
+ // Collect all the selectors that this rule applies to
+ loop {
+ let mut cur_sel;
- alt parse_element(reader) {
- some(elmt) { cur_sel = copy elmt; }
- none { ret none; } // we hit an eof in the middle of a rule
- }
+ alt self.parse_element() {
+ some(elmt) { cur_sel = copy elmt; }
+ none { ret none; } // we hit an eof in the middle of a rule
+ }
- loop {
- let tok = reader.get();
- alt tok {
- Descendant {
- alt parse_element(reader) {
- some(elmt) {
- let built_sel <- cur_sel;
- let new_sel = copy elmt;
- cur_sel <- ~style::Descendant(built_sel, new_sel)
+ loop {
+ let tok = self.get();
+ let built_sel <- cur_sel;
+
+ alt tok {
+ Descendant {
+ alt self.parse_element() {
+ some(elmt) {
+ let new_sel = copy elmt;
+ cur_sel <- ~style::Descendant(built_sel, new_sel)
+ }
+ none { ret none; }
+ }
}
- none { ret none; }
- }
- }
- Child {
- alt parse_element(reader) {
- some(elmt) {
- let built_sel <- cur_sel;
- let new_sel = copy elmt;
- cur_sel <- ~style::Child(built_sel, new_sel)
+ Child {
+ alt self.parse_element() {
+ some(elmt) {
+ let new_sel = copy elmt;
+ cur_sel <- ~style::Child(built_sel, new_sel)
+ }
+ none { ret none; }
+ }
}
- none { ret none; }
- }
- }
- Sibling {
- alt parse_element(reader) {
- some(elmt) {
- let built_sel <- cur_sel;
- let new_sel = copy elmt;
- cur_sel <- ~style::Sibling(built_sel, new_sel)
+ Sibling {
+ alt self.parse_element() {
+ some(elmt) {
+ let new_sel = copy elmt;
+ cur_sel <- ~style::Sibling(built_sel, new_sel)
+ }
+ none { ret none; }
+ }
+ }
+ StartDescription {
+ push(sel_list, built_sel);
+ self.unget(StartDescription);
+ break;
+ }
+ Comma {
+ push(sel_list, built_sel);
+ self.unget(Comma);
+ break;
+ }
+ Attr(_) | EndDescription | Element(_) | Description(_, _) {
+ fail #fmt["Unexpected token %? in elements", tok];
}
- none { ret none; }
+ Eof { ret none; }
}
- }
- StartDescription {
- let built_sel <- cur_sel;
- push(sel_list, built_sel);
- reader.unget(StartDescription);
- break;
- }
- Comma {
- let built_sel <- cur_sel;
- push(sel_list, built_sel);
- reader.unget(Comma);
- break;
- }
- Attr(_) | EndDescription | Element(_) | Description(_, _) {
- fail #fmt["Unexpected token %? in elements", tok];
- }
- Eof { ret none; }
}
- }
- // check if we should break out of the nesting loop as well
- let tok = reader.get();
- alt tok {
- StartDescription { break; }
- Comma { }
- _ { reader.unget(tok); }
+ // check if we should break out of the nesting loop as well
+ // TODO: fix this when rust gets labelled loops
+ let tok = self.get();
+ alt tok {
+ StartDescription { break; }
+ Comma { }
+ _ { self.unget(tok); }
+ }
}
+
+ ret some(sel_list);
}
-
- // Get the description to be applied to the selector
- loop {
- let tok = reader.get();
- alt tok {
- EndDescription { break; }
- Description(prop, val) {
- alt prop {
- ~"font-size" {
- // TODO, support more ways to declare a font size than # pt
- assert val.ends_with(~"pt");
- let num = val.substr(0u, val.len() - 2u);
-
- alt uint::from_str(num) {
- some(n) { push(desc_list, FontSize(n)); }
- none { fail ~"Nonnumber provided as font size"; }
- }
- }
- ~"display" {
- alt val {
- ~"inline" { push(desc_list, Display(DisInline)); }
- ~"block" { push(desc_list, Display(DisBlock)); }
- ~"none" { push(desc_list, Display(DisNone)); }
- _ { #debug["Recieved unknown display value '%s'", val]; }
+
+ fn parse_description() -> option<~[StyleDeclaration]> {
+ let mut desc_list : ~[StyleDeclaration]= ~[];
+
+ // Get the description to be applied to the selector
+ loop {
+ let tok = self.get();
+ alt tok {
+ EndDescription { break; }
+ Description(prop, val) {
+ alt prop {
+ // TODO: have color parsing return an option instead of a real value
+ ~"background-color" { push(desc_list, BackgroundColor(parse_color(val))); }
+ ~"color" { push(desc_list, TextColor(parse_color(val))); }
+ ~"display" { parse_display_type(val).map(|res| push(desc_list, Display(res))); }
+ ~"font-size" { parse_font_size(val).map(|res| push(desc_list, FontSize(res))); }
+ ~"height" { parse_size(val).map(|res| push(desc_list, Height(res))); }
+ ~"width" { parse_size(val).map(|res| push(desc_list, Width(res))); }
+ _ { #debug["Recieved unknown style property '%s'", val]; }
}
}
- ~"color" {
- push(desc_list, TextColor(parse_color(val)));
+ Eof { ret none; }
+ StartDescription | Descendant | Child | Sibling | Comma | Element(_) | Attr(_) {
+ fail #fmt["Unexpected token %? in description", tok];
}
- ~"background-color" {
- push(desc_list, BackgroundColor(parse_color(val)));
- }
- _ { #debug["Recieved unknown style property '%s'", val]; }
}
- }
- Eof { ret none; }
- StartDescription | Descendant | Child | Sibling
- | Comma | Element(_) | Attr(_) {
- fail #fmt["Unexpected token %? in description", tok];
- }
}
+
+ ret some(desc_list);
}
- ret some(~(sel_list, desc_list));
+ fn parse_rule() -> option<~style::Rule> {
+ let sel_list = alt self.parse_selector() {
+ some(list){ copy list }
+ none { ret none; }
+ };
+
+ // Get the description to be applied to the selector
+ let desc_list = alt self.parse_description() {
+ some(list) { copy list }
+ none { ret none; }
+ };
+
+ ret some(~(sel_list, desc_list));
+ }
}
fn build_stylesheet(stream : port<Token>) -> ~[~style::Rule] {
@@ -189,9 +199,9 @@ fn build_stylesheet(stream : port<Token>) -> ~[~style::Rule] {
let reader = {stream : stream, mut lookahead : none};
loop {
- alt parse_rule(reader) {
- some(rule) { push(rule_list, copy rule); }
- none { break; }
+ alt reader.parse_rule() {
+ some(rule) { push(rule_list, copy rule); }
+ none { break; }
}
}