mirror of
https://github.com/servo/servo.git
synced 2025-08-07 14:35:33 +01:00
Implemented a parser for a subset of css and added a hack for guessing when .css files exist.
This commit is contained in:
parent
7f8573243b
commit
6f90054a1e
8 changed files with 367 additions and 33 deletions
|
@ -3,6 +3,7 @@ export content;
|
||||||
|
|
||||||
import result::extensions;
|
import result::extensions;
|
||||||
import dom::rcu::writer_methods;
|
import dom::rcu::writer_methods;
|
||||||
|
import dom::style;
|
||||||
import dom=dom::base;
|
import dom=dom::base;
|
||||||
import layout::layout;
|
import layout::layout;
|
||||||
import js::rust::methods;
|
import js::rust::methods;
|
||||||
|
@ -38,11 +39,36 @@ fn content(to_layout: chan<layout::msg>) -> chan<msg> {
|
||||||
parse(filename) {
|
parse(filename) {
|
||||||
#debug["content: Received filename `%s` to parse", filename];
|
#debug["content: Received filename `%s` to parse", filename];
|
||||||
|
|
||||||
|
// TODO actually parse where the css sheet should be
|
||||||
|
// Replace .html with .css and try to open a stylesheet
|
||||||
|
assert filename.ends_with(".html");
|
||||||
|
let new_file = filename.substr(0u, filename.len() - 5u)
|
||||||
|
+ ".css";
|
||||||
|
|
||||||
|
// Send off a task to parse the stylesheet
|
||||||
|
let css_port = comm::port();
|
||||||
|
let css_chan = comm::chan(css_port);
|
||||||
|
task::spawn {||
|
||||||
|
let css_stream = parser::lexer::
|
||||||
|
spawn_css_parser_task(new_file);
|
||||||
|
let css_rules = parser::css_builder::
|
||||||
|
build_stylesheet(css_stream);
|
||||||
|
css_chan.send(css_rules);
|
||||||
|
};
|
||||||
|
|
||||||
// Note: we can parse the next document in parallel
|
// Note: we can parse the next document in parallel
|
||||||
// with any previous documents.
|
// with any previous documents.
|
||||||
let stream = lexer::spawn_html_parser_task(filename);
|
let stream = parser::lexer::spawn_html_parser_task(filename);
|
||||||
let root = parser::html_builder::build_dom(scope, stream);
|
let root = parser::html_builder::build_dom(scope, stream);
|
||||||
|
|
||||||
|
// Collect the css stylesheet
|
||||||
|
let css_rules = comm::recv(css_port);
|
||||||
|
|
||||||
|
// Apply the css rules to the dom tree:
|
||||||
|
// TODO
|
||||||
|
#debug["%s",style::print_sheet(css_rules)];
|
||||||
|
|
||||||
|
|
||||||
// Now, join the layout so that they will see the latest
|
// Now, join the layout so that they will see the latest
|
||||||
// changes we have made.
|
// changes we have made.
|
||||||
join_layout(scope, to_layout);
|
join_layout(scope, to_layout);
|
||||||
|
|
|
@ -7,7 +7,7 @@ enum display_type{
|
||||||
}
|
}
|
||||||
|
|
||||||
enum style_decl{
|
enum style_decl{
|
||||||
font_size(uint),
|
font_size(uint), // Currently assumes format '# pt'
|
||||||
display(display_type),
|
display(display_type),
|
||||||
text_color(uint),
|
text_color(uint),
|
||||||
background_color(uint)
|
background_color(uint)
|
||||||
|
@ -27,10 +27,9 @@ enum selector{
|
||||||
sibling(~selector, ~selector)
|
sibling(~selector, ~selector)
|
||||||
}
|
}
|
||||||
|
|
||||||
type rule = (selector, [style_decl]);
|
type rule = ([~selector], [style_decl]);
|
||||||
|
|
||||||
type stylesheet = [rule];
|
|
||||||
|
|
||||||
|
type stylesheet = [~rule];
|
||||||
|
|
||||||
fn print_list<T>(list : [T], print : fn(T) -> str) -> str {
|
fn print_list<T>(list : [T], print : fn(T) -> str) -> str {
|
||||||
let l = vec::len(list);
|
let l = vec::len(list);
|
||||||
|
@ -48,6 +47,23 @@ fn print_list<T>(list : [T], print : fn(T) -> str) -> str {
|
||||||
ret res;
|
ret res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn print_list_vert<T>(list : [T], print : fn(T) -> str) -> str {
|
||||||
|
let l = vec::len(list);
|
||||||
|
if l == 0u { ret "" }
|
||||||
|
|
||||||
|
let mut res = "-";
|
||||||
|
res += print(list[0]);
|
||||||
|
let mut i = 1u;
|
||||||
|
|
||||||
|
while i < l {
|
||||||
|
res += "\n-";
|
||||||
|
res += print(list[i]);
|
||||||
|
i += 1u;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret res;
|
||||||
|
}
|
||||||
|
|
||||||
fn print_display(dis_ty : display_type) -> str {
|
fn print_display(dis_ty : display_type) -> str {
|
||||||
alt dis_ty {
|
alt dis_ty {
|
||||||
block { "block" }
|
block { "block" }
|
||||||
|
@ -57,7 +73,7 @@ fn print_display(dis_ty : display_type) -> str {
|
||||||
|
|
||||||
fn print_style(decl : style_decl) -> str{
|
fn print_style(decl : style_decl) -> str{
|
||||||
alt decl {
|
alt decl {
|
||||||
font_size(s) { #fmt("Font size = %u px", s) }
|
font_size(s) { #fmt("Font size = %u pt", s) }
|
||||||
display(dis_ty) { #fmt("Display style = %s", print_display(dis_ty)) }
|
display(dis_ty) { #fmt("Display style = %s", print_display(dis_ty)) }
|
||||||
text_color(c) { #fmt("Text color = 0x%06x", c) }
|
text_color(c) { #fmt("Text color = 0x%06x", c) }
|
||||||
background_color(c) { #fmt("Background color = 0x%06x", c) }
|
background_color(c) { #fmt("Background color = 0x%06x", c) }
|
||||||
|
@ -73,7 +89,7 @@ fn print_attr(attribute : attr) -> str {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_selector(select : ~selector) -> str {
|
fn print_selector(&&select : ~selector) -> str {
|
||||||
alt *select {
|
alt *select {
|
||||||
element(s, attrs) { #fmt("Element %s with attributes: %s", s,
|
element(s, attrs) { #fmt("Element %s with attributes: %s", s,
|
||||||
print_list(attrs, print_attr)) }
|
print_list(attrs, print_attr)) }
|
||||||
|
@ -86,39 +102,39 @@ fn print_selector(select : ~selector) -> str {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_rule(rule : rule) -> str {
|
fn print_rule(&&rule : ~rule) -> str {
|
||||||
alt rule {
|
alt *rule {
|
||||||
(sel, styles) {
|
(sels, styles) {
|
||||||
let sel_str = print_selector(~(copy sel));
|
let sel_str = print_list(sels, print_selector);
|
||||||
let sty_str = print_list(styles, print_style);
|
let sty_str = print_list(styles, print_style);
|
||||||
|
|
||||||
#fmt("Selector: %s, Style: {%s}", sel_str, sty_str)
|
#fmt("Selectors: %s; Style: {%s}", sel_str, sty_str)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_sheet(sheet : stylesheet) -> str {
|
fn print_sheet(sheet : stylesheet) -> str {
|
||||||
#fmt("CSS Rules: %s", print_list(sheet, print_rule))
|
#fmt("CSS Rules:\n%s", print_list_vert(sheet, print_rule))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_pretty_print() {
|
fn test_pretty_print() {
|
||||||
let test1 = [(element("p", []), [font_size(32u)])];
|
let test1 = [~([~element("p", [])], [font_size(32u)])];
|
||||||
let actual1 = print_sheet(test1);
|
let actual1 = print_sheet(test1);
|
||||||
let expected1 = "CSS Rules: Selector: Element p with attributes: ," +
|
let expected1 = "CSS Rules:\n-Selectors: Element p with attributes: ;" +
|
||||||
" Style: {Font size = 32 px}";
|
" Style: {Font size = 32 pt}";
|
||||||
|
|
||||||
assert(actual1 == expected1);
|
assert(actual1 == expected1);
|
||||||
|
|
||||||
let elmt1 = ~element("*", []);
|
let elmt1 = ~element("*", []);
|
||||||
let elmt2 = ~element("body", [exact("class", "2")]);
|
let elmt2 = ~element("body", [exact("class", "2")]);
|
||||||
|
|
||||||
let test2 = [(descendant(elmt1, elmt2),
|
let test2 = [~([~descendant(elmt1, elmt2)],
|
||||||
[display(block), text_color(0u)])];
|
[display(block), text_color(0u)])];
|
||||||
|
|
||||||
let actual2 = print_sheet(test2);
|
let actual2 = print_sheet(test2);
|
||||||
let expected2 = "CSS Rules: Selector: (Element * with attributes: ) " +
|
let expected2 = "CSS Rules:\n-Selectors: (Element * with attributes: ) "
|
||||||
"(Element body with attributes: [class = 2]), " +
|
+ "(Element body with attributes: [class = 2]); " +
|
||||||
"Style: {Display style = block, Text color = 0x000000}";
|
"Style: {Display style = block, Text color = 0x000000}";
|
||||||
|
|
||||||
assert(actual2 == expected2);
|
assert(actual2 == expected2);
|
||||||
|
|
|
@ -165,7 +165,7 @@ mod test {
|
||||||
for tree::each_child(btree, root) {|c|
|
for tree::each_child(btree, root) {|c|
|
||||||
r += flat_bounds(c);
|
r += flat_bounds(c);
|
||||||
}
|
}
|
||||||
ret r + [root.bounds];
|
ret r + [copy root.bounds];
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
262
src/servo/parser/css_builder.rs
Normal file
262
src/servo/parser/css_builder.rs
Normal file
|
@ -0,0 +1,262 @@
|
||||||
|
#[doc="Constructs a list of 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 parser::lexer::css::{token, to_start_desc, to_end_desc,
|
||||||
|
to_descendant, to_child, to_sibling,
|
||||||
|
to_comma, to_elmt, to_attr, to_desc,
|
||||||
|
to_eof};
|
||||||
|
import comm::recv;
|
||||||
|
|
||||||
|
type token_reader = {stream : port<token>, mut lookahead : option<token>};
|
||||||
|
|
||||||
|
impl methods for token_reader {
|
||||||
|
fn get() -> token {
|
||||||
|
alt self.lookahead {
|
||||||
|
some(tok) { self.lookahead = none; tok }
|
||||||
|
none { recv(self.stream) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unget(tok : token) {
|
||||||
|
self.lookahead = some(tok);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_element(reader : token_reader) -> option<~selector> {
|
||||||
|
// Get the current element type
|
||||||
|
let elmt_name = alt reader.get() {
|
||||||
|
to_elmt(tag) { tag }
|
||||||
|
to_eof { ret none; }
|
||||||
|
_ { fail "Expected an element" }
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut attr_list = [];
|
||||||
|
|
||||||
|
// Get the attributes associated with that element
|
||||||
|
loop {
|
||||||
|
let tok = reader.get();
|
||||||
|
alt tok {
|
||||||
|
to_attr(attr) { attr_list += [attr]; }
|
||||||
|
to_start_desc | to_descendant | to_child | to_sibling
|
||||||
|
| to_comma {
|
||||||
|
reader.unget(tok);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
to_eof { ret none; }
|
||||||
|
to_elmt(_) { fail "Unexpected second element without " +
|
||||||
|
"relation to first element"; }
|
||||||
|
to_end_desc { fail "Unexpected '}'"; }
|
||||||
|
to_desc(_, _) { fail "Unexpected description"; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret some(~element(elmt_name, attr_list));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Currently colors are supported in rgb(a,b,c) form and also by
|
||||||
|
// keywords for several common colors.
|
||||||
|
// TODO: extend this
|
||||||
|
fn parse_color(color : str) -> uint {
|
||||||
|
let blue_unit = 1u;
|
||||||
|
let green_unit = 256u;
|
||||||
|
let red_unit = 256u * 256u;
|
||||||
|
|
||||||
|
let result_color = if color.starts_with("rgb(") {
|
||||||
|
let color_vec = str::bytes(color);
|
||||||
|
let mut i = 4u;
|
||||||
|
let mut red_vec = [];
|
||||||
|
let mut green_vec = [];
|
||||||
|
let mut blue_vec = [];
|
||||||
|
|
||||||
|
while i < color_vec.len() && color_vec[i] != ',' as u8 {
|
||||||
|
red_vec += [color_vec[i]];
|
||||||
|
i += 1u;
|
||||||
|
}
|
||||||
|
|
||||||
|
i += 1u;
|
||||||
|
|
||||||
|
while i < color_vec.len() && color_vec[i] != ',' as u8 {
|
||||||
|
green_vec += [color_vec[i]];
|
||||||
|
i += 1u;
|
||||||
|
}
|
||||||
|
|
||||||
|
i += 1u;
|
||||||
|
|
||||||
|
while i < color_vec.len() && color_vec[i] != ',' as u8 {
|
||||||
|
blue_vec += [color_vec[i]];
|
||||||
|
i += 1u;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO, fail by ignoring the rule instead of setting the
|
||||||
|
// color to black
|
||||||
|
|
||||||
|
let blue_intense = alt uint::from_str(str::from_bytes(blue_vec)) {
|
||||||
|
some(c) { c }
|
||||||
|
none { 0u }
|
||||||
|
};
|
||||||
|
|
||||||
|
let green_intense = alt uint::from_str(str::from_bytes(green_vec)) {
|
||||||
|
some(c) { c }
|
||||||
|
none { 0u }
|
||||||
|
};
|
||||||
|
|
||||||
|
let red_intense = alt uint::from_str(str::from_bytes(red_vec)) {
|
||||||
|
some(c) { c }
|
||||||
|
none { 0u }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
blue_unit * blue_intense + green_intense * green_unit
|
||||||
|
+ red_intense * red_unit
|
||||||
|
} else {
|
||||||
|
alt color {
|
||||||
|
"red" { red_unit * 255u }
|
||||||
|
"blue" { blue_unit * 255u }
|
||||||
|
"green" { green_unit * 255u}
|
||||||
|
"white" { red_unit * 256u - 1u }
|
||||||
|
"black" { 0u }
|
||||||
|
// TODO, fail by ignoring the rule instead of setting the
|
||||||
|
// color to black
|
||||||
|
_ { #debug["Unrecognized color %s", color]; 0u }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ret result_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_rule(reader : token_reader) -> option<~rule> {
|
||||||
|
let mut sel_list = [];
|
||||||
|
let mut desc_list = [];
|
||||||
|
|
||||||
|
// Collect all the selectors that this rule applies to
|
||||||
|
loop {
|
||||||
|
let mut cur_sel;
|
||||||
|
|
||||||
|
alt parse_element(reader) {
|
||||||
|
some(elmt) { cur_sel <- elmt; }
|
||||||
|
none { ret none; } // we hit an eof in the middle of a rule
|
||||||
|
}
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let tok = reader.get();
|
||||||
|
alt tok {
|
||||||
|
to_descendant {
|
||||||
|
alt parse_element(reader) {
|
||||||
|
some(elmt) {
|
||||||
|
let built_sel <- cur_sel;
|
||||||
|
let new_sel <- elmt;
|
||||||
|
cur_sel <- ~descendant(built_sel, new_sel)
|
||||||
|
}
|
||||||
|
none { ret none; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
to_child {
|
||||||
|
alt parse_element(reader) {
|
||||||
|
some(elmt) {
|
||||||
|
let built_sel <- cur_sel;
|
||||||
|
let new_sel <- elmt;
|
||||||
|
cur_sel <- ~child(built_sel, new_sel)
|
||||||
|
}
|
||||||
|
none { ret none; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
to_sibling {
|
||||||
|
alt parse_element(reader) {
|
||||||
|
some(elmt) {
|
||||||
|
let built_sel <- cur_sel;
|
||||||
|
let new_sel <- elmt;
|
||||||
|
cur_sel <- ~sibling(built_sel, new_sel)
|
||||||
|
}
|
||||||
|
none { ret none; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
to_start_desc {
|
||||||
|
let built_sel <- cur_sel;
|
||||||
|
sel_list += [built_sel];
|
||||||
|
reader.unget(to_start_desc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
to_comma {
|
||||||
|
let built_sel <- cur_sel;
|
||||||
|
sel_list += [built_sel];
|
||||||
|
reader.unget(to_comma);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
to_attr(_) | to_end_desc | to_elmt(_) | to_desc(_, _) {
|
||||||
|
fail #fmt["Unexpected token %? in elements", tok];
|
||||||
|
}
|
||||||
|
to_eof { ret none; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if we should break out of the nesting loop as well
|
||||||
|
let tok = reader.get();
|
||||||
|
alt tok {
|
||||||
|
to_start_desc { break; }
|
||||||
|
to_comma { }
|
||||||
|
_ { reader.unget(tok); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the description to be applied to the selector
|
||||||
|
loop {
|
||||||
|
let tok = reader.get();
|
||||||
|
alt tok {
|
||||||
|
to_end_desc { break; }
|
||||||
|
to_desc(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) { desc_list += [font_size(n)]; }
|
||||||
|
none { fail "Nonnumber provided as font size"; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"display" {
|
||||||
|
alt val {
|
||||||
|
"inline" { desc_list += [display(inline)]; }
|
||||||
|
"block" { desc_list += [display(block)]; }
|
||||||
|
_ { #debug["Recieved unknown display value '%s'",
|
||||||
|
val]; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"color" {
|
||||||
|
desc_list += [text_color(parse_color(val))];
|
||||||
|
}
|
||||||
|
"background-color" {
|
||||||
|
desc_list += [background_color(parse_color(val))];
|
||||||
|
}
|
||||||
|
_ { #debug["Recieved unknown style property '%s'",
|
||||||
|
val]; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
to_eof { ret none; }
|
||||||
|
to_start_desc | to_descendant | to_child | to_sibling
|
||||||
|
| to_comma | to_elmt(_) | to_attr(_) {
|
||||||
|
fail #fmt["Unexpected token %? in description", tok];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret some(~(sel_list, desc_list));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_stylesheet(stream : port<token>) -> [~rule] {
|
||||||
|
let mut rule_list = [];
|
||||||
|
let reader = {stream : stream, mut lookahead : none};
|
||||||
|
|
||||||
|
loop {
|
||||||
|
alt parse_rule(reader) {
|
||||||
|
some(rule) { let r <- rule; rule_list += [r]; }
|
||||||
|
none { break; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret rule_list;
|
||||||
|
}
|
|
@ -307,7 +307,7 @@ mod css {
|
||||||
'>' as u8 { to_child }
|
'>' as u8 { to_child }
|
||||||
'+' as u8 { to_sibling }
|
'+' as u8 { to_sibling }
|
||||||
',' as u8 { to_comma }
|
',' as u8 { to_comma }
|
||||||
_ { to_descendant }
|
_ { self.unget(c); to_descendant }
|
||||||
};
|
};
|
||||||
|
|
||||||
self.eat_whitespace();
|
self.eat_whitespace();
|
||||||
|
@ -316,14 +316,22 @@ mod css {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_css_element(c : u8) -> token {
|
fn parse_css_element(c : u8) -> token {
|
||||||
/* Check for special attributes with an implied element.*/
|
assert self.lookahead.is_none();
|
||||||
|
|
||||||
|
/* Check for special attributes with an implied element,
|
||||||
|
or a wildcard which is not a alphabet character.*/
|
||||||
if c == '.' as u8 || c == '#' as u8 {
|
if c == '.' as u8 || c == '#' as u8 {
|
||||||
self.state = ps_css_attribute;
|
self.state = ps_css_attribute;
|
||||||
self.unget(c);
|
self.unget(c);
|
||||||
ret to_elmt("*");
|
ret to_elmt("*");
|
||||||
|
} else if c == '*' as u8 {
|
||||||
|
self.state = ps_css_attribute;
|
||||||
|
ret to_elmt("*");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.unget(c);
|
||||||
let element = self.parse_ident();
|
let element = self.parse_ident();
|
||||||
|
|
||||||
self.state = ps_css_attribute;
|
self.state = ps_css_attribute;
|
||||||
|
|
||||||
ret to_elmt(element);
|
ret to_elmt(element);
|
||||||
|
@ -389,7 +397,11 @@ mod css {
|
||||||
fn parse_css_description(c: u8) -> token {
|
fn parse_css_description(c: u8) -> token {
|
||||||
let mut ch = c;
|
let mut ch = c;
|
||||||
|
|
||||||
if ch.is_whitespace() {
|
if ch == '}' as u8 {
|
||||||
|
self.state = ps_css_elmt;
|
||||||
|
self.eat_whitespace();
|
||||||
|
ret to_end_desc;
|
||||||
|
} else if ch.is_whitespace() {
|
||||||
self.eat_whitespace();
|
self.eat_whitespace();
|
||||||
|
|
||||||
alt self.get() {
|
alt self.get() {
|
||||||
|
@ -439,7 +451,7 @@ mod css {
|
||||||
if desc_val.len() == 0u {
|
if desc_val.len() == 0u {
|
||||||
fail "Expected descriptor value";
|
fail "Expected descriptor value";
|
||||||
} else {
|
} else {
|
||||||
self.state = ps_css_elmt;
|
self.unget('}' as u8);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if ch == ';' as u8 {
|
} else if ch == ';' as u8 {
|
||||||
|
@ -485,16 +497,29 @@ fn spawn_css_parser_task(filename: str) -> port<css::token> {
|
||||||
let result_port = port();
|
let result_port = port();
|
||||||
let result_chan = chan(result_port);
|
let result_chan = chan(result_port);
|
||||||
task::spawn {||
|
task::spawn {||
|
||||||
let file_data = io::read_whole_file(filename).get();
|
|
||||||
let reader = io::bytes_reader(file_data);
|
|
||||||
|
|
||||||
assert filename.ends_with(".css");
|
assert filename.ends_with(".css");
|
||||||
let parser : parser = parser(reader, ps_css_elmt);
|
|
||||||
|
|
||||||
loop {
|
let file_try = io::read_whole_file(filename);
|
||||||
let token = parser.parse_css();
|
|
||||||
result_chan.send(token);
|
// Check if the given css file existed, if it does, parse it,
|
||||||
if token == css::to_eof { break; }
|
// otherwise just send an eof. This is a hack to allow
|
||||||
|
// guessing that if foo.html exists, foo.css is the
|
||||||
|
// corresponding stylesheet.
|
||||||
|
if file_try.is_success() {
|
||||||
|
#debug["Lexing css sheet %s", filename];
|
||||||
|
let file_data = file_try.get();
|
||||||
|
let reader = io::bytes_reader(file_data);
|
||||||
|
|
||||||
|
let parser : parser = parser(reader, ps_css_elmt);
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let token = parser.parse_css();
|
||||||
|
result_chan.send(token);
|
||||||
|
if token == css::to_eof { break; }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
#debug["Failed to open css sheet %s", filename];
|
||||||
|
result_chan.send(css::to_eof);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
ret result_port;
|
ret result_port;
|
||||||
|
|
|
@ -51,6 +51,7 @@ mod layout {
|
||||||
mod parser {
|
mod parser {
|
||||||
mod lexer;
|
mod lexer;
|
||||||
mod html_builder;
|
mod html_builder;
|
||||||
|
mod css_builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
mod platform {
|
mod platform {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import comm::*;
|
import comm::*;
|
||||||
import parser::lexer;
|
import parser::lexer;
|
||||||
//import parser::lexer::util_methods;
|
|
||||||
import result::extensions;
|
import result::extensions;
|
||||||
import gfx::renderer;
|
import gfx::renderer;
|
||||||
import platform::osmain;
|
import platform::osmain;
|
||||||
|
|
5
src/test/test.css
Normal file
5
src/test/test.css
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
p {font-size : 12pt}
|
||||||
|
p img {color : rgb(0,255,0); display : block }
|
||||||
|
p.blue > p.green + p.red { background-color : blue ;color : green }
|
||||||
|
img[class] .pastoral *[lang|=en] { display:inline}
|
||||||
|
.book > #novel + *[type=novella] p { color : blue; color : white }
|
Loading…
Add table
Add a link
Reference in a new issue