- term对应CSSParserValue对象。
- expr对应CSSParserValueList对象。
- operator刚被解析出来时,以字符形式存储在解释器堆栈上。等到需要与其他term组合时,转换为CSSParserValue对象存入CSSParserValueList对象中。
- error对应0。如果解析某条css规则时发现了错误,那么将0存储到解释器堆栈上。
- property对应一个整数值。整数值实际是属性名称的hash值。
- prio对应一个true或者false。如果有符号'!',那么将true压入解释器堆栈。否则,将false压入解释器堆栈。
- declaration对应CSSProperty对象。只是declaration对应的CSSProperty对象并未压入解释器堆栈,而是直接存入CSSParser的成员变量m_parsedProperties中。如果declaration是合法的,那么向解释器堆栈压入一个true。否则,压入一个false。
- decl_list对应Vector<CSSProperty, 256>。如果无错,那么将true压入解释器堆栈。如果有错,那么将false压入解释器堆栈。
- declaration_list与decl_list相同。
- pseudo_page对应CSSParserSelector对象。
- match对应CSSSelector::Match对象。
- attrib对应CSSParserSelector对象。如果是[attribute-name]形式,那么CSSParserSelector的attribute记录attribute-name。如果是[attribute-name=xxx]形式,那么CSSParserSelector的match记录=, value记录xxx, attribute记录attribute-name。
- attr_name对应CSSParserString对象。
- class对应CSSParserSelector对象。
- specifier对应CSSParserSelector对象。
- specifier_list对应CSSParserSelector对象。m_relation用于记录关系,m_tagHistory用于记录另一个Selector。如果是父子选择符,那么父亲是this,m_relation是sub, 子记录在this->m_tagHistory。
- element_name对应CSSParserString对象。
- simple_selector对应CSSParserSelector对象。
- simple_selector_list对应Vector<OwnPtr<CSSParserSelector> >对象。simple_selector_list是指selector, selector,xxx样式。
- namespace_selector对应CSSParserString对象。
- selector对应CSSParserSelector对象。形如selector combinator simple_selector,CSSParserSelector.m_relation是combinator, CSSParserSelector.m_tagHistory是selector, simple_selector->....->m_tagHistory是this。
- combinator对应CSSSelector::Relation对象。
- ruleset对应CSSStyleRule对象。在生成CSSRule对象时,会将CSSParser::m_parsedProperties转换为StylePropertySet对象。然后将StylePropertySet对象记录到m_parsedRules成员变量中。
- unary_operator对应1或者-1。
- region对应WebKitCSSRegionRule对象。
- region_selector对应Vector<OwnPtr<CSSParserSelector> >对象。
- font_face对应CSSFontFaceRule对象。
- margin_sym对应CSSSelector::MarginBoxType对象。
- page_selector对应CSSParserSelector对象。
- page对应CSSPageRule对象。
- key对应CSSParserValue对象。
- key_list对应CSSParserValueList对象。
- keyframe_rule对应StyleKeyframe对象。
- keyframes_rule对应WebKitCSSKeyframesRule对象。
- keyframes对应WebKitCSSKeyframesRule对象。
- 形如"[ xxx ]" 类型的选择符,使用CSSSelector::Set来描绘素。当DOM元素设置了xxx属性时,匹配成功。
- 形如“[ xxx = vvv ]”类型的选择符,使用CSSSelector::Exact来描述。当DOM元素设置了xxx属性且设置的值等于vvv时,匹配成功。
- 形如"[ xxx ~= vvv ]"类型的选择符,使用CSSSelector::List来描述。当DOM元素设置了xxx属性、设置的值是一系列 以空格分开的字符串、其中的一个字符串等于vvv,那么匹配成功。
- 形如"[ xxx |= vvv ]"类型的选择符,使用CSSSelector::Hyphen来描述。当DOM元素设置了xxx属性、设置的值是一系列用连字符分开的字符串、第一个字符串等于vvv时,匹配成功。
- 形如"[ xxx ^= vvv ]"类型的选择符,使用CSSSelector::Begin来描述。当DOM元素设置了xxx属性,设置的值是一个字符串且vvv是值的前缀时,匹配成功。
- 形如"[ xxx $= vvv ]"类型的选择符,使用CSSSelector::End来描述。当DOM元素设置了xxx属性,设置的值是一个字符串且vvv是值的后缀时,匹配成功。
- 形如"[ xxx *= vvv ]"类型的选择符,使用CSSSelector::Contain来描述。当DOM元素设置了xxx属性,设置的值是一个字符串且vvv是值的子串时,匹配成功。
类选择符也用到了成员变量m_match和m_data。类选择符的样式是".xxx"。CSSSelector对象将字符串"xxx"记录在m_data.m_value中,将CSSSelector::Class记录在m_match中。
id选择符也用到了成员变量m_match和m_data。id选择符的样式是"#xxx"。CSSSelector对象将字符串"#xxx"记录在m_data.m_value中,将CSSSelecotr::Id记录在m_match中。
元素选择符用到了成员变量m_tag。元素选择符的样式是"tag-name" or "*"。CSSSelector直接将字符串"tag-name"或者"*"记录在m_tag中。
伪类选择符用到了成员变量m_match、m_pseudoType、m_data。伪类选择符的样式是":xxx"。伪类选择符的种类非场多。碰到伪类选择符,CSSSelector对象将m_match设置为CSSSelector::PseudoClass,将字符串"xxx"记录到m_data.m_value中,再执行CSSSelector::pseudoType方法来解析出伪类的类型。另外,如果伪类选择符还需要设置参数,那么将参数记录到m_data.m_argument。例如:nth-child(xxx),xxx就记录在m_data.m_argument。伪类的类型可以阅读CSSSelector::PseudoType类型以及位于CSSSelector.cpp文件中的nameToPseudoTypeMap方法。
伪元素选择符用到了成员变量m_match、m_pseudoType、m_data。伪元素选择符的样式是"::xxx"。CSSSelector将m_match设在为CSSSelector::PseudoElement,将字符串"xxx"记录到m_data.m_value中,再执行CSSSelector::pseudoType解析伪元素类型。
组合选择符是由两个选择符根据一定关系组合起来的。目前webcore实现了五种组合关系: "子孙"、“孩子”、"直接相邻兄弟”、“间接相邻兄弟”、“属性组合”。组合选择符除了使用前述的成员变量之外,还需要用到m_relation。另外,对于CSSParserSelector对象来说,关系是通过指针m_tagHistory来实现。对于CSSSelector来说,关系通过地址紧临来实现,也就是说(this, this+1)具有关系。为叙述方便,我假设关系是通过指针ptr来实现的。
子孙选择符是形如"selector1 space selector2"样式的。如果DOM元素匹配selector2且DOM某祖先元素匹配selector1,那么才匹配成功。selector2的m_relation设置为CSSSelector::Descendant,并设置selector2->ptr为selector1的地址。
孩子选择符是形如"selector1 > selector2"样式的。如果DOM元素匹配selector2且DOM元素的父亲匹配selector1,那么匹配成功。selector2的m_relation设置为CSSSelector::Child,并设置selector2->ptr为selector1的地址。
直接相邻兄弟选择符是形如"selector1 + selector2"样式的。如果DOM元素A与DOM元素B具有相同的父节点、A紧跟在B之后且A匹配selector2、B匹配selector1,那么匹配成功。A可以使用选择符的样式。selector2的m_relation设置为CSSSelector::DirectAdjacent,并设置selector2->ptr为selector1的地址。
间接相邻兄弟选择符形如"selector1 ~ selector2"样式的。如果DOM元素A与DOM元素B具有相同父节点、A跟在B之后无需紧跟且A匹配selector2、B匹配selector1,那么匹配成功。A可以使用选择符的样式。selector2的m_relation设置为CSSSelector::IndirectAdjacent,并设置selector2->ptr为selector1的地址。
属性组合是形如"spec-selector spec-selector"样式。spec-selector表示id选择符、类选择符、属性选择符、伪类选择符。这种情况与子孙选择符样式很相似,区别在于子孙选择符是在此次处理之后添加的。有两种情况,分别会有SubSelector和ShadowDescendent两种关系。
假设选择符类型是"div .abc ['color']"。
- CSSParser先创建一个元素选择符对象div。
- 创建类选择符对象abc。
- 创建属性选择符对象color。
- 对abc、color做属性组合,结果是abc->ptr ==> color,关系为CSSSelector::SubSelector。
- 将abc与"*"做属性组合,结果是abc->ptr ==> abc,关系为CSSSelector::SubSelector,color的m_tag被设置为"*"。
- 将abc与div做子孙组合,结果是abc->ptr ==> color, 关系为CSSSelector::SubSelector。color->ptr ==> div,关系为Descendant。
假设选择符类型是"div ::abc ['color']"。
- CSSParser先创建一个元素选择符对象div。
- 创建伪元素选择符对象abc。
- 创建属性选择符对象color。
- 对abc、color做属性组合,结果是abc->ptr ==> color,关系为CSSSelector::SubSelector。color具有关系,为ShadowDescendant。
- 将abc与"*"做属性组合,结果是abc->ptr ==> color,关系为CSSSelector::SubSelector。color->ptr ==>“*”,关系为ShadowDescendant。
- 将abc与div做子孙组合,结果是abc->ptr ==> color, 关系为CSSSelector::SubSelector。color->ptr ==>“*”,关系为ShadowDescendant。"*"->ptr ==> div,关系为Descendant。
- 先创建CSSStyleSheet对象。将CSSStyleSheet对象的指针存储到CSSParser对象中。
- CSSParser识别出一个simple-selector,形如"div"或者".class"。创建一个CSSParserSelector对象。
- CSSParser识别出一个关系符和另一个simple-selecotr,那么修改之前创建的simple-selecotr, 创建组合关系符。
- 循环第3步直至碰到逗号或者左大括号。
- 如果碰到逗号,那么取出CSSParser的reuse vector,然后将堆栈尾部的CSSParserSelector对象弹出存入Vecotr中,最后跳转至第2步。如果碰到左大括号,那么跳转至第6步。
- 识别属性名称,将属性名称的hash值压入解释器堆栈。
- 识别属性值,创建CSSParserValue对象,并将CSSParserValue对象存入解释器堆栈。
- 将属性名称和属性值弹出栈,创建CSSProperty对象。并将CSSProperty对象存入CSSParser成员变量m_parsedProperties中。
- 如果识别处属性名称,那么转至第6步。如果识别右大括号,那么转至第10步。
- 将reuse vector从堆栈中弹出,并创建CSSStyleRule对象。CSSStyleRule对象的选择符就是reuse vector, 样式值就是CSSParser的成员变量m_parsedProperties。
- 把CSSStyleRule添加到CSSStyleSheet中。
- 清空CSSParser内部缓存结果。
- 如果没有内容了,那么结束。否则跳转值第2步。
补:nth-child和nth-last-child的实现细节。