/[suikacvs]/webroot/www/css/jsie/SimpleParser.js
Suika

Contents of /webroot/www/css/jsie/SimpleParser.js

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.2 - (show annotations) (download) (as text)
Sun Dec 30 05:09:05 2007 UTC (17 years, 3 months ago) by wakaba
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +53 -307 lines
File MIME type: application/javascript
Partial attempt to make scripts work without JSAN

1 function SimpleParser () {
2
3 }
4
5 /**
6 Parses a |DOMString| as an entire CSS style sheet (|stylesheet|)
7 and returns it as a |CSSStyleSheet| object.
8
9 This parser will discard any ignored tokens if any.
10 */
11 SimpleParser.prototype.parseString =
12 function (inputText) {
13 this._String = inputText;
14 this._CurrentCharPos = 0;
15 this._CharStack = [];
16 this._TokenStack = [];
17 this._IgnoreCharset = false;
18
19 var ss = new IEStyleSheet (null, null);
20 this._NSContext = ss;
21
22 this._ParseStyleSheet (ss);
23
24 this._NSContext = null;
25 this._String = null;
26 return ss;
27 };
28
29 /**
30 Parses a |DOMString| as a group of selectors (|selectors-group|)
31 and returns it as a |SSelectorsGroup| object.
32 */
33 SimpleParser.prototype.parseSelectorsString =
34 function (inputText, nsContext) {
35 this._String = inputText;
36 this._CurrentCharPos = 0;
37 this._CharStack = [];
38 this._TokenStack = [];
39 this._NSContext = nsContext;
40
41 var sel = this._ParseSelectorsGroup ();
42
43 var token = this._PopToken (false);
44 if (token != null) {
45 sel = this._Factory.createSSelectorsGroup ();
46 }
47
48 this._NSContext = null;
49 this._String = null;
50
51 return sel;
52 };
53
54 /**
55 Parses the input as a style sheet, i.e. a list of statements,
56 and returns a |CSSStyleSheet| object.
57 */
58 SimpleParser.prototype._ParseStyleSheet =
59 function (ss) {
60 // NOTE: IE ignores |@charset| rules for the purposes of CSSOM and |cssText|.
61
62 /* Whether a top-level |@import| rule should be ignored or not */
63 this._IgnoreImport = false;
64 // TODO: In quirks mode, no @import should be ignored
65
66 S: while (true) {
67 var token = this._PopToken (false);
68 if (!token) {
69 break S;
70 } else if (token.type == "ATKEYWORD") { /* at-rule */
71 this._ParseAtRule (token, ss, true);
72 if (token.value != "import" && token.value != "charset") {
73 this._IgnoreImport = true;
74 }
75 } else if (token.type == "S" || token.type == "CDO" || token.type == "CDC") {
76 this._IgnoreCharset = true;
77 } else if (token.type == "INVALID") {
78 /* Broken string -- ignored */
79 } else { /* rule set */
80 this._TokenStack.push (token);
81 this._ParseRuleSet (ss);
82 this._IgnoreImport = true;
83 }
84 }
85 };
86
87 /**
88 Parses an at-rule.
89 */
90 SimpleParser.prototype._ParseAtRule =
91 function (/* |ATKEYWORD| */ token, parentNode, isParentStyleSheet) {
92 var atType = token.value.toLowerCase ();
93 var token = this._PopToken (false);
94
95 if (atType == "import" &&
96 !this._IgnoreImport &&
97 isParentStyleSheet) {
98 if (token && (token.type == "STRING" || token.type == "URI")) {
99 var uri = token.value;
100 token = this._PopToken (false);
101
102 /* Media query (it might be empty) */
103 var mq = this._ParseMediaQuery ();
104
105 if (token && token.type == ";") {
106 var ati = this._Factory.createCSSImportRule (uri, mq);
107 parentNode.appendCSSRule (ati);
108
109 /* Skipping |S|s if any */
110 token = this._PopToken (false);
111 if (token != null) this._TokenStack.push (token);
112 return;
113 }
114 }
115 }
116
117 /* Skips |any|s */
118 ANY: while (token && (token.type != "{" && token.type != ";" &&
119 token.type != "ATKEYWORD")) {
120 if (token.type == "[" || token.type == "(" || token.type == "FUNCTION") {
121 this._TokenStack.push (token);
122 this._SkipAnyEnclosed ();
123 }
124 token = this._PopToken (false);
125 }
126 /* Skips a |block| if any */
127 if (token == null) {
128 /* WARNING: error */
129 } else if (token.type == "{") {
130 this._TokenStack.push (token);
131 this._SkipAnyEnclosed ();
132 token = this._PopToken (false); /* Skips |S| if any */
133 } else if (token.type == ";") {
134 token = this._PopToken (false); /* Skips |S| if any */
135 }
136 if (token != null) this._TokenStack.push (token);
137 };
138
139 /**
140 Parses a rule set.
141 */
142 SimpleParser.prototype._ParseRuleSet =
143 function (parentNode) {
144 var sel = this._ParseSelectorsGroup ();
145 var token = this._PopToken (false);
146 if (sel.getLength () != 0) {
147 if (token && token.type == "{") {
148 var rs = this._Factory.createCSSRuleSet (sel);
149 this._ParseDeclarationBlockContent (rs);
150 token = this._PopToken (false);
151 if (!token || token.type == "}") {
152 parentNode.appendCSSRule (rs);
153 /* Skips |S| if any */
154 token = this._PopToken (false);
155 if (token != null) this._TokenStack.push (token);
156 return;
157 }
158 }
159 }
160
161 /* Skips |any|s */
162 ANY: while (token && (token.type != "{" && token.type != ";" &&
163 token.type != "ATKEYWORD")) {
164 if (token.type == "[" || token.type == "(" || token.type == "FUNCTION") {
165 this._TokenStack.push (token);
166 this._SkipAnyEnclosed ();
167 }
168 token = this._PopToken (false);
169 }
170 if (token && token.type == "{") {
171 this._TokenStack.push (token);
172 this._SkipAnyEnclosed ();
173 } else {
174 /* Warning: error */
175 }
176 };
177
178 /**
179 Parses the content of a declaration block.
180 */
181 SimpleParser.prototype._ParseDeclarationBlockContent =
182 function (parentNode) {
183 var token = this._PopToken (false);
184 var block = parentNode.getStyle ();
185
186 D: while (token && (token.type == "IDENT" || token.type == "DELIM")) {
187 if (token.type == "IDENT") {
188 var prop = token.value.toLowerCase ();
189 token = this._PopToken (false);
190 if (token && token.type == "DELIM" && token.value == ":") {
191 token = this._PopToken (false);
192 var pp = {}; // TODO: propDef[prop]
193 if (pp.isSupported) {
194 this._TokenStack.push (token);
195 this._ValueStack = [];
196 var valsrc = pp.parseValueFromTokens
197 (this, prop.namespaceURI, prop.prefix, prop.localName);
198 var priority = valsrc != null ? this._GetPriority () : null;
199 if (priority != null) {
200 token = this._PopToken ();
201 if (!token || token.type == "}") {
202 pp.setDeclaredValue (prop.namespaceURI, prop.prefix, prop.localName,
203 block, valsrc, priority);
204 this._TokenStack.push (token);
205 return;
206 } else if (token.type == ";") {
207 pp.setDeclaredValue (prop.namespaceURI, prop.prefix, prop.localName,
208 block, valsrc, priority);
209 token = this._PopToken (false);
210 continue D;
211 }
212 } else {
213 token = this._PopToken (false);
214 }
215 }
216 }
217 }
218
219 /* Skips |any|s */
220 ANY: while (token && token.type != ";") {
221 if (token.type == "{" || token.type == "[" ||
222 token.type == "(" || token.type == "FUNCTION") {
223 this._TokenStack.push (token);
224 this._SkipAnyEnclosed ();
225 } else if (token.type == "}") {
226 this._TokenStack.push (token);
227 return;
228 }
229 token = this._PopToken (false);
230 }
231 if (token && token.type == ";") {
232 token = this._PopToken (false);
233 continue D;
234 }
235 } /* D */
236
237 if (token != null) this._TokenStack.push (token);
238 };
239
240 /**
241 Parses and returns the next value, if any, or |null|.
242 */
243 SimpleParser.prototype._GetNextValue =
244 function (token) {
245 var nextValue = this._ValueStack.pop ();
246 if (nextValue) {
247 return nextValue;
248 }
249 if (token == null) token = this._PopToken (false);
250 if (token == null) {
251 return null;
252 } else if (token.type == "DIMENSION") { /* <length> */
253 return ["DIMENSION", token.value, token.value2.toLowerCase ()];
254 } else if (token.type == "PERCENTAGE") { /* <percentage> */
255 return ["PERCENTAGE", token.value];
256 } else if (token.type == "NUMBER") { /* <number> or zero <length> */
257 return ["NUMBER", token.value];
258 } else if (token.type == "IDENT") {
259 return ["IDENT", token.value.toLowerCase ()];
260 } else if (token.type == "URI") {
261 return ["URI", token.value, this._NSContext.getBaseURI ()];
262 } else if (token.type == "FUNCTION") {
263 var fname = token.value.toLowerCase ();
264 if (fname == "rgb") {
265 token = this._PopToken (false);
266 if (token && token.type == "NUMBER") {
267 var r = token.value;
268 token = this._PopToken ();
269 if (token && token.type == "DELIM" && token.value == ",") {
270 token = this._PopToken ();
271 if (token && token.type == "NUMBER") {
272 var g = token.value;
273 token = this._PopToken ();
274 if (token && token.type == "DELIM" && token.value == ",") {
275 token = this._PopToken ();
276 if (token && token.type == "NUMBER") {
277 var b = token.value;
278 token = this._PopToken ();
279 if (!token || token.type == ")") {
280 /* null token is allowed because of CSS error recovering rule */
281 return ["RGB", r, g, b];
282 }
283 }
284 }
285 }
286 }
287 } else if (token && token.type == "PERCENTAGE") {
288 var r = token.value;
289 token = this._PopToken ();
290 if (token && token.type == "DELIM" && token.value == ",") {
291 token = this._PopToken ();
292 if (token && token.type == "PERCENTAGE") {
293 var g = token.value;
294 token = this._PopToken ();
295 if (token && token.type == "DELIM" && token.value == ",") {
296 token = this._PopToken ();
297 if (token && token.type == "PERCENTAGE") {
298 var b = token.value;
299 token = this._PopToken ();
300 if (!token || token.type == ")") {
301 /* null token is allowed because of CSS error recovering rule */
302 return ["RGBP", r, g, b];
303 }
304 }
305 }
306 }
307 }
308 }
309 }
310 /* error - push a dummy token for later process to ignore
311 tokens that takes matching of "(" & ")" into account */
312 this._TokenStack.push ({type: "FUNCTION", value: "**dummy**"});
313 return null;
314 } else if (token.type == "STRING") {
315 return ["STRING", token.value];
316 } else if (token.type == "DELIM") {
317 if (token.value == "-" || token.value == "+") {
318 var token2 = this._PopToken ();
319 if (token2 == null) {
320 this._TokenStack.push (token2);
321 } else if (token2.type == "NUMBER") { /* <number> or zero <length> */
322 if (token.value == "-") token2.value *= -1;
323 return ["NUMBER", token2.value];
324 } else {
325 this._TokenStack.push (token2);
326 }
327 }
328 } else if (token.type == "HASH") {
329 if (token.value.match (/^[0-9A-Fa-f]{6}$/)) {
330 return ["RGB", parseInt (token.value.slice (0, 2), 16),
331 parseInt (token.value.slice (2, 4), 16),
332 parseInt (token.value.slice (4, 6), 16)];
333 } else if (token.value.match (/^[0-9A-Fa-f]{3}$/)) {
334 return ["RGB", parseInt (token.value.slice (0, 1), 16),
335 parseInt (token.value.slice (1, 2), 16),
336 parseInt (token.value.slice (2, 3), 16)];
337 }
338 }
339 this._TokenStack.push (token);
340 return null;
341 };
342
343 /**
344 Converts priority specification at the end of the property declaration, if any,
345 into a |CSSValue| object and tests whether it reaches to the very last
346 of the declaration or not.
347 */
348 SimpleParser.prototype._GetPriority = function () {
349 if (this._ValueStack.length > 0) return null;
350 var token = this._PopToken (false);
351 var val = null;
352 if (token != null && token.type == "DELIM" && token.value == "!") {
353 token = this._PopToken (false);
354 if (token != null && token.type == "IDENT") {
355 val = token.value.toLowerCase ();
356 token = this._PopToken (false);
357 } else {
358 return null;
359 }
360 }
361 if (token == null ||
362 token.type == "}" ||
363 token.type == ";") {
364 if (token != null) this._TokenStack.push (token);
365 return val;
366 } else {
367 this._TokenStack.push (token);
368 return null;
369 }
370 };
371
372 /**
373 Expands an identifier (|ident|) into a triplet of namespace URI,
374 namespace prefix, and local name.
375
376 Note that namespace extension to identifiers is a non-standard feature.
377
378 @param ident The identifier to expand. It should be normalized to
379 lower case if necessary. The method does no such convertion.
380 @param defaultNamespaceURI The namespace URI of the default namespace.
381 If |null|, the default of the default namespace URI is
382 |urn:x-suika-fam-cx:css:|.
383 @return An |Object| that has three properties: |namespaceURI|, |localName|,
384 and |prefix|.
385 */
386 SimpleParser.prototype._ExpandNamespacedIdent =
387 function (ident, defaultNamespaceURI) {
388 if (this._NSContext != null && ident.match (/^-([^-]+)-/)) {
389 var prefix = RegExp.$1;
390 var lname = ident.substring (prefix.length + 2);
391 var ns = this._NSContext.lookupNamespaceURI (prefix);
392 /* ISSUE: Is prefix case-sensitive? */
393 if (ns != null) {
394 return {namespaceURI: ns, localName: lname, prefix: prefix};
395 }
396 }
397 return {namespaceURI: defaultNamespaceURI == null ? "urn:x-suika-fam-cx:css:"
398 : defaultNamespaceURI,
399 localName: ident.toLowerCase (), prefix: null};
400 };
401
402 /**
403 Parses a selector and returns it as a |SSelectorsGroup| object.
404 */
405 SimpleParser.prototype._ParseSelectorsGroup =
406 function () {
407 var token = this._PopToken (false);
408 var sels = this._Factory.createSSelectorsGroup ();
409 Sel: while (token != null) {
410 var sel = this._Factory.createSSelector ();
411 var cmb = null;
412 SelSeq: while (token != null) {
413 var pfx = "";
414 var ln = null;
415 var nsuri = null;
416 if (token.type == "IDENT" ||
417 (token.type == "DELIM" && token.value == "*")) {
418 ln = token.value;
419 pfx = null;
420 token = this._PopToken (true);
421 }
422
423 if (token && token.type == "DELIM" && token.value == "|") {
424 token = this._PopToken (true);
425 if (token != null && (token.type == "IDENT" ||
426 token.type == "DELIM" && token.value == "*")) {
427 pfx = ln != null ? ln.toLowerCase () : "";
428 if (pfx != "*") {
429 nsuri = this._NSContext.lookupNamespaceURI (pfx != "" ? pfx : null);
430 if (pfx != "" && nsuri == null) {
431 /* Invalid selector */
432 return this._Factory.createSSelectorsGroup ();
433 }
434 }
435 ln = token.value;
436 token = this._PopToken (true);
437 } else {
438 /* Invalid selector */
439 if (token != null && token.type == "S") token = this._PopToken (false);
440 if (token != null) this._TokenStack.push (token);
441 return this._Factory.createSSelectorsGroup ();
442 }
443 }
444
445 if (ln == null || pfx == null) {
446 pfx = null;
447 nsuri = this._NSContext.lookupNamespaceURI (null);
448 }
449
450 var tsel = this._Factory.createSTypeSelectorNS (nsuri, pfx, ln);
451 var selseq = this._Factory.createSSimpleSelectorSequence (tsel);
452
453 var hasPseudoElement = false;
454 SimpleSel: while (token != null) {
455 if (token.type == "DELIM") {
456 if (token.value == "." && !hasPseudoElement) {
457 token = this._PopToken (true);
458 if (token != null && token.type == "IDENT") {
459 selseq.appendSimpleSelector
460 (this._Factory.createSClassSelector (token.value));
461 token = this._PopToken (true);
462 continue SimpleSel;
463 }
464 } else if (token.value == "+" || token.value == "~" ||
465 token.value == ">" || token.value == ",") {
466 if (ln == null && selseq.getSimpleSelectorLength () == 1) {
467 // Empty (invalid) selector
468 } else {
469 break SimpleSel;
470 }
471 } else if (token.value == ":") {
472 token = this._PopToken (true);
473 if (token != null) {
474 if (token.type == "IDENT") {
475 var pctype = this._ExpandNamespacedIdent
476 (token.value.toLowerCase (),
477 "urn:x-suika-fam-cx:selectors:");
478 var pp = this._PseudoClassParser[pctype.namespaceURI] != null
479 ? this._PseudoClassParser[pctype.namespaceURI]
480 [pctype.localName]
481 : null;
482 if (pp != null) { /* Supported pseudo class */
483 if (pp.isPseudoElement) {
484 hasPseudoElement = true;
485 }
486 if (pp.apply (this, [selseq, pctype])) {
487 token = this._PopToken (true);
488 continue SimpleSel;
489 }
490 }
491 } else if (token.value == ":") {
492 hasPseudoElement = true;
493 token = this._PopToken (true);
494 if (token != null && token.type == "IDENT") {
495 var petype = this._ExpandNamespacedIdent
496 (token.value.toLowerCase (),
497 "urn:x-suika-fam-cx:selectors:");
498 var pp = this._PseudoElementParser[petype.namespaceURI] != null
499 ? this._PseudoElementParser[petype.namespaceURI]
500 [petype.localName]
501 : null;
502 if (pp != null) { /* Supported pseudo element */
503 if (pp.apply (this, [selseq, petype])) {
504 token = this._PopToken (true);
505 continue SimpleSel;
506 }
507 }
508 }
509 }
510 }
511 }
512 } else if (token.type == "[" && !hasPseudoElement) {
513 token = this._PopToken (false);
514 var pfx = "";
515 var nsuri = null;
516 var ln = null;
517 if (token != null && (token.type == "IDENT" ||
518 token.type == "DELIM" && token.value == "*")) {
519 ln = token.value;
520 pfx = null;
521 token = this._PopToken (true);
522 }
523
524 if (token && token.type == "DELIM" && token.value == "|") {
525 token = this._PopToken (true);
526 if (token != null && token.type == "IDENT") {
527 pfx = ln != null ? ln.toLowerCase () : "";
528 if (pfx != "*") {
529 if (pfx != "") nsuri = this._NSContext.lookupNamespaceURI (pfx);
530 if (pfx != "" && nsuri == null) {
531 /* Invalid selector */
532 return this._Factory.createSSelectorsGroup ();
533 }
534 }
535 ln = token.value;
536 token = this._PopToken (false);
537 } else {
538 /* Invalid selector */
539 if (token != null && token.type == "S") token = this._PopToken (false);
540 if (token != null) this._TokenStack.push (token);
541 return this._Factory.createSSelectorsGroup ();
542 }
543 }
544
545 if (ln == "*") {
546 /* Invalid selector */
547 if (token != null && token.type == "S") token = this._PopToken (false);
548 if (token != null) this._TokenStack.push (token);
549 return this._Factory.createSSelectorsGroup ();
550 }
551
552 if (token != null && token.type == "S") token = this._PopToken (false);
553 if (token != null && ln != null) {
554 var op = token.type;
555 if ((op == "DELIM" && token.value == "=") ||
556 op == "INCLUDES" ||
557 op == "DASHMATCH" ||
558 op == "PREFIXMATCH" ||
559 op == "SUFFIXMATCH" ||
560 op == "SUBSTRINGMATCH") {
561 token = this._PopToken (false);
562 if (token != null &&
563 (token.type == "STRING" || token.type == "IDENT")) {
564 var val = token.value;
565 token = this._PopToken (false);
566 if (token != null && token.type == "]") {
567 selseq.appendSimpleSelector
568 (this._Factory.createSAttributeSelectorNS
569 (nsuri, pfx, ln,
570 op == "DELIM"
571 ? Selectors.AttributeSelector
572 .prototype.SELECTORS_ATTRIBUTE_EQUALS :
573 op == "INCLUDES"
574 ? Selectors.AttributeSelector
575 .prototype.SELECTORS_ATTRIBUTE_INCLUDES :
576 op == "DASHMATCH"
577 ? Selectors.AttributeSelector
578 .prototype.SELECTORS_ATTRIBUTE_DASHMATCH :
579 op == "PREFIXMATCH"
580 ? Selectors.AttributeSelector
581 .prototype.SELECTORS_ATTRIBUTE_PREFIXMATCH :
582 op == "SUFFIXMATCH"
583 ? Selectors.AttributeSelector
584 .prototype.SELECTORS_ATTRIBUTE_SUFFIXMATCH :
585 Selectors.AttributeSelector
586 .prototype.SELECTORS_ATTRIBUTE_SUBSTRINGMATCH,
587 val));
588 token = this._PopToken (true);
589 continue SimpleSel;
590 }
591 }
592 } else if (op == "]") {
593 selseq.appendSimpleSelector
594 (this._Factory.createSAttributeSelectorNS
595 (nsuri, pfx, ln,
596 Selectors.AttributeSelector
597 .prototype.SELECTORS_ATTRIBUTE_HAS, null));
598 token = this._PopToken (true);
599 continue SimpleSel;
600 }
601 }
602 } else if (token.type == "HASH" && !hasPseudoElement) {
603 selseq.appendSimpleSelector
604 (this._Factory.createSIDSelector (token.value));
605 token = this._PopToken (true);
606 continue SimpleSel;
607 } else if (token.type == "S" || token.type == "}") {
608 break SimpleSel;
609 } else if (token.type == "{" || token.type == "ATKEYWORD") {
610 if (ln == null && selseq.getSimpleSelectorLength () == 1) {
611 // Empty (invalid) selector
612 } else {
613 break SimpleSel;
614 }
615 }
616
617 /* Invalid selector */
618 if (token != null && token.type == "S") token = this._PopToken (false);
619 if (token != null) this._TokenStack.push (token);
620 return this._Factory.createSSelectorsGroup ();
621 } /* SimpleSel */
622 sel.appendSimpleSelectorSequence (cmb, selseq);
623
624 if (token != null && token.type == "S" && !hasPseudoElement) {
625 cmb = Selectors.Selector
626 .prototype.SELECTORS_COMBINATOR_DESCENDANT;
627 token = this._PopToken (false);
628 } else {
629 cmb = null;
630 }
631 if (token != null && token.type == "DELIM" && !hasPseudoElement) {
632 if (token.value == "+") {
633 cmb = Selectors.Selector
634 .prototype.SELECTORS_COMBINATOR_CHILD;
635 token = this._PopToken (false);
636 continue SelSeq;
637 } else if (token.value == ">") {
638 cmb = Selectors.Selector
639 .prototype.SELECTORS_COMBINATOR_DIRECT_ADJACENT_SIBLING;
640 token = this._PopToken (false);
641 continue SelSeq;
642 } else if (token.value == "~") {
643 cmb = Selectors.Selector
644 .prototype.SELECTORS_COMBINATOR_INDIRECT_ADJACENT_SIBLING;
645 token = this._PopToken (false);
646 continue SelSeq;
647 } else if (token.value != "*" &&
648 token.value != "|" &&
649 token.value != ":" &&
650 token.value != ".") {
651 cmb = null;
652 break SelSeq;
653 }
654 } else if (token == null ||
655 (token.type != "IDENT" &&
656 token.type != "HASH" &&
657 token.type != "[" &&
658 !(token.type == "DELIM" && (token.value == "*" ||
659 token.value == "|" ||
660 token.value == ":" ||
661 token.value == ".")))) {
662 cmb = null;
663 break SelSeq;
664 } else if (cmb == null) {
665 break SelSeq;
666 }
667 } /* SelSeq */
668 if (cmb != null) { /* Non-terminated selector -> an empty Selectors */
669 /* Invalid selector */
670 if (token != null && token.type == "S") token = this._PopToken (false);
671 if (token != null) this._TokenStack.push (token);
672 return this._Factory.createSSelectorsGroup ();
673 }
674 sels.appendSelector (sel);
675
676 if (token != null && token.type == "DELIM" && token.value == ",") {
677 token = this._PopToken (false);
678 } else {
679 break Sel;
680 }
681 } /* Sel */
682 if (token != null) {
683 this._TokenStack.push (token);
684 }
685 return sels;
686 };
687
688 /*
689 selectors-group := selector *("," *S selector)
690 selector := simple-selector-sequence
691 *(combinator simple-selector-sequence)
692 pseudo-elements *S
693 simple-selector-sequence := [type-selector / universal-selector]
694 1*(simple-selector - type-selector
695 - universal-selector) /
696 type-selector / universal-selector
697 simple-selector := type-selector /
698 universal-selector /
699 attribute-selector /
700 class-selector /
701 ID-selector /
702 content-selector /
703 pseudo-class
704 type-selector := [namespace] element-name
705 element-name := IDENT
706 namespace := [namespace-prefix] "|"
707 namespace-prefix := IDENT / "*"
708 universal-selector := [namespace] "*"
709 attribute-selector := "[" *S [namespace] attribute-name *S
710 [attribute-match *S attribute-value] *S "]"
711 attribute-name := IDENT
712 attribute-match := "=" / INCLUDES / DASHMATCH /
713 PREFIXMATCH / SUFFIXMATCH / SUBSTRINGMATCH
714 attribute-value := IDENT / STRING
715 class-selector := "." IDENT
716 ID-selector := HASH
717 pseudo-class := ":" IDENT / functional-pseudo-class
718 functional-pseudo-class := ":" FUNCTION *S pseudo-class-value *S ")"
719 pseudo-class-value := IDENT / STRING / NUMBER / expression / negation-arg
720 expression := ["-" / INTEGER] "n" [SIGNED_INTEGER] / INTEGER
721 negation-arg := simple-selector
722 pseudo-elements := [structural-pseudo-elements]
723 [formatting-pseudo-element]
724 structural-pseudo-elements := *(["::outside" ["(" integer ")"]]
725 ("::before" ["(" integer ")"] / ":before" /
726 "::after" ["(" integer ")"] / ":after" /
727 "::alternate")
728 ["::outside" ["(" integer ")"]])
729 formatting-pseudo-element := "::first-line" / ":first-line" /
730 "::first-letter" / ":first-letter" /
731 "::marker" /
732 "::line-marker" /
733 "::selection"
734 combinator := 1*S / *S (">" / "+" / "~") *S
735 S := <SPACE> /
736 <HORIZONTAL TABULATOR> /
737 <LINE FEED> /
738 <CARRIAGE RETURN> /
739 <FORM FEED>
740 */
741
742 /**
743 Parses a media query and returns it as a |MQQuery| object.
744 */
745 SimpleParser.prototype._ParseMediaQuery =
746 function () {
747
748 };
749
750 /**
751 Skips any tokens enclosed by a pair of braces.
752 */
753 SimpleParser.prototype._SkipAnyEnclosed = function () {
754 var pair = [];
755 var token = this._PopToken (false);
756 T: while (token) {
757 if (token.type == "{" || token.type == "[" ||
758 token.type == "(" || token.type == "FUNCTION") {
759 pair.push (token.type == "{" ? "}" :
760 token.type == "[" ? "]" :
761 ")");
762 } else if (token.type == "}" || token.type == "]" ||
763 token.type == ")") {
764 var l = pair.pop ();
765 if (l == token.type) {
766 if (pair.length == 0) {
767 break T;
768 }
769 } else {
770 pair.push (l);
771 /* WARNING: Unmatched! */
772 }
773 }
774 token = this._PopToken (false);
775 } /* T */
776 if (pair.length > 0) {
777 /* WARNING: Unmatched! */
778 }
779 /* Skips |S| if any */
780 token = this._PopToken (false);
781 if (token != null) this._TokenStack.push (token);
782 };
783
784 /**
785 Pops the next token, if any, or returns |null|.
786
787 @param Ssignificant If |false|, any |S| token is ignored. Otherwise,
788 an |S| token is returned as well as other kind of
789 tokens.
790 */
791 SimpleParser.prototype._PopToken = function (Ssignificant) {
792 var nextToken = this._TokenStack.pop ();
793 while (!Ssignificant && nextToken != null && nextToken.type == "S") {
794 nextToken = this._TokenStack.pop ();
795 }
796 if (nextToken) {
797 return nextToken;
798 }
799 var r = "";
800 X: while (true) {
801 var ch = this._PopChar ();
802 if (ch.length == 0) {
803 break X;
804 } else if (ch.match (/^[_a-zA-Z]/) || ch.charCodeAt (0) > 0x007F ||
805 ch == "\\") {
806 var ident = ch == "\\" ? this._GetUnescapedChar (false) : ch;
807 if (ident.length != 0) {
808 var ch2;
809 I: while (true) {
810 ch2 = this._PopChar ();
811 if (ch2.match (/^[_a-zA-Z0-9-]/) || ch2.charCodeAt (0) > 0x007F) {
812 ident += ch2;
813 } else if (ch2 == "\\") {
814 ch2 = this._GetUnescapedChar (false);
815 if (ch2.length != 0) {
816 ident += ch2;
817 } else {
818 ch2 = "\\";
819 break I;
820 }
821 } else {
822 break I;
823 }
824 } /* I */
825
826 if (ch2 == "(") {
827 if (ident.toLowerCase () != "url") {
828 return {type: "FUNCTION", value: ident};
829 } else {
830 var chars = [ch2];
831 var ch3 = this._PopChar ();
832 IUS: while (true) {
833 if (ch3 == "\u0020" || ch3 == "\u0009" || ch3 == "\u000D" ||
834 ch3 == "\u000A" || ch3 == "\u000C") {
835 chars.push (ch3);
836 ch3 = this._PopChar ();
837 } else {
838 break IUS;
839 }
840 } /* IUS */
841 var uri = "";
842 if (ch3 == '"' || ch3 == "'") { /* string */
843 IUQ: while (true) {
844 var ch4 = this._PopChar ();
845 if (ch4 != "\u000D" && ch4 != "\u000A" && ch4 != "\u000C" &&
846 ch4 != "\\" && ch4 != ch) {
847 uri += ch4;
848 } else if (ch4 == ch) {
849 break IUQ;
850 } else if (ch4 == "\\") {
851 var unescaped = this._GetUnescapedChar (true);
852 if (unescaped.length > 0) {
853 uri += unescaped;
854 } else {
855 this._CharStack.push (ch4);
856 this._TokenStack.push ({type: "INVALID", value: uri});
857 chars.unshift (); /* |(| */
858 var ss = "";
859 for (var i = 0; i < chars.length; i++) {
860 ss += chars[i];
861 }
862 this._TokenStack.push ({type: "S", value: ss});
863 this._TokenStack.push ({type: "("});
864 return {type: "IDENT", value: ident};
865 }
866 } else {
867 if (ch2.length > 0) this._CharStack.push (ch2);
868 this._TokenStack.push ({type: "INVALID", value: uri});
869 chars.unshift (); /* |(| */
870 var ss = "";
871 for (var i = 0; i < chars.length; i++) {
872 ss += chars[i];
873 }
874 this._TokenStack.push ({type: "S", value: ss});
875 this._TokenStack.push ({type: "("});
876 return {type: "IDENT", value: ident};
877 }
878 } /* IUQ */
879 } else if (ch3.match (/^[!#$%&*-~]/) || ch3.charCodeAt (0) > 0x007F) {
880 IU: while (true) {
881 chars.push (ch3);
882 if (ch3 != "\\") {
883 uri += ch3;
884 } else {
885 var unescaped = this._GetUnescapedChar (false);
886 if (unescaped.length > 0) {
887 uri += ch3;
888 } else {
889 for (var i = 0; i < chars.length - 1; i++) {
890 this._CharStack.push (chars[i]);
891 }
892 return {type: "IDENT", value: ident};
893 }
894 }
895 ch3 = this._PopChar ();
896 if (ch3.match (/^[!#$%&*-~]/) || ch3.charCodeAt (0) > 0x007F) {
897 //
898 } else if (ch3 == ")" ||
899 ch3 == "\u0020" || ch3 == "\u0009" || ch3 == "\u000D" ||
900 ch3 == "\u000A" || ch3 == "\u000C") {
901 chars.push (ch3);
902 break IU;
903 } else {
904 for (var i = 0; i < chars.length - 1; i++) {
905 this._CharStack.push (chars[i]);
906 }
907 if (ch3.length > 0) this._CharStack.push (ch3);
908 return {type: "IDENT", value: ident};
909 }
910 } /* IU */
911 } else {
912 for (var i = 0; i < chars.length - 1; i++) {
913 this._CharStack.push (chars[i]);
914 }
915 return {type: "IDENT", value: ident};
916 }
917 if (ch3 != ")") {
918 ch3 = this._PopChar ();
919 IUR: while (true) {
920 if (ch3 == ")") {
921 break IUR;
922 } else if (ch3 == "\u0020" || ch3 == "\u0009" || ch3 == "\u000D" ||
923 ch3 == "\u000A" || ch3 == "\u000C") {
924 chars.push (ch3);
925 ch3 = this._PopChar ();
926 } else {
927 if (ch3.length > 0) this._CharStack.push (ch3);
928 for (var i = 0; i < chars.length - 1; i++) {
929 this._CharStack.push (chars[i]);
930 }
931 return {type: "IDENT", value: ident};
932 }
933 } /* IUR */
934 }
935 return {type: "URI", value: uri};
936 } /* url */
937 } else if ((ident == "U" || ident == "u") && ch2 == "+") {
938 var ch3 = this._PopChar ();
939 if (ch3.match (/^[0-9A-Fa-f?]/)) {
940 var cp = ch3;
941 ch3 = this._PopChar ();
942 IR: for (var i = 1; i < 6; i++) {
943 if (ch3.match (/^[0-9A-Fa-f?]/)) {
944 cp += ch3;
945 ch3 = this._PopChar ();
946 } else {
947 break IR;
948 }
949 } /* IR */
950 var cp2 = "";
951 if (ch3 == "-") {
952 var ch4 = this._PopChar ();
953 if (ch4.match (/^[0-9A-Fa-f]/)) {
954 cp2 = ch4;
955 IR2: for (var i = 1; i < 6; i++) {
956 ch4 = this._PopChar ();
957 if (ch4.match (/^[0-9A-Fa-f]/)) {
958 cp2 += ch4;
959 } else {
960 if (ch4.length > 0) this._CharStack.push (ch4);
961 break IR2;
962 }
963 } /* IR2 */
964 } else {
965 if (ch4.length > 0) this._CharStack.push (ch4);
966 }
967 } else if (ch3.length > 0) {
968 this._CharStack.push (ch3);
969 }
970 return {type: "UNICODE-RANGE", value: cp, value2: cp2};
971 } else {
972 if (ch3.length > 0) this._CharStack.push (ch3);
973 this._CharStack.push (ch2);
974 return {type: "IDENT", value: ident};
975 }
976 } else {
977 if (ch2.length > 0) this._CharStack.push (ch2);
978 return {type: "IDENT", value: ident};
979 }
980 } else { /* |REVERSE SOLIDUS| which does not introduce an |escape| */
981 return {type: "DELIM", value: ch};
982 }
983 } else if (ch.match (/^[0-9.]/)) {
984 var num = ch != "." ? ch : "0";
985 var ch2 = ch != "." ? this._PopChar () : ch;
986 if (ch != ".") {
987 N: while (true) {
988 if (ch2.match (/^[0-9]/)) {
989 num += ch2;
990 ch2 = this._PopChar ();
991 } else {
992 break N;
993 }
994 } /* N */
995 }
996
997 var isFloat = false;
998 if (ch2 == ".") {
999 isFloat = true;
1000 ch2 = this._PopChar ();
1001 if (ch2.match (/^[0-9]/)) {
1002 num += "." + ch2;
1003 ch2 = this._PopChar ();
1004 N: while (true) {
1005 if (ch2.match (/^[0-9]/)) {
1006 num += ch2;
1007 ch2 = this._PopChar ();
1008 } else {
1009 break N;
1010 }
1011 } /* N */
1012 } else if (ch == ".") {
1013 if (ch2.length > 0) this._CharStack.push (ch2);
1014 return {type: "DELIM", value: ch};
1015 } else {
1016 this._CharStack.push (ch2);
1017 ch2 = ".";
1018 }
1019 }
1020 num = parseFloat (num, 10);
1021
1022 var ihyphen = false;
1023 if (ch2 == "-") {
1024 ihyphen = true;
1025 ch2 = this._PopChar ();
1026 }
1027 if (ch2.match (/^[_a-zA-Z\\]/) || ch2.charCodeAt (0) > 0x007F) {
1028 var ident = ch2 == "\\" ? this._GetUnescapedChar (false) : ch2;
1029 if (ident.length != 0) {
1030 I: while (true) {
1031 ch2 = this._PopChar ();
1032 if (ch2.match (/^[_a-zA-Z0-9-]/) || ch2.charCodeAt (0) > 0x007F) {
1033 ident += ch2;
1034 } else if (ch2 == "\\") {
1035 ch2 = this._GetUnescapedChar (false);
1036 if (ch2.length != 0) {
1037 ident += ch2;
1038 } else {
1039 this._TokenStack.push ({type: "DELIM", value: "\\"});
1040 break I;
1041 }
1042 } else {
1043 if (ch2.length > 0) this._CharStack.push (ch2);
1044 break I;
1045 }
1046 } /* I */
1047 return {type: "DIMENSION", value: num,
1048 value2: ihyphen ? "-" + ident : ident};
1049 } else {
1050 this._CharStack.push (ch2);
1051 if (ihyphen) this._CharStack.push ("-");
1052 return {type: "NUMBER", value: num, isFloat: isFloat};
1053 }
1054 } else if (!ihyphen && ch2 == "%") {
1055 return {type: "PERCENTAGE", value: num};
1056 } else {
1057 if (ch2.length > 0) this._CharStack.push (ch2);
1058 if (ihyphen) this._CharStack.push ("-");
1059 return {type: "NUMBER", value: num};
1060 }
1061 } else if (ch == ";" || ch == "{" || ch == "}" || ch == "(" || ch == ")" ||
1062 ch == "[" || ch == "]") {
1063 return {type: ch};
1064 } else if (ch == "\u0020" || ch == "\u0009" || ch == "\u000A" ||
1065 ch == "\u000D" || ch == "\u000C") { /* S */
1066 S: while (true) {
1067 var ch = this._PopChar ();
1068 if (ch == "\u0020" || ch == "\u0009" || ch == "\u000A" ||
1069 ch == "\u000D" || ch == "\u000C") {
1070 //
1071 } else {
1072 if (ch.length > 0) this._CharStack.push (ch);
1073 break S;
1074 }
1075 }
1076 if (Ssignificant) {
1077 return {type: "S"};
1078 } else {
1079 continue X;
1080 }
1081 } else if (ch == "-") {
1082 var ch2 = this._PopChar ();
1083 if (ch2.match (/^[_a-zA-Z\\]/) || ch2.charCodeAt (0) > 0x007F) {
1084 var ident = ch2 == "\\" ? this._GetUnescapedChar (false) : ch2;
1085 if (ident.length != 0) {
1086 I: while (true) {
1087 ch2 = this._PopChar ();
1088 if (ch2.match (/^[_a-zA-Z0-9-]/) || ch2.charCodeAt (0) > 0x007F) {
1089 ident += ch2;
1090 } else if (ch2 == "\\") {
1091 ch2 = this._GetUnescapedChar (false);
1092 if (ch2.length != 0) {
1093 ident += ch2;
1094 } else {
1095 ch2 = "\\";
1096 break I;
1097 }
1098 } else {
1099 break I;
1100 }
1101 } /* I */
1102
1103 if (ch2 == "(") {
1104 return {type: "FUNCTION", value: "-" + ident};
1105 } else {
1106 if (ch2.length > 0) this._CharStack.push (ch2);
1107 return {type: "IDENT", value: "-" + ident};
1108 }
1109 } else {
1110 this._TokenStack.push ({type: "DELIM", value: "\\"});
1111 return {type: "DELIM", value: "-"};
1112 }
1113 } else if (ch2 == "-") {
1114 var ch3 = this._PopChar ();
1115 if (ch3 == ">") { /* CDC */
1116 return {type: "CDC"};
1117 } else {
1118 this._CharStack.push (ch3);
1119 this._CharStack.push (ch2);
1120 return {type: "DELIM", value: ch};
1121 }
1122 } else {
1123 if (ch2.length > 0) this._CharStack.push (ch2);
1124 return {type: "DELIM", value: ch};
1125 }
1126 } else if (ch == "@" || ch == "#") { /* ATKEYWORD || HASH */
1127 var ch2 = this._PopChar ();
1128 var ihyphen = false;
1129 if (ch == "@" && ch2 == "-") {
1130 ihyphen = true;
1131 ch2 = this._PopChar ();
1132 }
1133 if (ch2.match (/^[_a-zA-Z\\]/) || ch2.charCodeAt (0) > 0x007F) {
1134 var ident = ch2 == "\\" ? this._GetUnescapedChar (false) : ch2;
1135 if (ident.length != 0) {
1136 I: while (true) {
1137 ch2 = this._PopChar ();
1138 if (ch2.match (/^[_a-zA-Z0-9-]/) || ch2.charCodeAt (0) > 0x007F) {
1139 ident += ch2;
1140 } else if (ch2 == "\\") {
1141 ch2 = this._GetUnescapedChar (false);
1142 if (ch2.length != 0) {
1143 ident += ch2;
1144 } else {
1145 this._CharStack.push ("\\");
1146 break I;
1147 }
1148 } else {
1149 if (ch2.length > 0) this._CharStack.push (ch2);
1150 break I;
1151 }
1152 } /* I */
1153
1154 return {type: ch == "@" ? "ATKEYWORD" : "HASH",
1155 value: (ihyphen ? "-" : "") + ident};
1156 } else {
1157 this._CharStack.push ("\\");
1158 if (ihyphen) this._CharStack.push ("-");
1159 return {type: "DELIM", value: ch};
1160 }
1161 } else {
1162 if (ch2.length > 0) this._CharStack.push (ch2);
1163 return {type: "DELIM", value: ch};
1164 }
1165 } else if (ch == '"' || ch == "'") { /* STRING || INVALID */
1166 var text = "";
1167 Q: while (true) {
1168 var ch2 = this._PopChar ();
1169 if (ch2 != "\u000D" && ch2 != "\u000A" && ch2 != "\u000C" &&
1170 ch2 != "\\" && ch2 != ch) {
1171 text += ch2;
1172 } else if (ch2 == ch) {
1173 return {type: "STRING", value: text};
1174 break Q;
1175 } else if (ch2 == "\\") {
1176 var unescaped = this._GetUnescapedChar (true);
1177 if (unescaped.length > 0) {
1178 text += unescaped;
1179 } else {
1180 this._CharStack.push (ch2);
1181 return {type: "INVALID", value: text};
1182 }
1183 } else if (ch2.length == 0) {
1184 /* Note that an |INVALID| at the end of the entity is
1185 treated as if it is a |STRING| by the error handling rule. */
1186 return {type: "STRING", value: text};
1187 } else {
1188 this._CharStack.push (ch2);
1189 return {type: "INVALID", value: text};
1190 }
1191 } /* Q */
1192 } else if (ch == "/") {
1193 var ch2 = this._PopChar ();
1194 if (ch2 == "*") { /* COMMENT */
1195 ch2 = this._PopChar ();
1196 C: while (ch2.length > 0) {
1197 if (ch2 == "*") {
1198 ch2 = this._PopChar ();
1199 if (ch2 == "/") {
1200 break C;
1201 }
1202 } else {
1203 ch2 = this._PopChar ();
1204 }
1205 } /* C */
1206 } else {
1207 if (ch2.length > 0) this._CharStack.push (ch2);
1208 return {type: "DELIM", value: ch};
1209 }
1210 } else if (ch == "~" || ch == "|" || ch == "^" || ch == "$" || ch == "*") {
1211 var ch2 = this._PopChar (); /* [CSS3] */
1212 if (ch2 == "=") { /* INCLUDES || DASHMATCH || ... */
1213 return {type: ch == "~" ? "INCLUDES" :
1214 ch == "|" ? "DASHMATCH" :
1215 ch == "^" ? "PREFIXMATCH" :
1216 ch == "$" ? "SUFFIXMATCH" :
1217 "SUBSTRINGMATCH"};
1218 } else {
1219 if (ch2.length > 0) this._CharStack.push (ch2);
1220 return {type: "DELIM", value: ch};
1221 }
1222 } else if (ch == "<") {
1223 var ch2 = this._PopChar ();
1224 if (ch2 == "!") {
1225 var ch3 = this._PopChar ();
1226 if (ch3 == "-") {
1227 var ch4 = this._PopChar ();
1228 if (ch4 == "-") { /* CDO */
1229 return {type: "CDO"};
1230 } else {
1231 if (ch4.length > 0) this._CharStack.push (ch4);
1232 this._CharStack.push (ch3);
1233 this._CharStack.push (ch2);
1234 return {type: "DELIM", value: ch};
1235 }
1236 } else {
1237 if (ch3.length > 0) this._CharStack.push (ch3);
1238 this._CharStack.push (ch2);
1239 return {type: "DELIM", value: ch};
1240 }
1241 } else {
1242 if (ch2.length > 0) this._CharStack.push (ch2);
1243 return {type: "DELIM", value: "ch"};
1244 }
1245 } else if (ch.length > 0) {
1246 return {type: "DELIM", value: ch};
1247 } else {
1248 break X;
1249 }
1250 } /* X */
1251 return null;
1252 };
1253
1254 /**
1255 Unescapes the next escaped sequence. If the next characters
1256 are not a sequence expected after the |\| that introduces an escape
1257 sequence, then an empty string is returned.
1258
1259 @param allowNL If |true|, a line break sequence is accepted as
1260 an escaped sequence. Otherwise, such sequence will
1261 result in returning an empty string.
1262 */
1263 SimpleParser.prototype._GetUnescapedChar =
1264 function (allowNL) {
1265 /* Introducing |REVERSE SOLIDUS| character is already read */
1266 var ch3 = this._PopChar ();
1267 if (ch3.match (/^[0-9A-Fa-f]/)) {
1268 var cp = ch3;
1269 QF: for (var i = 1; i < 6; i++) {
1270 var ch4 = this._PopChar ();
1271 if (ch4.match (/^[0-9A-Fa-f]/)) {
1272 cp += ch4;
1273 } else {
1274 this._CharStack.push (ch4);
1275 break QF;
1276 }
1277 }
1278
1279 /* Following white space */
1280 var ch4 = this._PopChar ();
1281 if (ch4 == "\u0020" || ch4 == "\u000A" ||
1282 ch4 == "\u000C" || ch4 == "\u0009") {
1283 //
1284 } else if (ch4 == "\u000D") {
1285 ch4 = this._PopChar ();
1286 if (ch4 == "\u000A") {
1287 //
1288 } else if (ch4.length > 0) {
1289 this._CharStack.push (ch4);
1290 }
1291 } else if (ch4.length > 0) {
1292 this._CharStack.push (ch4);
1293 }
1294
1295 var code = parseInt (cp, 16);
1296 if (code < 0x10000) {
1297 return String.fromCharCode (code);
1298 } else {
1299 code -= 0x10000;
1300 return String.fromCharCode (0xD800 | ((code >> 10) % 0x10000),
1301 0xDC00 | (code % 0x10000));
1302 }
1303 } else if (ch3 == "\u000D" || ch3 == "\u000A" || ch3 == "\u000C") {
1304 if (allowNL) {
1305 if (ch3 == "\u000D") {
1306 var ch4 = this._PopChar ();
1307 if (ch4 == "\u000A") {
1308 return ch3 + ch4;
1309 } else if (ch4.length > 0) {
1310 this._CharStack.push (ch4);
1311 }
1312 } else {
1313 return ch3;
1314 }
1315 } else {
1316 this._CharStack.push (ch3);
1317 return "";
1318 }
1319 } else if (ch3.length > 0) {
1320 return ch3;
1321 } else { /* Invalid */
1322 return "";
1323 }
1324 };
1325
1326 /**
1327 Pops the next character.
1328 */
1329 SimpleParser.prototype._PopChar = function () {
1330 var nextChar = this._CharStack.pop ();
1331 if (nextChar) {
1332 return nextChar;
1333 }
1334 var ch = this._String.charAt (this._CurrentCharPos);
1335 if (ch.length > 0) {
1336 this._CurrentCharPos++;
1337 var cc = ch.charCodeAt (0);
1338 if (0xD800 <= cc && cc <= 0xDBFF) {
1339 var cn = this._String.charAt (this._CurrentCharPos);
1340 if (cn.length > 0) {
1341 var cnc = cn.charCodeAt (0);
1342 if (0xDC00 <= cnc && cnc <= 0xDFFF) {
1343 this._CurrentCharPos++;
1344 return ch + cn;
1345 }
1346 }
1347 }
1348 }
1349 return ch;
1350 };
1351
1352 /* Revision: $Date: 2007/12/30 03:09:38 $ */
1353
1354 /* ***** BEGIN LICENSE BLOCK *****
1355 * Copyright 2005 Wakaba <w@suika.fam.cx>. All rights reserved.
1356 *
1357 * This program is free software; you can redistribute it and/or
1358 * modify it under the same terms as Perl itself.
1359 *
1360 * Alternatively, the contents of this file may be used
1361 * under the following terms (the "MPL/GPL/LGPL"),
1362 * in which case the provisions of the MPL/GPL/LGPL are applicable instead
1363 * of those above. If you wish to allow use of your version of this file only
1364 * under the terms of the MPL/GPL/LGPL, and not to allow others to
1365 * use your version of this file under the terms of the Perl, indicate your
1366 * decision by deleting the provisions above and replace them with the notice
1367 * and other provisions required by the MPL/GPL/LGPL. If you do not delete
1368 * the provisions above, a recipient may use your version of this file under
1369 * the terms of any one of the Perl or the MPL/GPL/LGPL.
1370 *
1371 * "MPL/GPL/LGPL":
1372 *
1373 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
1374 *
1375 * The contents of this file are subject to the Mozilla Public License Version
1376 * 1.1 (the "License"); you may not use this file except in compliance with
1377 * the License. You may obtain a copy of the License at
1378 * <http://www.mozilla.org/MPL/>
1379 *
1380 * Software distributed under the License is distributed on an "AS IS" basis,
1381 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
1382 * for the specific language governing rights and limitations under the
1383 * License.
1384 *
1385 * The Original Code is BIDOM code.
1386 *
1387 * The Initial Developer of the Original Code is Wakaba.
1388 * Portions created by the Initial Developer are Copyright (C) 2005
1389 * the Initial Developer. All Rights Reserved.
1390 *
1391 * Contributor(s):
1392 * Wakaba <w@suika.fam.cx>
1393 *
1394 * Alternatively, the contents of this file may be used under the terms of
1395 * either the GNU General Public License Version 2 or later (the "GPL"), or
1396 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
1397 * in which case the provisions of the GPL or the LGPL are applicable instead
1398 * of those above. If you wish to allow use of your version of this file only
1399 * under the terms of either the GPL or the LGPL, and not to allow others to
1400 * use your version of this file under the terms of the MPL, indicate your
1401 * decision by deleting the provisions above and replace them with the notice
1402 * and other provisions required by the LGPL or the GPL. If you do not delete
1403 * the provisions above, a recipient may use your version of this file under
1404 * the terms of any one of the MPL, the GPL or the LGPL.
1405 *
1406 * ***** END LICENSE BLOCK ***** */

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24