1*37da2899SCharles.Forsythimplement CSSparser; 2*37da2899SCharles.Forsyth 3*37da2899SCharles.Forsythinclude "sys.m"; 4*37da2899SCharles.Forsyth sys: Sys; 5*37da2899SCharles.Forsythinclude "string.m"; 6*37da2899SCharles.Forsyth str: String; 7*37da2899SCharles.Forsythinclude "css.m"; 8*37da2899SCharles.Forsyth css: CSS; 9*37da2899SCharles.Forsyth Stylesheet, Statement, Select, Value: import css; 10*37da2899SCharles.Forsythinclude "cssparser.m"; 11*37da2899SCharles.Forsyth 12*37da2899SCharles.Forsythinit() 13*37da2899SCharles.Forsyth{ 14*37da2899SCharles.Forsyth sys = load Sys Sys->PATH; 15*37da2899SCharles.Forsyth str = load String String->PATH; 16*37da2899SCharles.Forsyth css = load CSS CSS->PATH; 17*37da2899SCharles.Forsyth if (css == nil) { 18*37da2899SCharles.Forsyth sys->fprint(sys->fildes(2), "cssparser: cannot load %s: %r\n", CSS->PATH); 19*37da2899SCharles.Forsyth raise "fail:bad module"; 20*37da2899SCharles.Forsyth } 21*37da2899SCharles.Forsyth css->init(1); 22*37da2899SCharles.Forsyth} 23*37da2899SCharles.Forsyth 24*37da2899SCharles.Forsythparse(s: string): list of (string, list of Decl) 25*37da2899SCharles.Forsyth{ 26*37da2899SCharles.Forsyth (stylesheet, e) := css->parse(s); 27*37da2899SCharles.Forsyth if (stylesheet == nil) { 28*37da2899SCharles.Forsyth warning("error parsing stylesheet: " + e); 29*37da2899SCharles.Forsyth return nil; 30*37da2899SCharles.Forsyth } 31*37da2899SCharles.Forsyth rules, r: list of (string, list of Decl); 32*37da2899SCharles.Forsyth for (stl := stylesheet.statements; stl != nil; stl = tl stl) { 33*37da2899SCharles.Forsyth pick st := hd stl { 34*37da2899SCharles.Forsyth Ruleset => 35*37da2899SCharles.Forsyth rules = ruleset2rule(st, rules); 36*37da2899SCharles.Forsyth } 37*37da2899SCharles.Forsyth } 38*37da2899SCharles.Forsyth for (; rules != nil; rules = tl rules) 39*37da2899SCharles.Forsyth r = hd rules :: r; 40*37da2899SCharles.Forsyth return r; 41*37da2899SCharles.Forsyth} 42*37da2899SCharles.Forsyth 43*37da2899SCharles.Forsythruleset2rule(statement: ref Statement.Ruleset, onto: list of (string, list of Decl)): list of (string, list of Decl) 44*37da2899SCharles.Forsyth{ 45*37da2899SCharles.Forsyth d := makedecls(statement.decls); 46*37da2899SCharles.Forsyth 47*37da2899SCharles.Forsyth names: list of string; 48*37da2899SCharles.Forsyth for (sels := statement.selectors; sels != nil; sels = tl sels) { 49*37da2899SCharles.Forsyth csel := hd sels; 50*37da2899SCharles.Forsyth if (len csel != 1) { 51*37da2899SCharles.Forsyth warning("context-specific selectors not allowed"); 52*37da2899SCharles.Forsyth continue; 53*37da2899SCharles.Forsyth } 54*37da2899SCharles.Forsyth (nil, l) := hd csel; 55*37da2899SCharles.Forsyth if ((name := selector2name(l)) != nil) 56*37da2899SCharles.Forsyth names = name :: names; 57*37da2899SCharles.Forsyth } 58*37da2899SCharles.Forsyth for (; names != nil; names = tl names) 59*37da2899SCharles.Forsyth onto = (hd names, d) :: onto; 60*37da2899SCharles.Forsyth 61*37da2899SCharles.Forsyth return onto; 62*37da2899SCharles.Forsyth} 63*37da2899SCharles.Forsyth 64*37da2899SCharles.Forsythmakedecls(decls: list of ref CSS->Decl): list of Decl 65*37da2899SCharles.Forsyth{ 66*37da2899SCharles.Forsyth d: list of Decl; 67*37da2899SCharles.Forsyth for (; decls != nil; decls = tl decls) { 68*37da2899SCharles.Forsyth nd: Decl; 69*37da2899SCharles.Forsyth nd.name = (hd decls).property; 70*37da2899SCharles.Forsyth nd.important = (hd decls).important; 71*37da2899SCharles.Forsyth s := ""; 72*37da2899SCharles.Forsyth for (vals := (hd decls).values; vals != nil; vals = tl vals) { 73*37da2899SCharles.Forsyth vs: string; 74*37da2899SCharles.Forsyth pick v := hd vals { 75*37da2899SCharles.Forsyth Percentage => 76*37da2899SCharles.Forsyth vs = v.value + "%"; 77*37da2899SCharles.Forsyth String or 78*37da2899SCharles.Forsyth Number or 79*37da2899SCharles.Forsyth Url or 80*37da2899SCharles.Forsyth Unicoderange => 81*37da2899SCharles.Forsyth vs = v.value; 82*37da2899SCharles.Forsyth Hexcolour => 83*37da2899SCharles.Forsyth vs = rgb2s(v.rgb); 84*37da2899SCharles.Forsyth RGB => 85*37da2899SCharles.Forsyth vs = rgb2s(v.rgb); 86*37da2899SCharles.Forsyth Ident => 87*37da2899SCharles.Forsyth vs = v.name; 88*37da2899SCharles.Forsyth Unit => 89*37da2899SCharles.Forsyth vs = v.value + v.units; 90*37da2899SCharles.Forsyth } 91*37da2899SCharles.Forsyth if (s != nil) 92*37da2899SCharles.Forsyth s[len s] = (hd vals).sep; 93*37da2899SCharles.Forsyth s += vs; 94*37da2899SCharles.Forsyth } 95*37da2899SCharles.Forsyth nd.val = s; 96*37da2899SCharles.Forsyth d = nd :: d; 97*37da2899SCharles.Forsyth } 98*37da2899SCharles.Forsyth return d; 99*37da2899SCharles.Forsyth} 100*37da2899SCharles.Forsyth 101*37da2899SCharles.Forsythrgb2s(rgb: (int, int, int)): string 102*37da2899SCharles.Forsyth{ 103*37da2899SCharles.Forsyth (r, g, b) := rgb; 104*37da2899SCharles.Forsyth return sys->sprint("#%.2x%.2x%.2x", r, g, b); 105*37da2899SCharles.Forsyth} 106*37da2899SCharles.Forsyth 107*37da2899SCharles.Forsythwarning(s: string) 108*37da2899SCharles.Forsyth{ 109*37da2899SCharles.Forsyth sys->fprint(sys->fildes(2), "cssparser: %s\n", s); 110*37da2899SCharles.Forsyth} 111*37da2899SCharles.Forsyth 112*37da2899SCharles.Forsythselector2name(sel: list of ref Select): string 113*37da2899SCharles.Forsyth{ 114*37da2899SCharles.Forsyth tag: string; 115*37da2899SCharles.Forsyth class: string; 116*37da2899SCharles.Forsyth pseudo: string; 117*37da2899SCharles.Forsyth 118*37da2899SCharles.Forsyth for (; sel != nil; sel = tl sel) { 119*37da2899SCharles.Forsyth pick v := hd sel { 120*37da2899SCharles.Forsyth Element => 121*37da2899SCharles.Forsyth tag = v.name; 122*37da2899SCharles.Forsyth Class => 123*37da2899SCharles.Forsyth class = "." + v.name; 124*37da2899SCharles.Forsyth Pseudo => 125*37da2899SCharles.Forsyth class = ":" + v.name; 126*37da2899SCharles.Forsyth * => 127*37da2899SCharles.Forsyth warning("unknown selector type " + string tagof(hd sel)); 128*37da2899SCharles.Forsyth } 129*37da2899SCharles.Forsyth } 130*37da2899SCharles.Forsyth return tag + class + pseudo; 131*37da2899SCharles.Forsyth} 132*37da2899SCharles.Forsyth 133*37da2899SCharles.Forsythparsedecl(s: string): list of Decl 134*37da2899SCharles.Forsyth{ 135*37da2899SCharles.Forsyth if (s == nil) 136*37da2899SCharles.Forsyth return nil; 137*37da2899SCharles.Forsyth (d, e) := css->parsedecl(s); 138*37da2899SCharles.Forsyth if (d == nil) { 139*37da2899SCharles.Forsyth warning(e); 140*37da2899SCharles.Forsyth return nil; 141*37da2899SCharles.Forsyth } 142*37da2899SCharles.Forsyth return makedecls(d); 143*37da2899SCharles.Forsyth} 144