1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
|
.TH W3C-CSS 2
.SH NAME
w3c-css \- cascading style sheet parser
.SH SYNOPSIS
.EX
include "css.m";
css := load CSS CSS->PATH;
Stylesheet: adt {
charset: string;
imports: list of ref Import;
statements: list of ref Statement;
};
Import: adt {
name: string;
media: list of string;
};
Statement: adt {
pick{
Media =>
media: list of string;
rules: list of ref Statement.Ruleset;
Page =>
pseudo: string;
decls: list of ref Decl;
Ruleset =>
selectors: list of Selector;
decls: list of ref Decl;
}
};
Decl: adt {
property: string;
values: list of ref Value;
important: int;
};
Selector: type list of (int, Simplesel); # (combinator, simplesel)
Simplesel: type list of ref Select;
Select: adt {
name: string;
pick{
Element or ID or Any or Class or Pseudo =>
# empty
Attrib =>
op: string; # "=" "~=" "|="
value: ref Value; # optional Ident or String
Pseudofn =>
arg: string;
}
};
Value: adt {
sep: int; # operator preceding this term
pick{
String or
Number or
Percentage or
Url or
Unicoderange =>
value: string;
Hexcolour =>
value: string; # as given
rgb: (int, int, int); # converted
RGB =>
args: cyclic list of ref Value; # as given
rgb: (int, int, int); # converted
Ident =>
name: string;
Unit =>
value: string; # int or float
units: string; # suffix giving units
Function =>
name: string;
args: cyclic list of ref Value;
}
};
init: fn(diag: int);
parse: fn(s: string): (ref Stylesheet, string);
parsedecl: fn(s: string): (list of ref Decl, string);
.EE
.SH DESCRIPTION
.B Css
implements a parser for the World-Wide Web Consortium's Cascading
Style Sheet, specification 2.1.
.PP
.B Init
must be called before any other operation in the module.
If
.I diag
is non-zero, the module will print diagnostics on standard output for
malformed or unrecognised items that are ignored during parsing (as
required by the specification).
.PP
.B Parse
takes a complete stylesheet in string
.IR s ,
parses it, and returns a tuple
.BI ( sheet,\ err )
where
.I sheet
refers to a
.B Stylesheet
value containing the logical content of
.IR s ,
as described below.
On a fatal error,
.I sheet
is nil and
.I err
is a diagnostic.
Most syntactic errors are ignored, as the specification requires.
.PP
In some applications there can be auxiliary declarations outside a stylesheet.
.B Parsedecl
takes a string
.I s
containing a sequence of declarations, and returns a tuple
.BI ( decls,\ err )
where
.I decls
is a list of references to
.B Decl
values, each representing a single
.I declaration
in
.IR s .
On a fatal error,
.I decls
is nil, and
.I err
is a diagnostic.
.PP
The adts represent an abstract syntax of the CSS grammar.
The concrete syntax is presented below in an extended BNF,
derived from the reference grammar,
with each section labelled by the name of the corresponding adts.
(Compared to the reference grammar in the
specification, it abstracts away from the complex rules about where whitespace can appear.)
.TP
.B Stylesheet
.EX
.ft R
\f2stylesheet\fP ::= [ '\f5@charset\fP' STRING '\f5;\fP' ] \f2import\fP* \f2statement\fP*
.EE
.IP
Limbo lists represent lists of items in the grammar.
Nil values denote optional components that are missing.
Upper-case names such as
IDENT,
STRING
and
NUMBER
are terminals; see the CSS specification for their
often subtle definitions.
They are usually represented
by Limbo string values in the adts.
.TP
.B Import
.EX
.ft R
\f2import\fP ::= '\f5@import\fP' (\f2STRING\fP|\f2uri\fP) [\f2medium\fP ('\f5,\fP' \f2medium\fP)*] '\f5;\fP'
\f2uri\fP ::= '\f5url(\fP' STRING '\f5)\fP'
.EE
.IP
.B Import.name
holds the text of the
STRING
or
.IR uri .
.TP
.B Statement
.EX
.ft R
\f2statement\fP ::= \f2ruleset\fP | \f2media\fP | \f2page\fP
\f2media\fP ::= '\f5@media\fP' \f2medium\fP ('\f5,\fP' \f2medium\fP)* '\f5{\fP' \f2ruleset\fP* '\f5}\fP'
\f2medium\fP ::= IDENT
\f2page\fP ::= '\f5@page\fP' [\f2pseudo_page\fP] '\f5{\fP' \f2declaration\fP ('\f5;\fP' \f2declaration\fP)* '\f5}\fP'
\f2pseudo_page\fP ::= '\f5:\fP' IDENT
\f2ruleset\fP ::= \f2selector\fP ('\f5,\fP' \f2selector\fP)* '\f5{\fP' \f2declaration\fP ('\f5;\fP' \f2declaration\fP)* '\f5}\fP'
.EE
.IP
.B Statement
is not in the reference grammar, but is introduced here to give a name corresponding
to the pick adt.
.TP
.B Decl
.EX
.ft R
\f2declaration\fP ::= \f2property\fP '\f5:\fP' \f2expr\fP ['\f5!\fP' '\f5important\fP'] | /* \f2empty\fP */
\f2property\fP ::= IDENT
.EE
.B Decl.values
is a list representing the terms of the
.I expr
(see below for details).
.BR Decl 's
field
.B important
is non-zero if the optional `important' priority is given.
.TP
.B "list of ref Value"
.EX
.ft R
\f2expr\fP ::= \f2term\fP (\f2operator\fP \f2term\fP)*
\f2operator\fP ::= '\f5/\fP' | '\f5,\fP' | /* \f2empty\fP */
.EE
.IP
An
.I expr
is always represented as a list of references to
.B Value
in some containing structure
(where
.B Value
represents a
.IR term ,
see below).
The
.I operator
preceding each
.I term
appears as the field
.B sep
of the corresponding
.BR Value ,
where a space character represents `empty' (concatenation).
.TP
.BR Selector
.EX
.ft R
\f2selector\fP ::= \f2simple_selector\fP (\f2combinator\fP \f2simple_selector\fP)*
\f2combinator\fP ::= '\f5+\fP' | '\f5>\fP' | /* \f2empty\fP */
.EE
.IP
.B Selector
is just a type synonym for a list of tuples, say
.BI ( com,\ simplesel )
where the
.I simplesel
value represents
.I simple_selector
(see below), and the integer
.I com
is one of the characters space (representing `empty'),
.RB ` > '
or
.RB ` + ',
giving the combinator that preceded the simple selector.
(The first in the list is always space.)
.TP
.BR Simplesel ", " Select
.EX
.ft R
\f2simple_selector\fP ::= \f2element_name\fP (\f2hash\fP | \f2class\fP | \f2attrib\fP | \f2pseudo\fP)*
| (\f2hash\fP | \f2class\fP | \f2attrib\fP | \f2pseudo\fP)+
\f2hash\fP ::= '\f5#\fP' NAME
\f2class\fP ::= '\f5.\fP' IDENT
\f2element_name\fP ::= IDENT | '\f5*\fP'
\f2attrib\fP ::= '\f5[\fP' IDENT [('\f5=\fP' | '\f5|=\fP' | '\f5~=\fP') (IDENT | STRING)] '\f5]\fP'
\f2pseudo\fP ::= '\f5:\fP' ( IDENT | IDENT '\f5(\fP' [IDENT] '\f5)\fP' )
.EE
.IP
A
.I simple_selector
is represented by
.BR Simplesel ,
a list of references to
.B Select
values, each representing one
.I element_name
or qualifier.
An
.I element_name
is represented by
.B Select.Element
for an
IDENT,
or
.B Select.Any
for
.RB ` * '.
The qualifiers are
.I hash
.RB ( Select.ID ),
.I class
.RB ( Select.Class ),
.I attrib
.RB ( Select.Attrib ,
where the comparison operator is the string
.BR op ),
.I pseudo
(either
.B Select.Pseudo
if a plain identifier, or
.B Select.Pseudofn
for a function with optional parameter).
.TP
.B Value
.EX
.ft R
\f2term\fP ::= ['\f5+\fP' | '\f5-\fP'] (NUMBER | \f2percent\fP | \f2unit\fP) | STRING | IDENT | \f2uri\fP | \f2function\fP | \f2hexcolour\fP | \f2rgb\fP
\f2function\fP ::= IDENT '\f5(\fP' \f2expr\fP '\f5)\fP'
\f2hash\fP ::= '\f5#\fP' NAME
\f2hexcolour\fP ::= '\f5#\fP' HEXDIGIT+
\f2percent\fP ::= NUMBER '\f5%\fP'
\f2unit\fP ::= NUMBER STRING
\f2rgb\fP ::= '\f5rgb(\fP' \f2term\fP '\f5,\fP' \f2term\fP '\f5,\fP' \f2term\fP '\f5)\fP'
\f2uri\fP ::= '\f5url(\fP' STRING '\f5)\fP'
.EE
.IP
Any sign before a
.BR Number ,
.B Percentage
or
.B Unit
appears as the first character of
.BR value .
All the dimensional units (LENGTH, EMS, EXS, ANGLE, TIME, FREQ and others)
in the reference grammar are mapped to
.BR Value.Unit ,
with the field
.B units
containing the name of the relevant unit (eg,
.LR cm ,
.LR in ,
etc.) in lower case.
Values and names appear shorn of the surrounding punctuation.
.B Value.Hexcolour
includes the original sequence of hex digits as a string,
and a decoding of it as an
.B rgb
triple.
The arguments to the CSS
.B rgb
function are similarly presented in original and decoded forms, in
.BR Value.RGB .
Other function references are returned uninterpreted in
.BR Value.Function .
.SH SOURCE
.B /appl/lib/w3c/css.b
.SH SEE ALSO
``Cascading Style Sheets, level 2 revision 1'',
.B http://www.w3.org/TR/CSS21
|