Adds support for shadow host selectors

Adds support for :host() and :host-context().
diff --git a/lib/parser.dart b/lib/parser.dart
index a268c55..a1a9823 100644
--- a/lib/parser.dart
+++ b/lib/parser.dart
@@ -1219,6 +1219,20 @@
     return new Selector(simpleSequences, _makeSpan(start));
   }
 
+  /// Same as [processSelector] but reports an error for each combinator.
+  ///
+  /// This is a quick fix for parsing <compound-selectors> until the parser
+  /// supports Selector Level 4 grammar:
+  /// https://drafts.csswg.org/selectors-4/#typedef-compound-selector
+  Selector processCompoundSelector() {
+    return processSelector()
+      ..simpleSelectorSequences.forEach((sequence) {
+        if (!sequence.isCombinatorNone) {
+          _error('compound selector can not contain combinator', sequence.span);
+        }
+      });
+  }
+
   simpleSelectorSequence(bool forceCombinatorNone) {
     var start = _peekToken.span;
     var combinatorType = TokenKind.COMBINATOR_NONE;
@@ -1429,7 +1443,8 @@
     // Functional pseudo?
 
     if (_peekToken.kind == TokenKind.LPAREN) {
-      if (!pseudoElement && pseudoName.name.toLowerCase() == 'not') {
+      var name = pseudoName.name.toLowerCase();
+      if (!pseudoElement && name == 'not') {
         _eat(TokenKind.LPAREN);
 
         // Negation :   ':NOT(' S* negation_arg S* ')'
@@ -1437,6 +1452,12 @@
 
         _eat(TokenKind.RPAREN);
         return new NegationSelector(negArg, _makeSpan(start));
+      } else if (!pseudoElement && (name == 'host' || name == 'host-context')) {
+        _eat(TokenKind.LPAREN);
+        var selector = processCompoundSelector();
+        _eat(TokenKind.RPAREN);
+        var span = _makeSpan(start);
+        return new PseudoClassFunctionSelector(pseudoName, selector, span);
       } else {
         // Special parsing for expressions in pseudo functions.  Minus is used
         // as operator not identifier.
diff --git a/lib/src/css_printer.dart b/lib/src/css_printer.dart
index 035bc46..d3b62d0 100644
--- a/lib/src/css_printer.dart
+++ b/lib/src/css_printer.dart
@@ -324,7 +324,7 @@
 
   void visitPseudoClassFunctionSelector(PseudoClassFunctionSelector node) {
     emit(":${node.name}(");
-    node.expression.visit(this);
+    node.argument.visit(this);
     emit(')');
   }
 
diff --git a/lib/src/tree.dart b/lib/src/tree.dart
index a6a64fc..63c7301 100644
--- a/lib/src/tree.dart
+++ b/lib/src/tree.dart
@@ -291,15 +291,19 @@
   String toString() => "::$name";
 }
 
-// :pseudoClassFunction(expression)
+// :pseudoClassFunction(argument)
 class PseudoClassFunctionSelector extends PseudoClassSelector {
-  final SelectorExpression expression;
+  final TreeNode _argument; // Selector, SelectorExpression
 
-  PseudoClassFunctionSelector(Identifier name, this.expression, SourceSpan span)
+  PseudoClassFunctionSelector(Identifier name, this._argument, SourceSpan span)
       : super(name, span);
 
   PseudoClassFunctionSelector clone() =>
-      new PseudoClassFunctionSelector(_name, expression, span);
+      new PseudoClassFunctionSelector(_name, _argument, span);
+
+  TreeNode get argument => _argument;
+  Selector get selector => _argument as Selector;
+  SelectorExpression get expression => _argument as SelectorExpression;
 
   visit(VisitorBase visitor) => visitor.visitPseudoClassFunctionSelector(this);
 }
diff --git a/lib/src/tree_printer.dart b/lib/src/tree_printer.dart
index 9b0a6c2..97c6acc 100644
--- a/lib/src/tree_printer.dart
+++ b/lib/src/tree_printer.dart
@@ -338,7 +338,7 @@
   void visitPseudoClassFunctionSelector(PseudoClassFunctionSelector node) {
     heading('Pseudo Class Function Selector', node);
     output.depth++;
-    visitSelectorExpression(node.expression);
+    node.argument.visit(this);
     super.visitPseudoClassFunctionSelector(node);
     output.depth--;
   }
diff --git a/test/selector_test.dart b/test/selector_test.dart
index dff4415..87fb60a 100644
--- a/test/selector_test.dart
+++ b/test/selector_test.dart
@@ -46,6 +46,18 @@
   selectorAst = selector('#_privateId', errors: errors..clear());
   expect(errors.isEmpty, true, reason: errors.toString());
   expect('#_privateId', compactOuptut(selectorAst));
+
+  selectorAst = selector(':host', errors: errors..clear());
+  expect(errors.isEmpty, true, reason: errors.toString());
+  expect(compactOuptut(selectorAst), ':host');
+
+  selectorAst = selector(':host(.foo)', errors: errors..clear());
+  expect(errors.isEmpty, true, reason: errors.toString());
+  expect(compactOuptut(selectorAst), ':host(.foo)');
+
+  selectorAst = selector(':host-context(.foo)', errors: errors..clear());
+  expect(errors.isEmpty, true, reason: errors.toString());
+  expect(compactOuptut(selectorAst), ':host-context(.foo)');
 }
 
 // TODO(terry): Move this failure case to a failure_test.dart when the analyzer