static void FixStructure(ContainerNode node) { // maybe rename nodes to "condition" and "body" or att attributes // see how variable names and functions pan out var isRound = AttributeSelector.ContainsClass(RoundName); var isCurly = AttributeSelector.ContainsClass(CurlyName); for (int i = 0; i < node.ChildNodes.Count; ++i) { HtmlNode child = node.ChildNodes[i]; // restructure switch (child.Name) { case "function": case "while": case "with": case "switch": case "for": case "if": // attach (...) if (Test(node, i + 1, isRound.IsMatch) == false) { break; } MoveNextSiblingToChild(node.ChildNodes, i); goto case "else"; // need body case "do": case "try": case "finally": case "else": // attach {} if (Test(node, i + 1, isCurly.IsMatch) == false) { break; } MoveNextSiblingToChild(node.ChildNodes, i); break; } } }
// consume exactly 1 partial-step INodeMatcher ConsumePartialStep() { CssToken t = GetNext(); switch (t.Type) { case CssTokenType.Name: return(new NameSelector(t.Text)); case CssTokenType.Class: return(AttributeSelector.ContainsClass(t.Text.Substring(1))); case CssTokenType.Id: return(AttributeSelector.IdIs(t.Text.Substring(1))); case CssTokenType.Square: { CssToken insideText = GetNext(); GetNext(); // throw away closing token return(ParseAttribute(insideText.Text)); } case CssTokenType.Pseudo: switch (t.Text) { case ":even": return(SiblingSelector.Even); case ":odd": return(SiblingSelector.Odd); case ":nth-child": _index += 3; return(ParseSibling(_tokens[_index - 2].Text)); case ":contains": _index += 3; return(new ContainsTextSelector(_tokens[_index - 2].Text)); default: _index += 3; return(ParseColon(t.Text)); } } --_index; // If didn't use it, we need to push it back onto the stream return(null); }