diff options
-rw-r--r-- | src/css.cc | 13 | ||||
-rw-r--r-- | src/cssparser.cc | 3 | ||||
-rw-r--r-- | src/doctree.hh | 54 |
3 files changed, 50 insertions, 20 deletions
@@ -104,6 +104,7 @@ CssSelector::CssSelector () { cs = selectorList->getRef (selectorList->size () - 1); cs->notMatchingBefore = -1; + cs->combinator = CHILD; cs->selector = new CssSimpleSelector (); }; @@ -133,6 +134,7 @@ bool CssSelector::match (Doctree *docTree, const DoctreeNode *node) { switch (comb) { case CHILD: + case ADJACENT_SIBLING: if (!sel->match (node)) return false; break; @@ -148,7 +150,7 @@ bool CssSelector::match (Doctree *docTree, const DoctreeNode *node) { if (sel->match (node)) break; - node = docTree->parent (node); + node = node->parent; } break; default: @@ -156,7 +158,11 @@ bool CssSelector::match (Doctree *docTree, const DoctreeNode *node) { } comb = cs->combinator; - node = docTree->parent (node); + + if (comb == ADJACENT_SIBLING) + node = node->sibling; + else + node = node->parent; } return true; @@ -200,6 +206,9 @@ void CssSelector::print () { case DESCENDANT: fprintf (stderr, "\" \" "); break; + case ADJACENT_SIBLING: + fprintf (stderr, "+ "); + break; default: fprintf (stderr, "? "); break; diff --git a/src/cssparser.cc b/src/cssparser.cc index 3d62b31d..73b4331a 100644 --- a/src/cssparser.cc +++ b/src/cssparser.cc @@ -1289,6 +1289,9 @@ CssSelector *CssParser::parseSelector() } else if (ttype == CSS_TK_CHAR && tval[0] == '>') { selector->addSimpleSelector (CssSelector::CHILD); nextToken(); + } else if (ttype == CSS_TK_CHAR && tval[0] == '+') { + selector->addSimpleSelector (CssSelector::ADJACENT_SIBLING); + nextToken(); } else if (ttype != CSS_TK_END && spaceSeparated) { selector->addSimpleSelector (CssSelector::DESCENDANT); } else { diff --git a/src/doctree.hh b/src/doctree.hh index ef7faa7c..c46a5a10 100644 --- a/src/doctree.hh +++ b/src/doctree.hh @@ -6,6 +6,8 @@ class DoctreeNode { public: DoctreeNode *parent; + DoctreeNode *sibling; + DoctreeNode *lastChild; int num; // unique ascending id int element; lout::misc::SimpleVector<char*> *klass; @@ -14,11 +16,27 @@ class DoctreeNode { DoctreeNode () { parent = NULL; + sibling = NULL; + lastChild = NULL; klass = NULL; pseudo = NULL; id = NULL; element = 0; }; + + ~DoctreeNode () { + dFree ((void*) id); + while (lastChild) { + DoctreeNode *n = lastChild; + lastChild = lastChild->sibling; + delete n; + } + if (klass) { + for (int i = 0; i < klass->size (); i++) + dFree (klass->get(i)); + delete klass; + } + } }; /** @@ -26,47 +44,47 @@ class DoctreeNode { * * The Doctree class defines the interface to the parsed HTML document tree * as it is used for CSS selector matching. - * Currently the Doctree can be represented as stack, however to support - * CSS adjacent siblings or for future JavaScript support it may have to - * be extended to a real tree. */ class Doctree { private: DoctreeNode *topNode; + DoctreeNode *rootNode; int num; public: Doctree () { topNode = NULL; + rootNode = NULL; num = 0; }; - ~Doctree () { while (top ()) pop (); }; + + ~Doctree () { + if (rootNode) + delete rootNode; + }; + DoctreeNode *push () { DoctreeNode *dn = new DoctreeNode (); dn->parent = topNode; + if (dn->parent) { + dn->sibling = dn->parent->lastChild; + dn->parent->lastChild = dn; + } dn->num = num++; + if (!rootNode) + rootNode = dn; topNode = dn; return dn; }; + void pop () { - DoctreeNode *dn = topNode; - if (dn) { - dFree ((void*) dn->id); - if (dn->klass) { - for (int i = 0; i < dn->klass->size (); i++) - dFree (dn->klass->get(i)); - delete dn->klass; - } - topNode = dn->parent; - delete dn; - } + if (topNode) + topNode = topNode->parent; }; + inline DoctreeNode *top () { return topNode; }; - inline DoctreeNode *parent (const DoctreeNode *node) { - return node->parent; - }; }; #endif |