ref: babf901b4a508c3ec5d1f89655f10377bbdf9637
dir: /appl/ebook/cssparser.b/
implement CSSparser;
include "sys.m";
sys: Sys;
include "string.m";
str: String;
include "css.m";
css: CSS;
Stylesheet, Statement, Select, Value: import css;
include "cssparser.m";
init()
{
sys = load Sys Sys->PATH;
str = load String String->PATH;
css = load CSS CSS->PATH;
if (css == nil) {
sys->fprint(sys->fildes(2), "cssparser: cannot load %s: %r\n", CSS->PATH);
raise "fail:bad module";
}
css->init(1);
}
parse(s: string): list of (string, list of Decl)
{
(stylesheet, e) := css->parse(s);
if (stylesheet == nil) {
warning("error parsing stylesheet: " + e);
return nil;
}
rules, r: list of (string, list of Decl);
for (stl := stylesheet.statements; stl != nil; stl = tl stl) {
pick st := hd stl {
Ruleset =>
rules = ruleset2rule(st, rules);
}
}
for (; rules != nil; rules = tl rules)
r = hd rules :: r;
return r;
}
ruleset2rule(statement: ref Statement.Ruleset, onto: list of (string, list of Decl)): list of (string, list of Decl)
{
d := makedecls(statement.decls);
names: list of string;
for (sels := statement.selectors; sels != nil; sels = tl sels) {
csel := hd sels;
if (len csel != 1) {
warning("context-specific selectors not allowed");
continue;
}
(nil, l) := hd csel;
if ((name := selector2name(l)) != nil)
names = name :: names;
}
for (; names != nil; names = tl names)
onto = (hd names, d) :: onto;
return onto;
}
makedecls(decls: list of ref CSS->Decl): list of Decl
{
d: list of Decl;
for (; decls != nil; decls = tl decls) {
nd: Decl;
nd.name = (hd decls).property;
nd.important = (hd decls).important;
s := "";
for (vals := (hd decls).values; vals != nil; vals = tl vals) {
vs: string;
pick v := hd vals {
Percentage =>
vs = v.value + "%";
String or
Number or
Url or
Unicoderange =>
vs = v.value;
Hexcolour =>
vs = rgb2s(v.rgb);
RGB =>
vs = rgb2s(v.rgb);
Ident =>
vs = v.name;
Unit =>
vs = v.value + v.units;
}
if (s != nil)
s[len s] = (hd vals).sep;
s += vs;
}
nd.val = s;
d = nd :: d;
}
return d;
}
rgb2s(rgb: (int, int, int)): string
{
(r, g, b) := rgb;
return sys->sprint("#%.2x%.2x%.2x", r, g, b);
}
warning(s: string)
{
sys->fprint(sys->fildes(2), "cssparser: %s\n", s);
}
selector2name(sel: list of ref Select): string
{
tag: string;
class: string;
pseudo: string;
for (; sel != nil; sel = tl sel) {
pick v := hd sel {
Element =>
tag = v.name;
Class =>
class = "." + v.name;
Pseudo =>
class = ":" + v.name;
* =>
warning("unknown selector type " + string tagof(hd sel));
}
}
return tag + class + pseudo;
}
parsedecl(s: string): list of Decl
{
if (s == nil)
return nil;
(d, e) := css->parsedecl(s);
if (d == nil) {
warning(e);
return nil;
}
return makedecls(d);
}