root/lang/actionscript/ascss/src/css/ASCSS.asy @ 9972

Revision 9972, 66.8 kB (checked in by gyuque, 5 years ago)

ascss: updated test

Line 
1%{
2/*
3 *  Copyright (C) 2002-2003 Lars Knoll (knoll@kde.org)
4 *  Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
5 *  Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
6 *
7 *  This library is free software; you can redistribute it and/or
8 *  modify it under the terms of the GNU Lesser General Public
9 *  License as published by the Free Software Foundation; either
10 *  version 2 of the License, or (at your option) any later version.
11 *
12 *  This library is distributed in the hope that it will be useful,
13 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 *  Lesser General Public License for more details.
16 *
17 *  You should have received a copy of the GNU Lesser General Public
18 *  License along with this library; if not, write to the Free Software
19 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20 *
21 */
22
23package css
24{
25        public class ASCSS
26        {
27                private var mParser:ASCSSParser;
28                private var mSheet:StyleList;
29
30                function ASCSS(aSrc:String, aDebugOut:Object = null)
31                {
32                        mSheet = new StyleList(null);
33                        var parser:ASCSSParser = new ASCSSParser(mSheet, aDebugOut);
34                        var lx:CSSLexer = new CSSLexer(aSrc, parser);
35                        parser.lexer = lx;
36
37                        mParser = parser;
38                }
39
40                public function set propertyExtension(x:IPropertyExtension):void
41                {
42                        mParser.propertyExtension = x;
43                }
44
45                public function get sheet():StyleList
46                {
47                        return mSheet;
48                }
49
50                public function parse():void
51                {
52                        mParser.yyparse();
53
54                        if (mParser.inShorthand)
55                                throw "parser is still in shorthand scope!";
56                }
57        }
58}
59%}
60
61%union {
62    bool Boolean;
63    char character;
64    int integer;
65    double number;
66    ParseString string;
67
68    CSSRule* rule;
69    CSSRuleList* ruleList;
70    CSSSelector* selector;
71    CSSSelector::Relation relation;
72    MediaList* mediaList;
73    MediaQuery* mediaQuery;
74    MediaQuery::Restrictor mediaQueryRestrictor;
75    MediaQueryExp* mediaQueryExp;
76    ParseValue value;
77    ValueList* valueList;
78    Vector<MediaQueryExp*>* mediaQueryExpList;
79}
80
81%expect 41
82
83%left UNIMPORTANT_TOK
84
85%token WHITESPACE SGML_CD
86
87%token INCLUDES
88%token DASHMATCH
89%token BEGINSWITH
90%token ENDSWITH
91%token CONTAINS
92
93%token <string> STRING
94%right <string> IDENT
95%token <string> NTH
96
97%nonassoc <string> HEX
98%nonassoc <string> IDSEL
99%nonassoc ':'
100%nonassoc '.'
101%nonassoc '['
102%nonassoc <string> '*'
103%nonassoc error
104%left '|'
105
106%token IMPORT_SYM
107%token PAGE_SYM
108%token MEDIA_SYM
109%token FONT_FACE_SYM
110%token CHARSET_SYM
111%token NAMESPACE_SYM
112%token WEBKIT_RULE_SYM
113%token WEBKIT_DECLS_SYM
114%token WEBKIT_VALUE_SYM
115%token WEBKIT_MEDIAQUERY_SYM
116
117%token IMPORTANT_SYM
118%token MEDIA_ONLY
119%token MEDIA_NOT
120%token MEDIA_AND
121
122%token <number> QEMS
123%token <number> EMS
124%token <number> EXS
125%token <number> PXS
126%token <number> CMS
127%token <number> MMS
128%token <number> INS
129%token <number> PTS
130%token <number> PCS
131%token <number> DEGS
132%token <number> RADS
133%token <number> GRADS
134%token <number> MSECS
135%token <number> SECS
136%token <number> HERZ
137%token <number> KHERZ
138%token <string> DIMEN
139%token <number> PERCENTAGE
140%token <number> FLOATTOKEN
141%token <number> INTEGER
142
143%token <string> URI
144%token <string> FUNCTION
145%token <string> NOTFUNCTION
146
147%token <string> UNICODERANGE
148
149%type <relation> combinator
150
151%type <rule> charset
152%type <rule> ruleset
153%type <rule> valid_rule_or_import
154%type <rule> media
155%type <rule> import
156%type <rule> page
157%type <rule> font_face
158%type <rule> invalid_rule
159%type <rule> invalid_at
160%type <rule> invalid_import
161%type <rule> rule
162%type <rule> valid_rule
163
164%type <string> maybe_ns_prefix
165
166%type <string> namespace_selector
167
168%type <string> string_or_uri
169%type <string> ident_or_string
170%type <string> medium
171%type <string> hexcolor
172
173%type <string> media_feature
174%type <mediaList> media_list
175%type <mediaList> maybe_media_list
176%type <mediaQuery> media_query
177%type <mediaQueryRestrictor> maybe_media_restrictor
178%type <valueList> maybe_media_value
179%type <mediaQueryExp> media_query_exp
180%type <mediaQueryExpList> media_query_exp_list
181%type <mediaQueryExpList> maybe_media_query_exp_list
182
183%type <ruleList> ruleset_list
184
185%type <integer> property
186
187%type <selector> specifier
188%type <selector> specifier_list
189%type <selector> simple_selector
190%type <selector> selector
191%type <selector> selector_list
192%type <selector> selector_with_trailing_whitespace
193%type <selector> class
194%type <selector> attrib
195%type <selector> pseudo
196
197%type <boolean> declaration_list
198%type <boolean> decl_list
199%type <boolean> declaration
200
201%type <boolean> prio
202
203%type <integer> match
204%type <integer> unary_operator
205%type <character> operator
206
207%type <valueList> expr
208%type <value> term
209%type <value> unary_term
210%type <value> function
211
212%type <string> element_name
213%type <string> attr_name
214
215%%
216
217stylesheet:
218    maybe_charset maybe_sgml import_list namespace_list rule_list
219  | webkit_rule maybe_space
220  | webkit_decls maybe_space
221  | webkit_value maybe_space
222  | webkit_mediaquery maybe_space
223  ;
224
225valid_rule_or_import:
226    valid_rule
227  | import
228  ;
229
230webkit_rule:
231    WEBKIT_RULE_SYM '{' maybe_space valid_rule_or_import maybe_space '}' {
232/*
233        static_cast<CSSParser*>(parser)->rule = $4;
234*/
235    }
236;
237
238webkit_decls:
239    WEBKIT_DECLS_SYM '{' maybe_space declaration_list '}' {
240        /* can be empty */
241    }
242;
243
244webkit_value:
245    WEBKIT_VALUE_SYM '{' maybe_space expr '}' {
246/*
247        CSSParser* p = static_cast<CSSParser*>(parser);
248        if ($4) {
249            p->valueList = p->sinkFloatingValueList($4);
250            int oldParsedProperties = p->numParsedProperties;
251            if (!p->parseValue(p->id, p->important))
252                p->rollbackLastProperties(p->numParsedProperties - oldParsedProperties);
253            delete p->valueList;
254            p->valueList = 0;
255        }
256*/
257    }
258;
259
260webkit_mediaquery:
261     WEBKIT_MEDIAQUERY_SYM WHITESPACE maybe_space media_query '}' {
262/*
263         CSSParser* p = static_cast<CSSParser*>(parser);
264         p->mediaQuery = p->sinkFloatingMediaQuery($4);
265*/
266     }
267;
268
269maybe_space:
270    /* empty */ %prec UNIMPORTANT_TOK
271  | maybe_space WHITESPACE
272  ;
273
274maybe_sgml:
275    /* empty */
276  | maybe_sgml SGML_CD
277  | maybe_sgml WHITESPACE
278  ;
279
280maybe_charset:
281   /* empty */
282  | charset {
283  }
284;
285
286charset:
287  CHARSET_SYM maybe_space STRING maybe_space ';' {
288/*
289
290     CSSParser* p = static_cast<CSSParser*>(parser);
291     $$ = static_cast<CSSParser*>(parser)->createCharsetRule($3);
292     if ($$ && p->styleElement && p->styleElement->isCSSStyleSheet())
293         p->styleElement->append($$);
294*/
295  }
296  | CHARSET_SYM error invalid_block {
297  }
298  | CHARSET_SYM error ';' {
299  }
300;
301
302import_list:
303 /* empty */
304 | import_list import maybe_sgml {
305/*
306     CSSParser* p = static_cast<CSSParser*>(parser);
307     if ($2 && p->styleElement && p->styleElement->isCSSStyleSheet())
308         p->styleElement->append($2);
309*/
310 }
311 ;
312
313namespace_list:
314/* empty */
315| namespace_list namespace maybe_sgml
316;
317
318rule_list:
319   /* empty */
320 | rule_list rule maybe_sgml {
321        if ($2 != null && styleElement != null /* && styleElement.isCSSStyleSheet() */)
322                styleElement.append($2);
323 }
324 ;
325
326valid_rule:
327    ruleset
328  | media
329  | page
330  | font_face
331  ;
332
333rule:
334    valid_rule
335  | invalid_rule
336  | invalid_at
337  | invalid_import
338  ;
339
340import:
341    IMPORT_SYM maybe_space string_or_uri maybe_space maybe_media_list ';' {
342//        $$ = static_cast<CSSParser*>(parser)->createImportRule($3, $5);
343    }
344  | IMPORT_SYM error invalid_block {
345//        $$ = 0;
346    }
347  | IMPORT_SYM error ';' {
348//        $$ = 0;
349    }
350  ;
351
352namespace:
353NAMESPACE_SYM maybe_space maybe_ns_prefix string_or_uri maybe_space ';' {
354/*
355    CSSParser* p = static_cast<CSSParser*>(parser);
356    if (p->styleElement && p->styleElement->isCSSStyleSheet())
357        static_cast<CSSStyleSheet*>(p->styleElement)->addNamespace(p, $3, $4);
358*/
359}
360| NAMESPACE_SYM error invalid_block
361| NAMESPACE_SYM error ';'
362;
363
364maybe_ns_prefix:
365/* empty */ {
366//      $$.characters = 0;
367}
368| IDENT WHITESPACE {
369// $$ = $1;
370}
371;
372
373string_or_uri:
374STRING
375| URI
376;
377
378media_feature:
379    IDENT maybe_space {
380//        $$ = $1;
381    }
382    ;
383
384maybe_media_value:
385    /*empty*/ {
386//        $$ = 0;
387    }
388    | ':' maybe_space expr maybe_space {
389//        $$ = $3;
390    }
391    ;
392
393media_query_exp:
394    MEDIA_AND maybe_space '(' maybe_space media_feature maybe_space maybe_media_value ')' maybe_space {
395/*
396        $5.lower();
397        $$ = static_cast<CSSParser*>(parser)->createFloatingMediaQueryExp($5, $7);
398*/
399    }
400    ;
401
402media_query_exp_list:
403    media_query_exp {
404/*
405        CSSParser* p = static_cast<CSSParser*>(parser);
406        $$ = p->createFloatingMediaQueryExpList();
407        $$->append(p->sinkFloatingMediaQueryExp($1));
408*/
409    }
410    | media_query_exp_list media_query_exp {
411/*
412        $$ = $1;
413        $$->append(static_cast<CSSParser*>(parser)->sinkFloatingMediaQueryExp($2));
414*/
415    }
416    ;
417
418maybe_media_query_exp_list:
419    /*empty*/ {
420//        $$ = static_cast<CSSParser*>(parser)->createFloatingMediaQueryExpList();
421    }
422    | media_query_exp_list
423    ;
424
425maybe_media_restrictor:
426    /*empty*/ {
427//        $$ = MediaQuery::None;
428    }
429    | MEDIA_ONLY {
430//        $$ = MediaQuery::Only;
431    }
432    | MEDIA_NOT {
433//        $$ = MediaQuery::Not;
434    }
435    ;
436
437media_query:
438    maybe_media_restrictor maybe_space medium maybe_media_query_exp_list {
439/*
440        CSSParser* p = static_cast<CSSParser*>(parser);
441        $3.lower();
442        $$ = p->createFloatingMediaQuery($1, $3, p->sinkFloatingMediaQueryExpList($4));
443*/
444    }
445    ;
446
447maybe_media_list:
448     /* empty */ {
449//        $$ = static_cast<CSSParser*>(parser)->createMediaList();
450     }
451     | media_list
452     ;
453
454media_list:
455    media_query {
456/*
457        CSSParser* p = static_cast<CSSParser*>(parser);
458        $$ = p->createMediaList();
459        $$->appendMediaQuery(p->sinkFloatingMediaQuery($1));
460*/
461    }
462    | media_list ',' maybe_space media_query {
463/*
464        $$ = $1;
465        if ($$)
466            $$->appendMediaQuery(static_cast<CSSParser*>(parser)->sinkFloatingMediaQuery($4));
467*/
468    }
469    | media_list error {
470/*
471        $$ = 0;
472*/
473    }
474    ;
475
476media:
477    MEDIA_SYM maybe_space media_list '{' maybe_space ruleset_list '}' {
478//        $$ = static_cast<CSSParser*>(parser)->createMediaRule($3, $6);
479    }
480    | MEDIA_SYM maybe_space '{' maybe_space ruleset_list '}' {
481//        $$ = static_cast<CSSParser*>(parser)->createMediaRule(0, $5);
482    }
483    ;
484
485ruleset_list:
486    /* empty */ {
487                $$ = null;
488        }
489    | ruleset_list ruleset maybe_space {
490/*
491        $$ = $1;
492        if ($2) {
493            if (!$$)
494                $$ = static_cast<CSSParser*>(parser)->createRuleList();
495            $$->append($2);
496        }
497*/
498    }
499    ;
500
501medium:
502  IDENT maybe_space {
503//      $$ = $1;
504  }
505  ;
506
507/*
508page:
509    PAGE_SYM maybe_space IDENT? pseudo_page? maybe_space
510    '{' maybe_space declaration [ ';' maybe_space declaration ]* '}' maybe_space
511  ;
512
513pseudo_page
514  : ':' IDENT
515  ;
516*/
517
518page:
519    PAGE_SYM error invalid_block {
520//      $$ = 0;
521    }
522  | PAGE_SYM error ';' {
523//      $$ = 0;
524    }
525    ;
526
527font_face:
528    FONT_FACE_SYM maybe_space
529    '{' maybe_space declaration_list '}'  maybe_space {
530//        $$ = static_cast<CSSParser*>(parser)->createFontFaceRule();
531    }
532    | FONT_FACE_SYM error invalid_block {
533//      $$ = 0;
534    }
535    | FONT_FACE_SYM error ';' {
536//      $$ = 0;
537    }
538;
539
540combinator:
541    '+' maybe_space {
542// $$ = CSSSelector::DirectAdjacent;
543  }
544  | '~' maybe_space {
545// $$ = CSSSelector::IndirectAdjacent;
546  }
547  | '>' maybe_space {
548// $$ = CSSSelector::Child;
549  }
550  ;
551
552unary_operator:
553    '-' {
554 $$ = -1;
555  }
556  | '+' {
557 $$ = 1;
558  }
559  ;
560
561ruleset:
562    selector_list '{' maybe_space declaration_list '}' {
563                $$ = createStyleRule($1);
564//        $$ = static_cast<CSSParser*>(parser)->createStyleRule($1);
565    }
566  ;
567
568selector_list:
569    selector %prec UNIMPORTANT_TOK {
570        $$ = $1;
571    }
572    | selector_list ',' maybe_space selector %prec UNIMPORTANT_TOK {
573        if ($1 != null && $4 != null) {
574            $$ = $1;
575            $$.append($4);
576        } else
577            $$ = null;
578    }
579  | selector_list error {
580        $$ = null;
581    }
582   ;
583
584selector_with_trailing_whitespace:
585    selector WHITESPACE {
586        $$ = $1;
587    }
588    ;
589
590selector:
591    simple_selector {
592        $$ = $1;
593    }
594    | selector_with_trailing_whitespace
595    {
596        $$ = $1;
597    }
598    | selector_with_trailing_whitespace simple_selector
599    {
600                $$ = $2;
601                if ($1 == null)
602                        $$ = null;
603                else if ($$ != null)
604                {
605                        var endSel:CSSSelector = $$ as CSSSelector;
606                        while (endSel.mTagHistory != null)
607                                endSel = endSel.mTagHistory;
608
609                        endSel.mRelation = CSSSelector.REL_Descendant;
610                        endSel.mTagHistory = $1;
611                }
612
613/*
614        $$ = $2;
615        if (!$1)
616            $$ = 0;
617        else if ($$) {
618            CSSParser* p = static_cast<CSSParser*>(parser);
619            CSSSelector* end = $$;
620            while (end->m_tagHistory)
621                end = end->m_tagHistory;
622            end->m_relation = CSSSelector::Descendant;
623            end->m_tagHistory = p->sinkFloatingSelector($1);
624            if (Document* doc = p->document())
625                doc->setUsesDescendantRules(true);
626        }
627*/
628    }
629    | selector combinator simple_selector {
630/*
631        $$ = $3;
632        if (!$1)
633            $$ = 0;
634        else if ($$) {
635            CSSParser* p = static_cast<CSSParser*>(parser);
636            CSSSelector* end = $$;
637            while (end->m_tagHistory)
638                end = end->m_tagHistory;
639            end->m_relation = $2;
640            end->m_tagHistory = p->sinkFloatingSelector($1);
641            if ($2 == CSSSelector::Child) {
642                if (Document* doc = p->document())
643                    doc->setUsesDescendantRules(true);
644            } else if ($2 == CSSSelector::DirectAdjacent || $2 == CSSSelector::IndirectAdjacent) {
645                if (Document* doc = p->document())
646                    doc->setUsesSiblingRules(true);
647            }
648        }
649*/
650    }
651    | selector error {
652//        $$ = 0;
653    }
654    ;
655
656namespace_selector:
657    /* empty */ '|' {
658// $$.characters = 0; $$.length = 0;
659    }
660    | '*' '|' {
661// static UChar star = '*'; $$.characters = &star; $$.length = 1;
662    }
663    | IDENT '|' {
664// $$ = $1;
665    }
666;
667   
668simple_selector:
669    element_name {
670                $$ = new CSSSelector();
671                $$.mTag = new QualifiedName(null, $1.str, defaultNamespace);
672    }
673    | element_name specifier_list {
674        $$ = $2;
675        if ($$) {
676            $$.mTag = new QualifiedName(null, $1.str, defaultNamespace);
677        }
678    }
679    | specifier_list {
680        $$ = $1;
681        if ($$ != null && defaultNamespace != '*')
682            $$.mTag = new QualifiedName(null, '*', defaultNamespace);
683    }
684    | namespace_selector element_name {
685/*
686        AtomicString namespacePrefix = $1;
687        CSSParser* p = static_cast<CSSParser*>(parser);
688        $$ = p->createFloatingSelector();
689        if (p->styleElement && p->styleElement->isCSSStyleSheet()) {
690            $$->m_tag = QualifiedName(namespacePrefix, $2,
691                                      static_cast<CSSStyleSheet*>(p->styleElement)->determineNamespace(namespacePrefix));
692        } else // FIXME: Shouldn't this case be an error?
693            $$->m_tag = QualifiedName(nullAtom, $2, p->defaultNamespace);
694*/
695    }
696    | namespace_selector element_name specifier_list {
697/*
698        $$ = $3;
699        if ($$) {
700            AtomicString namespacePrefix = $1;
701            CSSParser* p = static_cast<CSSParser*>(parser);
702            if (p->styleElement && p->styleElement->isCSSStyleSheet()) {
703                $$->m_tag = QualifiedName(namespacePrefix, $2,
704                                          static_cast<CSSStyleSheet*>(p->styleElement)->determineNamespace(namespacePrefix));
705            } else // FIXME: Shouldn't this case be an error?
706                $$->m_tag = QualifiedName(nullAtom, $2, p->defaultNamespace);
707        }
708*/
709    }
710    | namespace_selector specifier_list {
711/*
712        $$ = $2;
713        if ($$) {
714            AtomicString namespacePrefix = $1;
715            CSSParser* p = static_cast<CSSParser*>(parser);
716            if (p->styleElement && p->styleElement->isCSSStyleSheet())
717                $$->m_tag = QualifiedName(namespacePrefix,
718                                          starAtom,
719                                          static_cast<CSSStyleSheet*>(p->styleElement)->determineNamespace(namespacePrefix));
720        }
721*/
722    }
723  ;
724
725element_name:
726    IDENT {
727        var str:ParseString = new ParseString($1);
728                if (parsingHTMLDocument)
729            str.lower();
730        $$ = str;
731    }
732    | '*' {
733                $$ = new ParseString("*");
734    }
735  ;
736
737specifier_list:
738    specifier {
739        $$ = $1;
740    }
741    | specifier_list specifier {
742        if ($2 == null)
743            $$ = null;
744        else if ($1) {
745            $$ = $1;
746            var end:CSSSelector = $1;
747            while (end.mTagHistory != null)
748                end = end.mTagHistory;
749            end.mRelation = CSSSelector.REL_SubSelector;
750            end.mTagHistory = $2;
751        }
752    }
753    | specifier_list error {
754        $$ = null;
755    }
756;
757
758specifier:
759    IDSEL {
760/*
761        CSSParser* p = static_cast<CSSParser*>(parser);
762        $$ = p->createFloatingSelector();
763        $$->m_match = CSSSelector::Id;
764        if (!p->strict)
765            $1.lower();
766        $$->m_attr = idAttr;
767        $$->m_value = $1;
768*/
769    }
770  | HEX {
771/*
772        if ($1.characters[0] >= '0' && $1.characters[0] <= '9') {
773            $$ = 0;
774        } else {
775            CSSParser* p = static_cast<CSSParser*>(parser);
776            $$ = p->createFloatingSelector();
777            $$->m_match = CSSSelector::Id;
778            if (!p->strict)
779                $1.lower();
780            $$->m_attr = idAttr;
781            $$->m_value = $1;
782        }
783*/
784    }
785  | class
786  | attrib
787  | pseudo
788    ;
789
790class:
791    '.' IDENT {
792                $$ = new CSSSelector();
793                var str_clsid:ParseString = new ParseString($2);
794                $$.mMatch = CSSSelector.MATCH_Class;
795                if (!mStrict)
796                        str_clsid.lower();
797                $$.mAttr  = QualifiedName.classAttr;
798                $$.mValue = str_clsid.str;
799    }
800  ;
801
802attr_name:
803    IDENT maybe_space {
804/*
805        ParseString& str = $1;
806        CSSParser* p = static_cast<CSSParser*>(parser);
807        Document* doc = p->document();
808        if (doc && doc->isHTMLDocument())
809            str.lower();
810        $$ = str;
811*/
812    }
813    ;
814
815attrib:
816    '[' maybe_space attr_name ']' {
817/*
818        $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
819        $$->m_attr = QualifiedName(nullAtom, $3, nullAtom);
820        $$->m_match = CSSSelector::Set;
821*/
822    }
823    | '[' maybe_space attr_name match maybe_space ident_or_string maybe_space ']' {
824/*
825        $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
826        $$->m_attr = QualifiedName(nullAtom, $3, nullAtom);
827        $$->m_match = (CSSSelector::Match)$4;
828        $$->m_value = $6;
829*/
830    }
831    | '[' maybe_space namespace_selector attr_name ']' {
832/*
833        AtomicString namespacePrefix = $3;
834        CSSParser* p = static_cast<CSSParser*>(parser);
835        $$ = p->createFloatingSelector();
836        $$->m_attr = QualifiedName(namespacePrefix, $4,
837                                   static_cast<CSSStyleSheet*>(p->styleElement)->determineNamespace(namespacePrefix));
838        $$->m_match = CSSSelector::Set;
839*/
840    }
841    | '[' maybe_space namespace_selector attr_name match maybe_space ident_or_string maybe_space ']' {
842/*
843        AtomicString namespacePrefix = $3;
844        CSSParser* p = static_cast<CSSParser*>(parser);
845        $$ = p->createFloatingSelector();
846        $$->m_attr = QualifiedName(namespacePrefix, $4,
847                                   static_cast<CSSStyleSheet*>(p->styleElement)->determineNamespace(namespacePrefix));
848        $$->m_match = (CSSSelector::Match)$5;
849        $$->m_value = $7;
850*/
851    }
852  ;
853
854match:
855    '=' {
856//        $$ = CSSSelector::Exact;
857    }
858    | INCLUDES {
859//        $$ = CSSSelector::List;
860    }
861    | DASHMATCH {
862//        $$ = CSSSelector::Hyphen;
863    }
864    | BEGINSWITH {
865//        $$ = CSSSelector::Begin;
866    }
867    | ENDSWITH {
868//        $$ = CSSSelector::End;
869    }
870    | CONTAINS {
871//        $$ = CSSSelector::Contain;
872    }
873    ;
874
875ident_or_string:
876    IDENT
877  | STRING
878    ;
879
880pseudo:
881    ':' IDENT {
882                $$ = new CSSSelector();
883                $$.mMatch = CSSSelector.MATCH_PseudoClass;
884                var str_pcls:ParseString = new ParseString($2);
885                str_pcls.lower();
886                $$.mValue = str_pcls.str;
887                var pseudotype:int = $$.pseudoType;
888/*
889        $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
890        $$->m_match = CSSSelector::PseudoClass;
891        $2.lower();
892        $$->m_value = $2;
893        CSSSelector::PseudoType type = $$->pseudoType();
894        if (type == CSSSelector::PseudoUnknown)
895            $$ = 0;
896        else if (type == CSSSelector::PseudoEmpty ||
897                 type == CSSSelector::PseudoFirstChild ||
898                 type == CSSSelector::PseudoFirstOfType ||
899                 type == CSSSelector::PseudoLastChild ||
900                 type == CSSSelector::PseudoLastOfType ||
901                 type == CSSSelector::PseudoOnlyChild ||
902                 type == CSSSelector::PseudoOnlyOfType) {
903            CSSParser* p = static_cast<CSSParser*>(parser);
904            Document* doc = p->document();
905            if (doc)
906                doc->setUsesSiblingRules(true);
907        } else if (type == CSSSelector::PseudoFirstLine) {
908            CSSParser* p = static_cast<CSSParser*>(parser);
909            if (Document* doc = p->document())
910                doc->setUsesFirstLineRules(true);
911        }
912*/
913    }
914    | ':' ':' IDENT {
915/*
916        $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
917        $$->m_match = CSSSelector::PseudoElement;
918        $3.lower();
919        $$->m_value = $3;
920        CSSSelector::PseudoType type = $$->pseudoType();
921        if (type == CSSSelector::PseudoUnknown)
922            $$ = 0;
923        else if (type == CSSSelector::PseudoFirstLine) {
924            CSSParser* p = static_cast<CSSParser*>(parser);
925            if (Document* doc = p->document())
926                doc->setUsesFirstLineRules(true);
927        }
928*/
929    }
930    // used by :nth-*(ax+b)
931    | ':' FUNCTION NTH ')' {
932/*
933        CSSParser *p = static_cast<CSSParser*>(parser);
934        $$ = p->createFloatingSelector();
935        $$->m_match = CSSSelector::PseudoClass;
936        $$->m_argument = $3;
937        $$->m_value = $2;
938        CSSSelector::PseudoType type = $$->pseudoType();
939        if (type == CSSSelector::PseudoUnknown)
940            $$ = 0;
941        else if (type == CSSSelector::PseudoNthChild ||
942                 type == CSSSelector::PseudoNthOfType ||
943                 type == CSSSelector::PseudoNthLastChild ||
944                 type == CSSSelector::PseudoNthLastOfType) {
945            if (p->document())
946                p->document()->setUsesSiblingRules(true);
947        }
948*/
949    }
950    // used by :nth-*
951    | ':' FUNCTION INTEGER ')' {
952/*
953        CSSParser *p = static_cast<CSSParser*>(parser);
954        $$ = p->createFloatingSelector();
955        $$->m_match = CSSSelector::PseudoClass;
956        $$->m_argument = String::number($3);
957        $$->m_value = $2;
958        CSSSelector::PseudoType type = $$->pseudoType();
959        if (type == CSSSelector::PseudoUnknown)
960            $$ = 0;
961        else if (type == CSSSelector::PseudoNthChild ||
962                 type == CSSSelector::PseudoNthOfType ||
963                 type == CSSSelector::PseudoNthLastChild ||
964                 type == CSSSelector::PseudoNthLastOfType) {
965            if (p->document())
966                p->document()->setUsesSiblingRules(true);
967        }
968*/
969    }
970    // used by :nth-*(odd/even) and :lang
971    | ':' FUNCTION IDENT ')' {
972/*
973        CSSParser *p = static_cast<CSSParser*>(parser);
974        $$ = p->createFloatingSelector();
975        $$->m_match = CSSSelector::PseudoClass;
976        $$->m_argument = $3;
977        $2.lower();
978        $$->m_value = $2;
979        CSSSelector::PseudoType type = $$->pseudoType();
980        if (type == CSSSelector::PseudoUnknown)
981            $$ = 0;
982        else if (type == CSSSelector::PseudoNthChild ||
983                 type == CSSSelector::PseudoNthOfType ||
984                 type == CSSSelector::PseudoNthLastChild ||
985                 type == CSSSelector::PseudoNthLastOfType) {
986            if (p->document())
987                p->document()->setUsesSiblingRules(true);
988        }
989*/
990    }
991    // used by :not
992    | ':' NOTFUNCTION maybe_space simple_selector maybe_space ')' {
993/*
994        if (!$4)
995            $$ = 0;
996        else {
997            CSSParser* p = static_cast<CSSParser*>(parser);
998            $$ = p->createFloatingSelector();
999            $$->m_match = CSSSelector::PseudoClass;
1000            $$->m_simpleSelector = p->sinkFloatingSelector($4);
1001            $2.lower();
1002            $$->m_value = $2;
1003        }
1004*/
1005    }
1006  ;
1007
1008declaration_list:
1009    declaration {
1010        $$ = $1;
1011    }
1012    | decl_list declaration {
1013        $$ = $1;
1014        if ( $2 )
1015            $$ = $2;
1016    }
1017    | decl_list {
1018        $$ = $1;
1019    }
1020    | error invalid_block_list error {
1021        $$ = false;
1022    }
1023    | error {
1024        $$ = false;
1025    }
1026    | decl_list error {
1027        $$ = $1;
1028    }
1029    ;
1030
1031decl_list:
1032    declaration ';' maybe_space {
1033        $$ = $1;
1034    }
1035    | declaration invalid_block_list ';' maybe_space {
1036        $$ = false;
1037    }
1038    | error ';' maybe_space {
1039        $$ = false;
1040    }
1041    | error invalid_block_list error ';' maybe_space {
1042        $$ = false;
1043    }
1044    | decl_list declaration ';' maybe_space {
1045        $$ = $1;
1046        if ($2)
1047            $$ = $2;
1048    }
1049    | decl_list error ';' maybe_space {
1050        $$ = $1;
1051    }
1052    | decl_list error invalid_block_list error ';' maybe_space {
1053        $$ = $1;
1054    }
1055    ;
1056
1057declaration:
1058    property ':' maybe_space expr prio {
1059
1060                $$ = false;
1061                if ($1 && $4)
1062                {
1063                        currentValueList = $4;
1064                        $$ = parseValue($1, $5);
1065                        mValueList = null;
1066                }
1067
1068/*
1069        $$ = false;
1070        CSSParser* p = static_cast<CSSParser*>(parser);
1071        if ($1 && $4) {
1072            p->valueList = p->sinkFloatingValueList($4);
1073            int oldParsedProperties = p->numParsedProperties;
1074            $$ = p->parseValue($1, $5);
1075            if (!$$)
1076                p->rollbackLastProperties(p->numParsedProperties - oldParsedProperties);
1077            delete p->valueList;
1078            p->valueList = 0;
1079        }
1080*/
1081    }
1082    |
1083    property error {
1084        $$ = false;
1085    }
1086    |
1087    property ':' maybe_space error expr prio {
1088        /* The default movable type template has letter-spacing: .none;  Handle this by looking for
1089        error tokens at the start of an expr, recover the expr and then treat as an error, cleaning
1090        up and deleting the shifted expr.  */
1091        $$ = false;
1092    }
1093    |
1094    IMPORTANT_SYM maybe_space {
1095        /* Handle this case: div { text-align: center; !important } Just reduce away the stray !important. */
1096        $$ = false;
1097    }
1098    |
1099    property ':' maybe_space {
1100        /* div { font-family: } Just reduce away this property with no value. */
1101        $$ = false;
1102    }
1103    |
1104    property ':' maybe_space error {
1105        /* if we come across rules with invalid values like this case: p { weight: *; }, just discard the rule */
1106        $$ = false;
1107    }
1108  ;
1109
1110property:
1111    IDENT maybe_space {
1112        $$ = cssPropertyID($1);
1113    }
1114  ;
1115
1116prio:
1117    IMPORTANT_SYM maybe_space {
1118      $$ = true;
1119    }
1120    | /* empty */ {
1121      $$ = false;
1122    }
1123  ;
1124
1125expr:
1126    term {
1127                var vallist:ValueList = new ValueList();
1128                vallist.addValue($1)
1129                $$ = vallist;
1130    }
1131    | expr operator term {
1132                $$ = $1
1133                if ($$ != null) {
1134                        if ($2 != null) {
1135                                var opval:ParseValue = new ParseValue(0, ParseValue.Operator);
1136                                opval.iValue = ($2 == '/') ? ParseValue.OP_SLASH : ParseValue.OP_COMMA;
1137                                $$.addValue(opval);
1138                        }
1139                        $$.addValue($3);
1140                }
1141    }
1142    | expr error {
1143        $$ = null;
1144    }
1145  ;
1146
1147operator:
1148    '/' maybe_space {
1149                $$ = '/';
1150    }
1151  | ',' maybe_space {
1152                $$ = ',';
1153    }
1154  | /* empty */ {
1155                $$ = null;
1156  }
1157  ;
1158
1159term:
1160  unary_term {
1161// $$ = $1;
1162  }
1163  | unary_operator unary_term {
1164// $$ = $2; $$.fValue *= $1;
1165  }
1166  | STRING maybe_space {
1167// $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_STRING;
1168  }
1169  | IDENT maybe_space {
1170        $$ = new ParseValue(cssValueKeywordID($1), CSSPrimitiveValue.CSS_IDENT);
1171        $$.stringVal = new ParseString($1);
1172  }
1173  /* We might need to actually parse the number from a dimension, but we can't just put something that uses $$.string into unary_term. */
1174  | DIMEN maybe_space {
1175// $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_DIMENSION
1176  }
1177  | unary_operator DIMEN maybe_space {
1178// $$.id = 0; $$.string = $2; $$.unit = CSSPrimitiveValue::CSS_DIMENSION
1179  }
1180  | URI maybe_space {
1181// $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_URI;
1182  }
1183  | UNICODERANGE maybe_space {
1184// $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_UNICODE_RANGE
1185  }
1186  | hexcolor {
1187    $$ = new ParseValue(0, CSSPrimitiveValue.CSS_RGBCOLOR);
1188    $$.stringVal = $1
1189  }
1190  | '#' maybe_space {
1191// $$.id = 0; $$.string = ParseString(); $$.unit = CSSPrimitiveValue::CSS_RGBCOLOR;
1192  }
1193  /* Handle error case: "color: #;" */
1194
1195  /* FIXME: according to the specs a function can have a unary_operator in front. I know no case where this makes sense */
1196  | function {
1197//      $$ = $1;
1198  }
1199  | '%' maybe_space {} /* Handle width: %; */
1200  ;
1201
1202unary_term:
1203  INTEGER maybe_space {
1204        $$ = new ParseValue(0, CSSPrimitiveValue.CSS_NUMBER);
1205        $$.fValue = $1;
1206        $$.isInt = true;
1207  }
1208  | FLOATTOKEN maybe_space {
1209        $$ = new ParseValue(0, CSSPrimitiveValue.CSS_NUMBER);
1210        $$.fValue = $1;
1211        $$.isInt = false;
1212  }
1213  | PERCENTAGE maybe_space {
1214        $$ = new ParseValue(0, CSSPrimitiveValue.CSS_PERCENTAGE);
1215        $$.fValue = $1;
1216        $$.isInt = false;
1217  }
1218  | PXS maybe_space {
1219        $$ = new ParseValue(0, CSSPrimitiveValue.CSS_PX);
1220        $$.fValue = $1;
1221  }
1222  | CMS maybe_space {
1223// $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_CM;
1224  }
1225  | MMS maybe_space {
1226// $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_MM;
1227  }
1228  | INS maybe_space {
1229// $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_IN;
1230  }
1231  | PTS maybe_space {
1232// $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PT;
1233  }
1234  | PCS maybe_space {
1235// $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PC;
1236  }
1237  | DEGS maybe_space {
1238        $$ = new ParseValue(0, CSSPrimitiveValue.CSS_DEG);
1239        $$.fValue = $1;
1240  }
1241  | RADS maybe_space {
1242// $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_RAD;
1243  }
1244  | GRADS maybe_space {
1245// $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_GRAD;
1246  }
1247  | MSECS maybe_space {
1248// $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_MS;
1249  }
1250  | SECS maybe_space {
1251// $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_S;
1252  }
1253  | HERZ maybe_space {
1254// $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_HZ;
1255  }
1256  | KHERZ maybe_space {
1257// $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_KHZ;
1258  }
1259  | EMS maybe_space {
1260        $$ = new ParseValue(0, CSSPrimitiveValue.CSS_EMS);
1261        $$.fValue = $1;
1262  }
1263  | QEMS maybe_space {
1264// $$.id = 0; $$.fValue = $1; $$.unit = Value::Q_EMS;
1265  }
1266  | EXS maybe_space {
1267        $$ = new ParseValue(0, CSSPrimitiveValue.CSS_EXS);
1268        $$.fValue = $1;
1269  }
1270  ;
1271
1272
1273function:
1274    FUNCTION maybe_space expr ')' maybe_space {
1275/*
1276        CSSParser* p = static_cast<CSSParser*>(parser);
1277        Function* f = p->createFloatingFunction();
1278        f->name = $1;
1279        f->args = p->sinkFloatingValueList($3);
1280        $$.id = 0;
1281        $$.unit = Value::Function;
1282        $$.function = f;
1283*/
1284    } |
1285    FUNCTION maybe_space error {
1286/*
1287        CSSParser* p = static_cast<CSSParser*>(parser);
1288        Function* f = p->createFloatingFunction();
1289        f->name = $1;
1290        f->args = 0;
1291        $$.id = 0;
1292        $$.unit = Value::Function;
1293        $$.function = f;
1294*/
1295    }
1296    ;
1297/*
1298 * There is a constraint on the color that it must
1299 * have either 3 or 6 hex-digits (i.e., [0-9a-fA-F])
1300 * after the "#"; e.g., "#000" is OK, but "#abcd" is not.
1301 */
1302hexcolor:
1303  HEX maybe_space {
1304   $$ = new ParseString($1);
1305  }
1306  | IDSEL maybe_space {
1307// $$ = $1;
1308  }
1309  ;
1310
1311
1312/* error handling rules */
1313
1314invalid_at:
1315    '@' error invalid_block {
1316//        $$ = 0;
1317    }
1318  | '@' error ';' {
1319//        $$ = 0;
1320    }
1321    ;
1322
1323invalid_import:
1324    import {
1325//        $$ = 0;
1326    }
1327    ;
1328
1329invalid_rule:
1330    error invalid_block {
1331//        $$ = 0;
1332    }
1333/*
1334  Seems like the two rules below are trying too much and violating
1335  http://www.hixie.ch/tests/evil/mixed/csserrorhandling.html
1336
1337  | error ';' {
1338        $$ = 0;
1339    }
1340  | error '}' {
1341        $$ = 0;
1342    }
1343*/
1344    ;
1345
1346invalid_block:
1347    '{' error invalid_block_list error '}'
1348  | '{' error '}'
1349    ;
1350
1351invalid_block_list:
1352    invalid_block
1353  | invalid_block_list error invalid_block
1354;
1355
1356
1357%%
1358import css.*;
1359
1360private var mInParseShorthand:int      = 0;
1361private var mCurrentShorthand:int      = 0;
1362private var mImplicitShorthand:Boolean = false;
1363private var mDefaultNamespace:String = '*';
1364private var mLex:CSSLexer;
1365private var mValueList:ValueList;
1366private var mStrict:Boolean = false;
1367private var mParsedProperties:Array = [];
1368private var mStyleElement:StyleList;
1369private var mParsedStyleObjects:Array /* of StyleBase */ = [];
1370private var mDebugOut:Object = null;
1371private var mPropertyExtension:IPropertyExtension;
1372
1373function ASCSSParser(aSheet:StyleList, dbgout:Object)
1374{
1375        mDebugOut = dbgout;
1376        mStyleElement = aSheet;
1377}
1378
1379private function puts(s:*):void
1380{
1381        if (mDebugOut != null)
1382                mDebugOut.puts(s);
1383}
1384
1385public function set propertyExtension(x:IPropertyExtension):void
1386{
1387        mPropertyExtension = x;
1388}
1389
1390public function set strictParsing(s:Boolean):void
1391{
1392        mStrict = s;
1393}
1394
1395public function set lexer(lx:CSSLexer):void
1396{
1397        mLex = lx;
1398}
1399
1400public function get parsingHTMLDocument():Boolean
1401{
1402        return false;
1403}
1404
1405public function get defaultNamespace():String
1406{
1407        return mDefaultNamespace;
1408}
1409
1410public function set currentValueList(vl:ValueList):void
1411{
1412        mValueList = vl;
1413}
1414
1415public function get styleElement():StyleList
1416{
1417        return mStyleElement;
1418}
1419
1420private function appendStyleObject(o:StyleBase):void
1421{
1422        mParsedStyleObjects.push(o);
1423}
1424
1425private function yylex():int {
1426        var ret:int = mLex.next();
1427        yylval = mLex.tokenBody;
1428
1429//      puts("tok: "+ret +"  '"+mLex.tokenBody+"'");
1430       
1431        return ret;
1432}
1433
1434private function yyerror(msg:String):void {
1435        puts(msg);
1436}
1437
1438private function cssPropertyID(name:String):int
1439{
1440        if (CSSPropertyID.MAP[name] || CSSPropertyID.MAP[name] == 0)
1441                return CSSPropertyID.MAP[name];
1442
1443    return -1;
1444}
1445
1446
1447// units for parsed value
1448public static const U_FUnknown:uint   = 0x0000;
1449public static const U_FInteger:uint   = 0x0001;
1450public static const U_FNumber:uint    = 0x0002;  // Real Numbers
1451public static const U_FPercent:uint   = 0x0004;
1452public static const U_FLength:uint    = 0x0008;
1453public static const U_FAngle:uint     = 0x0010;
1454public static const U_FTime:uint      = 0x0020;
1455public static const U_FFrequency:uint = 0x0040;
1456public static const U_FRelative:uint  = 0x0100;
1457public static const U_FNonNeg:uint    = 0x0200;
1458
1459private function parseValue(propId:int, important:Boolean):Boolean
1460{
1461        if (mValueList == null)
1462                return false;
1463
1464        var val:ParseValue = mValueList.currentValue;
1465        if (val == null)
1466                return false;
1467
1468        var id:int   = val.id;
1469        var num:uint = inShorthand ? 1 : mValueList.length;
1470
1471        var valid_primitive:Boolean = false;
1472        var parsedValue:CSSValue;
1473
1474        switch(propId) {
1475                case CSSPropertyID.CSSPropertySize:                              // <length>{1,2} | auto | portrait | landscape | inherit
1476                case CSSPropertyID.CSSPropertyQuotes:                      // [<string> <string>]+ | none | inherit
1477                        if (id != 0)
1478                                valid_primitive = true;
1479                        break;
1480                case CSSPropertyID.CSSPropertyUnicodeBidi:               // normal | embed | bidi-override | inherit
1481                        if (id == CSSValueKeywords.CSSValueNormal ||
1482                                 id == CSSValueKeywords.CSSValueEmbed ||
1483                                 id == CSSValueKeywords.CSSValueBidiOverride)
1484                                valid_primitive = true;
1485                        break;
1486       
1487                case CSSPropertyID.CSSPropertyPosition:                  // static | relative | absolute | fixed | inherit
1488                        if (id == CSSValueKeywords.CSSValueStatic ||
1489                                 id == CSSValueKeywords.CSSValueRelative ||
1490                                 id == CSSValueKeywords.CSSValueAbsolute ||
1491                                 id == CSSValueKeywords.CSSValueFixed)
1492                                valid_primitive = true;
1493                        break;
1494
1495
1496                case CSSPropertyID.CSSPropertyBottom:               // <length> | <percentage> | auto | inherit
1497                case CSSPropertyID.CSSPropertyLeft:                 // <length> | <percentage> | auto | inherit
1498                case CSSPropertyID.CSSPropertyRight:                // <length> | <percentage> | auto | inherit
1499                case CSSPropertyID.CSSPropertyTop:                  // <length> | <percentage> | auto | inherit
1500                case CSSPropertyID.CSSPropertyMarginTop:           //// <margin-width> | inherit
1501                case CSSPropertyID.CSSPropertyMarginRight:         //   Which is defined as
1502                case CSSPropertyID.CSSPropertyMarginBottom:        //   <length> | <percentage> | auto | inherit
1503                case CSSPropertyID.CSSPropertyMarginLeft:          ////
1504                case CSSPropertyID.CSSPropertyWebkitMarginStart:
1505                if (id == CSSValueKeywords.CSSValueAuto)
1506                        valid_primitive = true;
1507                else
1508                        valid_primitive = (id == 0 && validUnit(val, U_FLength|U_FPercent, mStrict));
1509                break;
1510
1511                case CSSPropertyID.CSSPropertyPageBreakAfter:    // auto | always | avoid | left | right | inherit
1512                case CSSPropertyID.CSSPropertyPageBreakBefore:
1513                case CSSPropertyID.CSSPropertyWebkitColumnBreakAfter:
1514                case CSSPropertyID.CSSPropertyWebkitColumnBreakBefore:
1515                        if (id == CSSValueKeywords.CSSValueAuto ||
1516                                 id == CSSValueKeywords.CSSValueAlways ||
1517                                 id == CSSValueKeywords.CSSValueAvoid ||
1518                                 id == CSSValueKeywords.CSSValueLeft ||
1519                                 id == CSSValueKeywords.CSSValueRight)
1520                                valid_primitive = true;
1521                        break;
1522       
1523                case CSSPropertyID.CSSPropertyPageBreakInside:  // avoid | auto | inherit
1524                case CSSPropertyID.CSSPropertyWebkitColumnBreakInside:
1525                        if (id == CSSValueKeywords.CSSValueAuto || id == CSSValueKeywords.CSSValueAvoid)
1526                                valid_primitive = true;
1527                        break;
1528       
1529                case CSSPropertyID.CSSPropertyEmptyCells:                 // show | hide | inherit
1530                        if (id == CSSValueKeywords.CSSValueShow ||
1531                                 id == CSSValueKeywords.CSSValueHide)
1532                                valid_primitive = true;
1533                        break;
1534/*     
1535                case CSSPropertyID.CSSPropertyContent:                    // [ <string> | <uri> | <counter> | attr(X) | open-quote |
1536                        // close-quote | no-open-quote | no-close-quote ]+ | inherit
1537                        return parseContent(propId, important);
1538                        break;
1539*/     
1540                case CSSPropertyID.CSSPropertyWhiteSpace:                 // normal | pre | nowrap | inherit
1541                        if (id == CSSValueKeywords.CSSValueNormal ||
1542                                id == CSSValueKeywords.CSSValuePre ||
1543                                id == CSSValueKeywords.CSSValuePreWrap ||
1544                                id == CSSValueKeywords.CSSValuePreLine ||
1545                                id == CSSValueKeywords.CSSValueNowrap)
1546                                valid_primitive = true;
1547                        break;
1548       
1549                case CSSPropertyID.CSSPropertyClip:                              // <shape> | auto | inherit
1550                        if (id == CSSValueKeywords.CSSValueAuto)
1551                                valid_primitive = true;
1552        //              else if (val.unit == ParseValue.Function)
1553        //                      return parseShape(propId, important);
1554                        break;
1555
1556                /* Start of supported CSS properties with validation. This is needed for parseShorthand to work
1557                 * correctly and allows optimization in WebCore::applyRule(..)
1558                 */
1559                case CSSPropertyID.CSSPropertyCaptionSide:               // top | bottom | left | right | inherit
1560                        if (id == CSSValueKeywords.CSSValueLeft || id == CSSValueKeywords.CSSValueRight ||
1561                                id == CSSValueKeywords.CSSValueTop || id == CSSValueKeywords.CSSValueBottom)
1562                                valid_primitive = true;
1563                        break;
1564       
1565                case CSSPropertyID.CSSPropertyBorderCollapse:     // collapse | separate | inherit
1566                        if (id == CSSValueKeywords.CSSValueCollapse || id == CSSValueKeywords.CSSValueSeparate)
1567                                valid_primitive = true;
1568                        break;
1569       
1570                case CSSPropertyID.CSSPropertyVisibility:                  // visible | hidden | collapse | inherit
1571                        if (id == CSSValueKeywords.CSSValueVisible || id == CSSValueKeywords.CSSValueHidden || id == CSSValueKeywords.CSSValueCollapse)
1572                                valid_primitive = true;
1573                        break;
1574       
1575                case CSSPropertyID.CSSPropertyOverflow: {
1576                        enterShorthandScope(propId);
1577                        if (num != 1 || !parseValue(CSSPropertyID.CSSPropertyOverflowX, important))
1578                        {
1579                                leaveShorthandScope();
1580                                return false;
1581                        }
1582
1583                        var ofvalue:CSSValue = CSSProperty(mParsedProperties[mParsedProperties.length - 1]).value;
1584                        addProperty(CSSPropertyID.CSSPropertyOverflowY, ofvalue, important);
1585
1586                        leaveShorthandScope();
1587                        return true;
1588                }
1589       
1590                case CSSPropertyID.CSSPropertyOverflowX:
1591                case CSSPropertyID.CSSPropertyOverflowY:                   // visible | hidden | scroll | auto | marquee | overlay | inherit
1592                        if (id == CSSValueKeywords.CSSValueVisible || id == CSSValueKeywords.CSSValueHidden || id == CSSValueKeywords.CSSValueScroll || id == CSSValueKeywords.CSSValueAuto ||
1593                                id == CSSValueKeywords.CSSValueOverlay || id == CSSValueKeywords.CSSValueWebkitMarquee)
1594                                valid_primitive = true;
1595                        break;
1596       
1597                case CSSPropertyID.CSSPropertyListStylePosition:  // inside | outside | inherit
1598                        if (id == CSSValueKeywords.CSSValueInside || id == CSSValueKeywords.CSSValueOutside)
1599                                valid_primitive = true;
1600                        break;
1601       
1602                case CSSPropertyID.CSSPropertyListStyleType:
1603                        // disc | circle | square | decimal | decimal-leading-zero | lower-roman |
1604                        // upper-roman | lower-greek | lower-alpha | lower-latin | upper-alpha |
1605                        // upper-latin | hebrew | armenian | georgian | cjk-ideographic | hiragana |
1606                        // katakana | hiragana-iroha | katakana-iroha | none | inherit
1607                        if ((id >= CSSValueKeywords.CSSValueDisc && id <= CSSValueKeywords.CSSValueKatakanaIroha) || id == CSSValueKeywords.CSSValueNone)
1608                                valid_primitive = true;
1609                        break;
1610       
1611                case CSSPropertyID.CSSPropertyDisplay:
1612                        // inline | block | list-item | run-in | inline-block | table |
1613                        // inline-table | table-row-group | table-header-group | table-footer-group | table-row |
1614                        // table-column-group | table-column | table-cell | table-caption | box | inline-box | none | inherit
1615                        if ((id >= CSSValueKeywords.CSSValueInline && id <= CSSValueKeywords.CSSValueWebkitInlineBox) || id == CSSValueKeywords.CSSValueNone)
1616                                valid_primitive = true;
1617                        break;
1618       
1619                case CSSPropertyID.CSSPropertyDirection:                        // ltr | rtl | inherit
1620                        if (id == CSSValueKeywords.CSSValueLtr || id == CSSValueKeywords.CSSValueRtl)
1621                                valid_primitive = true;
1622                        break;
1623       
1624                case CSSPropertyID.CSSPropertyTextTransform:       // capitalize | uppercase | lowercase | none | inherit
1625                        if ((id >= CSSValueKeywords.CSSValueCapitalize && id <= CSSValueKeywords.CSSValueLowercase) || id == CSSValueKeywords.CSSValueNone)
1626                                valid_primitive = true;
1627                        break;
1628       
1629                case CSSPropertyID.CSSPropertyFloat:                            // left | right | none | inherit + center for buggy CSS
1630                        if (id == CSSValueKeywords.CSSValueLeft || id == CSSValueKeywords.CSSValueRight ||
1631                                 id == CSSValueKeywords.CSSValueNone || id == CSSValueKeywords.CSSValueCenter)
1632                                valid_primitive = true;
1633                        break;
1634       
1635                case CSSPropertyID.CSSPropertyClear:                            // none | left | right | both | inherit
1636                        if (id == CSSValueKeywords.CSSValueNone || id == CSSValueKeywords.CSSValueLeft ||
1637                                 id == CSSValueKeywords.CSSValueRight|| id == CSSValueKeywords.CSSValueBoth)
1638                                valid_primitive = true;
1639                        break;
1640       
1641                case CSSPropertyID.CSSPropertyTextAlign:
1642                        // left | right | center | justify | webkit_left | webkit_right | webkit_center | start | end | <string> | inherit
1643                        if ((id >= CSSValueKeywords.CSSValueWebkitAuto && id <= CSSValueKeywords.CSSValueWebkitCenter) || id == CSSValueKeywords.CSSValueStart || id == CSSValueKeywords.CSSValueEnd ||
1644                                 val.unit == CSSPrimitiveValue.CSS_STRING)
1645                                valid_primitive = true;
1646                        break;
1647       
1648                case CSSPropertyID.CSSPropertyOutlineStyle:             // <border-style> | auto | inherit
1649                        if (id == CSSValueKeywords.CSSValueAuto) {
1650                                valid_primitive = true;
1651                                break;
1652                        } // Fall through!
1653                case CSSPropertyID.CSSPropertyBorderTopStyle:    //// <border-style> | inherit
1654                case CSSPropertyID.CSSPropertyBorderRightStyle:   //   Defined as:      none | hidden | dotted | dashed |
1655                case CSSPropertyID.CSSPropertyBorderBottomStyle:  //   solid | double | groove | ridge | inset | outset
1656                case CSSPropertyID.CSSPropertyBorderLeftStyle:
1657                case CSSPropertyID.CSSPropertyWebkitColumnRuleStyle:
1658                        if (id >= CSSValueKeywords.CSSValueNone && id <= CSSValueKeywords.CSSValueDouble)
1659                                valid_primitive = true;
1660                        break;
1661       
1662                case CSSPropertyID.CSSPropertyFontWeight:  // normal | bold | bolder | lighter | 100 | 200 | 300 | 400 |
1663                        // 500 | 600 | 700 | 800 | 900 | inherit
1664                        if (id >= CSSValueKeywords.CSSValueNormal && id <= CSSValueKeywords.CSSValue900) {
1665                                // Allready correct id
1666                                valid_primitive = true;
1667                        } else if (validUnit(val, U_FInteger|U_FNonNeg, false)) {
1668                                var weight:int = int(val.fValue);
1669                                if ((weight % 100) != 0)
1670                                        break;
1671                                weight /= 100;
1672                                if (weight >= 1 && weight <= 9) {
1673                                        id = CSSValueKeywords.CSSValue100 + weight - 1;
1674                                        valid_primitive = true;
1675                                }
1676                        }
1677                        break;
1678
1679                case CSSPropertyID.CSSPropertyBorderSpacing: {
1680                        const BORDERSPACING_PROPERTIES:Array = [ CSSPropertyID.CSSPropertyWebkitBorderHorizontalSpacing,
1681                                                                                                        CSSPropertyID.CSSPropertyWebkitBorderVerticalSpacing ];
1682                        if (num == 1) {
1683                                enterShorthandScope(CSSPropertyID.CSSPropertyBorderSpacing);
1684                                if (!parseValue(BORDERSPACING_PROPERTIES[0], important))
1685                                {
1686                                        leaveShorthandScope();
1687                                        return false;
1688                                }
1689                                var bs1val:CSSValue = CSSProperty(mParsedProperties[mParsedProperties.length-1]).value;
1690                                addProperty(BORDERSPACING_PROPERTIES[1], bs1val, important);
1691
1692                                leaveShorthandScope();
1693                                return true;
1694                        }
1695                        else if (num == 2) {
1696                                enterShorthandScope(CSSPropertyID.CSSPropertyBorderSpacing);
1697
1698                                if (!parseValue(BORDERSPACING_PROPERTIES[0], important) || !parseValue(BORDERSPACING_PROPERTIES[1], important))
1699                                {
1700                                        leaveShorthandScope();
1701                                        return false;
1702                                }
1703                                leaveShorthandScope();
1704                                return true;
1705                        }
1706                        return false;
1707                }
1708                case CSSPropertyID.CSSPropertyWebkitBorderHorizontalSpacing:
1709                case CSSPropertyID.CSSPropertyWebkitBorderVerticalSpacing:
1710                        valid_primitive = validUnit(val, U_FLength|U_FNonNeg, mStrict);
1711                        break;
1712                case CSSPropertyID.CSSPropertyScrollbarFaceColor:                // IE5.5
1713                case CSSPropertyID.CSSPropertyScrollbarShadowColor:        // IE5.5
1714                case CSSPropertyID.CSSPropertyScrollbarHighlightColor:  // IE5.5
1715                case CSSPropertyID.CSSPropertyScrollbar3dlightColor:      // IE5.5
1716                case CSSPropertyID.CSSPropertyScrollbarDarkshadowColor:   // IE5.5
1717                case CSSPropertyID.CSSPropertyScrollbarTrackColor:              // IE5.5
1718                case CSSPropertyID.CSSPropertyScrollbarArrowColor:              // IE5.5
1719                        if (mStrict)
1720                                break;
1721                        /* nobreak */
1722                case CSSPropertyID.CSSPropertyOutlineColor:             // <color> | invert | inherit
1723                        // Outline color has "invert" as additional keyword.
1724                        // Also, we want to allow the special focus color even in strict parsing mode.
1725                        if (propId == CSSPropertyID.CSSPropertyOutlineColor && (id == CSSValueKeywords.CSSValueInvert || id == CSSValueKeywords.CSSValueWebkitFocusRingColor)) {
1726                                valid_primitive = true;
1727                                break;
1728                        }
1729                        /* nobreak */
1730
1731                case CSSPropertyID.CSSPropertyBackgroundColor:     // <color> | inherit
1732                case CSSPropertyID.CSSPropertyBorderTopColor:     // <color> | inherit
1733                case CSSPropertyID.CSSPropertyBorderRightColor:   // <color> | inherit
1734                case CSSPropertyID.CSSPropertyBorderBottomColor:  // <color> | inherit
1735                case CSSPropertyID.CSSPropertyBorderLeftColor:    // <color> | inherit
1736                case CSSPropertyID.CSSPropertyColor:                // <color> | inherit
1737                case CSSPropertyID.CSSPropertyTextLineThroughColor: // CSS3 text decoration colors
1738                case CSSPropertyID.CSSPropertyTextUnderlineColor:
1739                case CSSPropertyID.CSSPropertyTextOverlineColor:
1740                case CSSPropertyID.CSSPropertyWebkitColumnRuleColor:
1741                case CSSPropertyID.CSSPropertyWebkitTextFillColor:
1742                case CSSPropertyID.CSSPropertyWebkitTextStrokeColor:
1743                        if (id == CSSValueKeywords.CSSValueWebkitText)
1744                                valid_primitive = true; // Always allow this, even when strict parsing is on,
1745                                                        // since we use this in our UA sheets.
1746                else
1747                        if (id >= CSSValueKeywords.CSSValueAqua && id <= CSSValueKeywords.CSSValueWindowtext || id == CSSValueKeywords.CSSValueMenu ||
1748                                        (id >= CSSValueKeywords.CSSValueWebkitFocusRingColor && id < CSSValueKeywords.CSSValueWebkitText && !mStrict))
1749                        {
1750                                valid_primitive = true;
1751                }
1752                        else
1753                        {
1754                    parsedValue = parseColor();
1755                    if (parsedValue != null)
1756                        mValueList.next();
1757                }
1758                break;
1759
1760/*
1761        case CSSPropertyCursor:
1762        case CSSPropertyBackgroundAttachment:
1763        case CSSPropertyWebkitBackgroundClip:
1764        case CSSPropertyWebkitBackgroundComposite:
1765        case CSSPropertyBackgroundImage:
1766        case CSSPropertyWebkitBackgroundOrigin:
1767        case CSSPropertyBackgroundPosition:
1768        case CSSPropertyBackgroundPositionX:
1769        case CSSPropertyBackgroundPositionY:
1770        case CSSPropertyWebkitBackgroundSize:
1771        case CSSPropertyBackgroundRepeat: {
1772        case CSSPropertyListStyleImage:
1773*/
1774
1775                case CSSPropertyID.CSSPropertyWebkitTextStrokeWidth:
1776                case CSSPropertyID.CSSPropertyOutlineWidth:             // <border-width> | inherit
1777                case CSSPropertyID.CSSPropertyBorderTopWidth:    //// <border-width> | inherit
1778                case CSSPropertyID.CSSPropertyBorderRightWidth:   //   Which is defined as
1779                case CSSPropertyID.CSSPropertyBorderBottomWidth:  //   thin | medium | thick | <length>
1780                case CSSPropertyID.CSSPropertyBorderLeftWidth:
1781                case CSSPropertyID.CSSPropertyWebkitColumnRuleWidth:
1782                        if (id == CSSValueKeywords.CSSValueThin || id == CSSValueKeywords.CSSValueMedium || id == CSSValueKeywords.CSSValueThick)
1783                                valid_primitive = true;
1784                        else
1785                                valid_primitive = validUnit(val, U_FLength, mStrict);
1786                        break;
1787       
1788                case CSSPropertyID.CSSPropertyLetterSpacing:       // normal | <length> | inherit
1789                case CSSPropertyID.CSSPropertyWordSpacing:               // normal | <length> | inherit
1790                        if (id == CSSValueKeywords.CSSValueNormal)
1791                                valid_primitive = true;
1792                        else
1793                                valid_primitive = validUnit(val, U_FLength, mStrict);
1794                        break;
1795       
1796                case CSSPropertyID.CSSPropertyWordBreak:                  // normal | break-all | break-word (this is a custom extension)
1797                        if (id == CSSValueKeywords.CSSValueNormal || id == CSSValueKeywords.CSSValueBreakAll || id == CSSValueKeywords.CSSValueBreakWord)
1798                                valid_primitive = true;
1799                        break;
1800       
1801                case CSSPropertyID.CSSPropertyWordWrap:            // normal | break-word
1802                        if (id == CSSValueKeywords.CSSValueNormal || id == CSSValueKeywords.CSSValueBreakWord)
1803                                valid_primitive = true;
1804                        break;
1805       
1806                case CSSPropertyID.CSSPropertyTextIndent:                 // <length> | <percentage> | inherit
1807                case CSSPropertyID.CSSPropertyPaddingTop:                 //// <padding-width> | inherit
1808                case CSSPropertyID.CSSPropertyPaddingRight:             //   Which is defined as
1809                case CSSPropertyID.CSSPropertyPaddingBottom:       //   <length> | <percentage>
1810                case CSSPropertyID.CSSPropertyPaddingLeft:               ////
1811                case CSSPropertyID.CSSPropertyWebkitPaddingStart:
1812                        valid_primitive = (0 == id && validUnit(val, U_FLength|U_FPercent, mStrict));
1813                        break;
1814
1815                case CSSPropertyID.CSSPropertyMaxHeight:                   // <length> | <percentage> | none | inherit
1816                case CSSPropertyID.CSSPropertyMaxWidth:                 // <length> | <percentage> | none | inherit
1817                        if (id == CSSValueKeywords.CSSValueNone || id == CSSValueKeywords.CSSValueIntrinsic || id == CSSValueKeywords.CSSValueMinIntrinsic) {
1818                                valid_primitive = true;
1819                                break;
1820                        }
1821                        /* nobreak */
1822                case CSSPropertyID.CSSPropertyMinHeight:                   // <length> | <percentage> | inherit
1823                case CSSPropertyID.CSSPropertyMinWidth:                 // <length> | <percentage> | inherit
1824                        if (id == CSSValueKeywords.CSSValueIntrinsic || id == CSSValueKeywords.CSSValueMinIntrinsic)
1825                                valid_primitive = true;
1826                        else
1827                                valid_primitive = (0 == id && validUnit(val, U_FLength|U_FPercent|U_FNonNeg, mStrict));
1828                        break;
1829       
1830                case CSSPropertyID.CSSPropertyFontSize:
1831                        // <absolute-size> | <relative-size> | <length> | <percentage> | inherit
1832                        if (id >= CSSValueKeywords.CSSValueXxSmall && id <= CSSValueKeywords.CSSValueLarger)
1833                                valid_primitive = true;
1834                        else
1835                                valid_primitive = (validUnit(val, U_FLength|U_FPercent, mStrict));
1836                        break;
1837       
1838                case CSSPropertyID.CSSPropertyFontStyle:                   // normal | italic | oblique | inherit
1839                        if (id == CSSValueKeywords.CSSValueNormal || id == CSSValueKeywords.CSSValueItalic || id == CSSValueKeywords.CSSValueOblique)
1840                                valid_primitive = true;
1841                        break;
1842       
1843                case CSSPropertyID.CSSPropertyFontVariant:               // normal | small-caps | inherit
1844                        if (id == CSSValueKeywords.CSSValueNormal || id == CSSValueKeywords.CSSValueSmallCaps)
1845                                valid_primitive = true;
1846                        break;
1847       
1848                case CSSPropertyID.CSSPropertyVerticalAlign:
1849                        // baseline | sub | super | top | text-top | middle | bottom | text-bottom |
1850                        // <percentage> | <length> | inherit
1851       
1852                        if (id >= CSSValueKeywords.CSSValueBaseline && id <= CSSValueKeywords.CSSValueWebkitBaselineMiddle)
1853                                valid_primitive = true;
1854                        else
1855                                valid_primitive = (0 == id && validUnit(val, U_FLength|U_FPercent, mStrict));
1856                        break;
1857       
1858                case CSSPropertyID.CSSPropertyHeight:                      // <length> | <percentage> | auto | inherit
1859                case CSSPropertyID.CSSPropertyWidth:                            // <length> | <percentage> | auto | inherit
1860                        if (id == CSSValueKeywords.CSSValueAuto || id == CSSValueKeywords.CSSValueIntrinsic || id == CSSValueKeywords.CSSValueMinIntrinsic)
1861                                valid_primitive = true;
1862                        else
1863                                // ### handle multilength case where we allow relative units
1864                                valid_primitive = (0 == id && validUnit(val, U_FLength|U_FPercent|U_FNonNeg, mStrict));
1865                        break;
1866
1867                case CSSPropertyID.CSSPropertyBottom:               // <length> | <percentage> | auto | inherit
1868                case CSSPropertyID.CSSPropertyLeft:                 // <length> | <percentage> | auto | inherit
1869                case CSSPropertyID.CSSPropertyRight:                // <length> | <percentage> | auto | inherit
1870                case CSSPropertyID.CSSPropertyTop:                  // <length> | <percentage> | auto | inherit
1871                case CSSPropertyID.CSSPropertyMarginTop:           //// <margin-width> | inherit
1872                case CSSPropertyID.CSSPropertyMarginRight:         //   Which is defined as
1873                case CSSPropertyID.CSSPropertyMarginBottom:        //   <length> | <percentage> | auto | inherit
1874                case CSSPropertyID.CSSPropertyMarginLeft:          ////
1875                case CSSPropertyID.CSSPropertyWebkitMarginStart:
1876                        if (id == CSSValueKeywords.CSSValueAuto)
1877                                valid_primitive = true;
1878                        else
1879                                valid_primitive = (0 == id && validUnit(val, U_FLength|U_FPercent, mStrict));
1880                        break;
1881
1882                case CSSPropertyID.CSSPropertyZIndex:                     // auto | <integer> | inherit
1883                        if (id == CSSValueKeywords.CSSValueAuto) {
1884                                valid_primitive = true;
1885                                break;
1886                        }
1887                        /* nobreak */
1888                case CSSPropertyID.CSSPropertyOrphans:                    // <integer> | inherit
1889                case CSSPropertyID.CSSPropertyWidows:                      // <integer> | inherit
1890                        // ### not supported later on
1891                        valid_primitive = (0 == id && validUnit(val, U_FInteger, false));
1892                        break;
1893
1894                case CSSPropertyID.CSSPropertyLineHeight:                 // normal | <number> | <length> | <percentage> | inherit
1895                        if (id == CSSValueKeywords.CSSValueNormal)
1896                                valid_primitive = true;
1897                        else
1898                                valid_primitive = (0 == id && validUnit(val, U_FNumber|U_FLength|U_FPercent, mStrict));
1899                        break;
1900        /*
1901                case CSSPropertyID.CSSPropertyCounterIncrement: // [ <identifier> <integer>? ]+ | none | inherit
1902                        if (id != CSSValueNone)
1903                                return parseCounter(propId, 1, important);
1904                        valid_primitive = true;
1905                        break;
1906        */
1907
1908                case CSSPropertyID.CSSPropertyTextDecoration:
1909                case CSSPropertyID.CSSPropertyWebkitTextDecorationsInEffect:
1910                        // none | [ underline || overline || line-through || blink ] | inherit
1911                        if (id == CSSValueKeywords.CSSValueNone) {
1912                                valid_primitive = true;
1913                        } else {
1914                                var decolist:CSSValueList = new CSSValueList();
1915                                var is_valid:Boolean = true;
1916                                while(is_valid && val != null) {
1917                                        switch (val.id) {
1918                                        case CSSValueKeywords.CSSValueBlink:
1919                                                break;
1920                                        case CSSValueKeywords.CSSValueUnderline:
1921                                        case CSSValueKeywords.CSSValueOverline:
1922                                        case CSSValueKeywords.CSSValueLineThrough:
1923                                                decolist.append(CSSPrimitiveValue.newId(val.id));
1924                                                break;
1925                                        default:
1926                                                is_valid = false;
1927                                        }
1928                                        val = mValueList.next();
1929                                }
1930                                if (decolist.length != 0 && is_valid) {
1931                                        parsedValue = decolist;
1932                                        mValueList.next();
1933                                }
1934                        }
1935                        break;
1936
1937        // -- shorthands
1938               
1939                case CSSPropertyID.CSSPropertyBorder:
1940                        const BORDER_PROPERTIES:Array = [CSSPropertyID.CSSPropertyBorderWidth, CSSPropertyID.CSSPropertyBorderStyle, CSSPropertyID.CSSPropertyBorderColor];
1941                        return parseShorthand(propId, BORDER_PROPERTIES, important);
1942                        break;
1943
1944                case CSSPropertyID.CSSPropertyBorderColor:
1945                // <color>{1,4} | inherit
1946                {
1947                        const BORDERCOLOR_PROPERTIES:Array = [ CSSPropertyID.CSSPropertyBorderTopColor, CSSPropertyID.CSSPropertyBorderRightColor,
1948                                                               CSSPropertyID.CSSPropertyBorderBottomColor, CSSPropertyID.CSSPropertyBorderLeftColor ];
1949                        return parse4Values(propId, BORDERCOLOR_PROPERTIES, important);
1950                }
1951
1952                case CSSPropertyID.CSSPropertyBorderWidth:
1953                // <border-width>{1,4} | inherit
1954                {
1955                        const BORDERWIDTH_PROPERTIES:Array = [ CSSPropertyID.CSSPropertyBorderTopWidth, CSSPropertyID.CSSPropertyBorderRightWidth,
1956                                                               CSSPropertyID.CSSPropertyBorderBottomWidth, CSSPropertyID.CSSPropertyBorderLeftWidth];
1957                        return parse4Values(propId, BORDERWIDTH_PROPERTIES, important);
1958                }
1959                case CSSPropertyID.CSSPropertyBorderStyle:
1960                // <border-style>{1,4} | inherit
1961                {
1962                        const BORDERSTYLE_PROPERTIES:Array = [ CSSPropertyID.CSSPropertyBorderTopStyle, CSSPropertyID.CSSPropertyBorderRightStyle,
1963                                                               CSSPropertyID.CSSPropertyBorderBottomStyle, CSSPropertyID.CSSPropertyBorderLeftStyle ];
1964                        return parse4Values(propId, BORDERSTYLE_PROPERTIES, important);
1965                }
1966                case CSSPropertyID.CSSPropertyMargin:
1967                // <margin-width>{1,4} | inherit
1968                {
1969                        const MARGIN_PROPERTIES:Array = [ CSSPropertyID.CSSPropertyMarginTop, CSSPropertyID.CSSPropertyMarginRight,
1970                                                          CSSPropertyID.CSSPropertyMarginBottom, CSSPropertyID.CSSPropertyMarginLeft ];
1971                        return parse4Values(propId, MARGIN_PROPERTIES, important);
1972                }
1973                case CSSPropertyID.CSSPropertyPadding:
1974                // <padding-width>{1,4} | inherit
1975                {
1976                        const PADDING_PROPERTIES:Array = [ CSSPropertyID.CSSPropertyPaddingTop, CSSPropertyID.CSSPropertyPaddingRight,
1977                                                           CSSPropertyID.CSSPropertyPaddingBottom, CSSPropertyID.CSSPropertyPaddingLeft ];
1978                        return parse4Values(propId, PADDING_PROPERTIES, important);
1979                }
1980
1981                default:
1982                        if (mPropertyExtension)
1983                        {
1984                                if (mPropertyExtension.isValidPrimitiveValue(propId, id))
1985                                        valid_primitive = true;
1986                        }
1987                        break;
1988        }
1989
1990        if (valid_primitive) {
1991                if (id != 0)
1992                        parsedValue = CSSPrimitiveValue.newId(id);
1993                else if (val.unit >= CSSPrimitiveValue.CSS_NUMBER && val.unit <= CSSPrimitiveValue.CSS_KHZ)
1994                        parsedValue = CSSPrimitiveValue.newUnitNumber(val.fValue, val.unit);
1995/*
1996        else if (value->unit == CSSPrimitiveValue::CSS_STRING)
1997            parsedValue = new CSSPrimitiveValue(value->string, (CSSPrimitiveValue::UnitTypes) value->unit);
1998        else if (value->unit >= Value::Q_EMS)
1999            parsedValue = new CSSQuirkPrimitiveValue(value->fValue, CSSPrimitiveValue::CSS_EMS);
2000*/
2001        mValueList.next();
2002    }
2003
2004        if (parsedValue != null) {
2005                if (mValueList.currentValue == null || inShorthand) {
2006                        addProperty(propId, parsedValue, important);
2007                        return true;
2008                }
2009        }
2010
2011        return false;
2012}
2013
2014public function get inShorthand():Boolean
2015{
2016        return mInParseShorthand != 0;
2017}
2018
2019private function enterShorthandScope(propId:int):void
2020{
2021        if (0 == (mInParseShorthand++))
2022                mCurrentShorthand = propId;
2023}
2024
2025private function leaveShorthandScope():void
2026{
2027        if (0 == (--mInParseShorthand))
2028                mCurrentShorthand = 0;
2029}
2030
2031private function parse4Values(propId:int, properties:Array, important:Boolean):Boolean
2032{
2033        var num:int = inShorthand ? 1 : mValueList.length;
2034        enterShorthandScope(propId);
2035        var rval:Boolean = parse4ValuesInternal(propId, properties, important, num);
2036        leaveShorthandScope();
2037        return rval;
2038}
2039
2040private function parse4ValuesInternal(propId:int, properties:Array, important:Boolean, num:int):Boolean
2041{
2042        /* From the CSS 2 specs, 8.3
2043         * If there is only one value, it applies to all sides. If there are two values, the top and
2044         * bottom margins are set to the first value and the right and left margins are set to the second.
2045         * If there are three values, the top is set to the first value, the left and right are set to the
2046         * second, and the bottom is set to the third. If there are four values, they apply to the top,
2047         * right, bottom, and left, respectively.
2048         */
2049
2050        // the order is top, right, bottom, left
2051        var value:CSSValue;
2052        switch (num) {
2053                case 1: {
2054                        if (!parseValue(properties[0], important))
2055                                return false;
2056                        value = CSSProperty(mParsedProperties[mParsedProperties.length-1]).value;
2057                        mImplicitShorthand = true;
2058                        addProperty(properties[1], value, important);
2059                        addProperty(properties[2], value, important);
2060                        addProperty(properties[3], value, important);
2061                        mImplicitShorthand = false;
2062                        break;
2063                }
2064                case 2: {
2065                        if (!parseValue(properties[0], important) || !parseValue(properties[1], important))
2066                                return false;
2067
2068                        value = CSSProperty(mParsedProperties[mParsedProperties.length-2]).value;
2069                        mImplicitShorthand = true;
2070                        addProperty(properties[2], value, important);
2071                        value = CSSProperty(mParsedProperties[mParsedProperties.length-2]).value;
2072                        addProperty(properties[3], value, important);
2073                        mImplicitShorthand = false;
2074                        break;
2075                }
2076                case 3: {
2077                        if (!parseValue(properties[0], important) || !parseValue(properties[1], important) || !parseValue(properties[2], important))
2078                                return false;
2079                        value = CSSProperty(mParsedProperties[mParsedProperties.length-2]).value;
2080                        mImplicitShorthand = true;
2081                        addProperty(properties[3], value, important);
2082                        mImplicitShorthand = false;
2083                        break;
2084                }
2085                case 4: {
2086                        if (!parseValue(properties[0], important) || !parseValue(properties[1], important) ||
2087                                !parseValue(properties[2], important) || !parseValue(properties[3], important))
2088                                return false;
2089                        break;
2090                }
2091                default: {
2092                        return false;
2093                }
2094        }
2095       
2096        return true;
2097}
2098
2099private function parseShorthand(propId:int, properties:Array, important:Boolean):Boolean
2100{
2101        enterShorthandScope(propId);
2102        var rval:Boolean = parseShorthandInternal(propId, properties, important);
2103        leaveShorthandScope();
2104        return rval;
2105}
2106
2107private function parseShorthandInternal(propId:int, properties:Array, important:Boolean):Boolean
2108{
2109        // We try to match as many properties as possible
2110        // We set up an array of booleans to mark which property has been found,
2111        // and we try to search for properties until it makes no longer any sense.
2112        var numProperties:int = properties.length;
2113
2114        var i:int;
2115        var found:Boolean = false;
2116        var fnd:Array = new Array(6); // Trust me ;)
2117        for (i = 0; i < numProperties; i++)
2118                fnd[i] = false;
2119
2120        while (mValueList.currentValue != null) {
2121                found = false;
2122                for (var propIndex:int = 0; !found && propIndex < numProperties; ++propIndex) {
2123                        if (!fnd[propIndex]) {
2124                                if (parseValue(properties[propIndex], important))
2125                                        fnd[propIndex] = found = true;
2126                        }
2127                }
2128       
2129                // if we didn't find at least one match, this is an
2130                // invalid shorthand and we have to ignore it
2131                if (!found)
2132                        return false;
2133        }
2134
2135    // Fill in any remaining properties with the initial value.
2136    mImplicitShorthand = true;
2137    for (i = 0; i < numProperties; ++i) {
2138        if (!fnd[i])
2139            addProperty(properties[i], new CSSInitialValue(true), important);
2140    }
2141    mImplicitShorthand = false;
2142
2143        return true;
2144}
2145
2146private function validUnit(aValue:ParseValue, aUnitFlags:uint, aStrict:Boolean):Boolean
2147{
2148        if ((aUnitFlags & U_FNonNeg) != 0 && aValue.fValue < 0)
2149                return false;
2150
2151    var b:Boolean = false;
2152    switch(aValue.unit) {
2153    case CSSPrimitiveValue.CSS_NUMBER:
2154                b = (aUnitFlags & U_FNumber) != 0;
2155                if (!b && ((aUnitFlags & (U_FLength | U_FAngle)) != 0 && (aValue.fValue == 0 || !aStrict))) {
2156                        aValue.unit = ((aUnitFlags & U_FLength) !=0 ) ? CSSPrimitiveValue.CSS_PX : CSSPrimitiveValue.CSS_DEG;
2157                        b = true;
2158                }
2159                if (!b && (aUnitFlags & U_FInteger) != 0 && aValue.isInt)
2160                        b = true;
2161                break;
2162        case CSSPrimitiveValue.CSS_PERCENTAGE:
2163                b = (aUnitFlags & U_FPercent) != 0;
2164                break;
2165        case ParseValue.Q_EMS:
2166        case CSSPrimitiveValue.CSS_EMS:
2167        case CSSPrimitiveValue.CSS_EXS:
2168        case CSSPrimitiveValue.CSS_PX:
2169        case CSSPrimitiveValue.CSS_CM:
2170        case CSSPrimitiveValue.CSS_MM:
2171        case CSSPrimitiveValue.CSS_IN:
2172        case CSSPrimitiveValue.CSS_PT:
2173        case CSSPrimitiveValue.CSS_PC:
2174                b = (aUnitFlags & U_FLength) != 0;
2175                break;
2176        case CSSPrimitiveValue.CSS_MS:
2177        case CSSPrimitiveValue.CSS_S:
2178                b = (aUnitFlags & U_FTime) != 0;
2179                break;
2180        case CSSPrimitiveValue.CSS_DEG:
2181        case CSSPrimitiveValue.CSS_RAD:
2182        case CSSPrimitiveValue.CSS_GRAD:
2183                b = (aUnitFlags & U_FAngle) != 0;
2184                break;
2185        case CSSPrimitiveValue.CSS_HZ:
2186        case CSSPrimitiveValue.CSS_KHZ:
2187        case CSSPrimitiveValue.CSS_DIMENSION:
2188    default:
2189        break;
2190        }
2191
2192        return b;
2193}
2194
2195private function parseColor(aValue:ParseValue = null):CSSPrimitiveValue
2196{
2197        var c:uint = WKColor.transparent;
2198
2199        var res:Object;
2200        if (null == (res = parseColorFromValue((aValue != null) ? aValue : mValueList.currentValue)))
2201                return null;
2202        else
2203                c = uint(res);
2204
2205        return CSSPrimitiveValue.newColor(c);
2206}
2207
2208private function parseColorFromValue(value:ParseValue, svg:Boolean = false):Object
2209{
2210        var res:Object = null;
2211        if (value.unit == CSSPrimitiveValue.CSS_RGBCOLOR) {
2212                if (null == (res = parseColorString(value.stringVal.str, mStrict && value.unit == CSSPrimitiveValue.CSS_IDENT)))
2213                        return null;
2214    }
2215
2216        return res;
2217}
2218
2219private function parseColorString(name:String, strict:Boolean):Object
2220{
2221        var res:Object = null;
2222    if (!strict && (res = WKColor.parseHexColor(name)) != null)
2223        return res;
2224
2225    return null;
2226}
2227
2228private function cssValueKeywordID(name:String):int
2229{
2230        if (CSSValueKeywords.MAP[name] || CSSValueKeywords.MAP[name] == 0)
2231                return CSSValueKeywords.MAP[name];
2232       
2233        return 0;
2234}
2235
2236private function addProperty(propId:int, value:CSSValue, important:Boolean):void
2237{
2238        var p:CSSProperty = new CSSProperty(propId, value, important, mCurrentShorthand, mImplicitShorthand);
2239        mParsedProperties.push(p);
2240
2241}
2242
2243private function createStyleRule(sel:CSSSelector):CSSRule
2244{
2245        var rule:CSSStyleRule = null;
2246        if (sel != null)
2247        {
2248                rule = new CSSStyleRule(styleElement);
2249                appendStyleObject(rule);
2250                rule.selector = sel;
2251                rule.declaration = new CSSMutableStyleDeclaration(rule, mParsedProperties);
2252        }
2253
2254        clearProperties();
2255        return rule;
2256}
2257
2258private function clearProperties():void
2259{
2260        for (;mParsedProperties.length > 0;)
2261                mParsedProperties.shift();
2262}
Note: See TracBrowser for help on using the browser.