Index: trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSource.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSource.java	(revision 3901)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSource.java	(revision 3902)
@@ -18,4 +18,5 @@
 import org.openstreetmap.josm.gui.mappaint.Range;
 import org.openstreetmap.josm.gui.mappaint.StyleSource;
+import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.GeneralSelector;
 import org.openstreetmap.josm.gui.mappaint.mapcss.parser.MapCSSParser;
 import org.openstreetmap.josm.gui.mappaint.mapcss.parser.ParseException;
@@ -109,11 +110,15 @@
         for (MapCSSRule r : rules) {
             for (Selector s : r.selectors) {
-                if (s.base.equals(type)) {
-                    for (Condition cnd : s.conds) {
-                        if (!cnd.applies(env))
-                            continue NEXT_RULE;
-                    }
-                    for (Instruction i : r.declaration) {
-                        i.execute(env);
+                if ((s instanceof GeneralSelector)) {
+                    GeneralSelector gs = (GeneralSelector) s;
+                    if (gs.base.equals(type))
+                     {
+                        for (Condition cnd : gs.conds) {
+                            if (!cnd.applies(env))
+                                continue NEXT_RULE;
+                        }
+                        for (Instruction i : r.declaration) {
+                            i.execute(env);
+                        }
                     }
                 }
@@ -133,12 +138,12 @@
             for (Selector s : r.selectors) {
                 if (s.applies(env)) {
-                    if (s.range.contains(scale)) {
-                        mc.range = Range.cut(mc.range, s.range);
+                    if (s.getRange().contains(scale)) {
+                        mc.range = Range.cut(mc.range, s.getRange());
                     } else {
-                        mc.range = mc.range.reduceAround(scale, s.range);
+                        mc.range = mc.range.reduceAround(scale, s.getRange());
                         continue;
                     }
 
-                    String sub = s.subpart;
+                    String sub = s.getSubpart();
                     if (sub == null) {
                         sub = "default";
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Selector.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Selector.java	(revision 3901)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Selector.java	(revision 3902)
@@ -4,4 +4,5 @@
 import java.util.List;
 
+import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
@@ -13,78 +14,146 @@
 import org.openstreetmap.josm.tools.Utils;
 
-public class Selector {
-    public String base;
-    public Range range;
-    protected List<Condition> conds;
-    public String subpart;
+public interface Selector {
+    
+    public boolean applies(Environment e);
 
-    public Selector(String base, Pair<Integer, Integer> zoom, List<Condition> conds, String subpart) {
-        this.base = base;
-        if (zoom != null) {
-            int a = zoom.a == null ? 0 : zoom.a;
-            int b = zoom.b == null ? Integer.MAX_VALUE : zoom.b;
-            if (a <= b) {
-                range = fromLevel(a, b);
+    public String getSubpart();
+    public Range getRange();
+
+    public static class DescendentSelector implements Selector {
+        Selector a, b;
+        boolean child;
+
+        public DescendentSelector(Selector a, Selector b, boolean child) {
+            this.a = a;
+            this.b = b;
+            this.child = child;
+        }
+
+        @Override
+        public boolean applies(Environment e) {
+            if (!b.applies(e))
+                return false;
+
+            Environment e2 = new Environment(null, e.mc, e.layer, e.source);
+            if (child) {
+                for (OsmPrimitive osm : e.osm.getReferrers()) {
+                    e2.osm = osm;
+                    if (a.applies(e2))
+                        return true;
+                }
+            } else {
+                if (e.osm instanceof Relation) {
+                    for (OsmPrimitive chld : ((Relation) e.osm).getMemberPrimitives()) {
+                        e2.osm = chld;
+                        if (a.applies(e2))
+                            return true;
+                    }
+                } else if (e.osm instanceof Way) {
+                    for (Node n : ((Way) e.osm).getNodes()) {
+                        e2.osm = n;
+                        if (a.applies(e2))
+                            return true;
+                    }
+                }
             }
+            return false;
         }
-        if (range == null) {
-            range = new Range();
+
+        @Override
+        public String getSubpart() {
+            return b.getSubpart();
         }
-        this.conds = conds;
-        this.subpart = subpart;
+
+        @Override
+        public Range getRange() {
+            return b.getRange();
+        }
     }
 
-    public boolean applies(Environment e) {
-        if (!baseApplies(e.osm))
+    public static class GeneralSelector implements Selector {
+        public String base;
+        public Range range;
+        protected List<Condition> conds;
+        private String subpart;
+
+        public GeneralSelector(String base, Pair<Integer, Integer> zoom, List<Condition> conds, String subpart) {
+            this.base = base;
+            if (zoom != null) {
+                int a = zoom.a == null ? 0 : zoom.a;
+                int b = zoom.b == null ? Integer.MAX_VALUE : zoom.b;
+                if (a <= b) {
+                    range = fromLevel(a, b);
+                }
+            }
+            if (range == null) {
+                range = new Range();
+            }
+            this.conds = conds;
+            this.subpart = subpart;
+        }
+
+        @Override
+        public String getSubpart() {
+            return subpart;
+        }
+        @Override
+        public Range getRange() {
+            return range;
+        }
+
+        @Override
+        public boolean applies(Environment e) {
+            if (!baseApplies(e.osm))
+                return false;
+            for (Condition c : conds) {
+                if (!c.applies(e))
+                    return false;
+            }
+            return true;
+        }
+
+        private boolean baseApplies(OsmPrimitive osm) {
+            if (base.equals("*"))
+                return true;
+            if (base.equals("area")) {
+                if (osm instanceof Way)
+                    return true;
+                if (osm instanceof Relation && ((Relation) osm).isMultipolygon())
+                    return true;
+            }
+            if (base.equals(OsmPrimitiveType.from(osm).getAPIName()))
+                return true;
             return false;
-        for (Condition c : conds) {
-            if (!c.applies(e))
-                return false;
         }
-        return true;
+
+        public static Range fromLevel(int a, int b) {
+            if (a > b)
+                throw new AssertionError();
+            double lower = 0;
+            double upper = Double.POSITIVE_INFINITY;
+            if (b != Integer.MAX_VALUE) {
+                lower = level2scale(b + 1);
+            }
+            if (a != 0) {
+                upper = level2scale(a);
+            }
+            return new Range(lower, upper);
+        }
+
+        final static double R = 6378135;
+
+        public static double level2scale(int lvl) {
+            if (lvl < 0)
+                throw new IllegalArgumentException();
+            // preliminary formula - map such that mapnik imagery tiles of the same
+            // or similar level are displayed at the given scale
+            return 2.0 * Math.PI * R / Math.pow(2.0, lvl) / 2.56;
+        }
+
+        @Override
+        public String toString() {
+            return base + (range == null ? "" : range) + Utils.join("", conds) + (subpart != null ? ("::" + subpart) : "");
+        }
     }
-
-    private boolean baseApplies(OsmPrimitive osm) {
-        if (base.equals("*"))
-            return true;
-        if (base.equals("area")) {
-            if (osm instanceof Way)
-                return true;
-            if (osm instanceof Relation && ((Relation) osm).isMultipolygon())
-                return true;
-        }
-        if (base.equals(OsmPrimitiveType.from(osm).getAPIName()))
-            return true;
-        return false;
-    }
-
-    public static Range fromLevel(int a, int b) {
-        if (a > b)
-            throw new AssertionError();
-        double lower = 0;
-        double upper = Double.POSITIVE_INFINITY;
-        if (b != Integer.MAX_VALUE) {
-            lower = level2scale(b + 1);
-        }
-        if (a != 0) {
-            upper = level2scale(a);
-        }
-        return new Range(lower, upper);
-    }
-
-    final static double R = 6378135;
-
-    public static double level2scale(int lvl) {
-        if (lvl < 0)
-            throw new IllegalArgumentException();
-        // preliminary formula - map such that mapnik imagery tiles of the same
-        // or similar level are displayed at the given scale
-        return 2.0 * Math.PI * R / Math.pow(2.0, lvl) / 2.56;
-    }
-
-    @Override
-    public String toString() {
-        return base + (range == null ? "" : range) + Utils.join("", conds) + (subpart != null ? ("::" + subpart) : "");
-    }
-
 }
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/parser/MapCSSParser.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/parser/MapCSSParser.java	(revision 3901)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/parser/MapCSSParser.java	(revision 3902)
@@ -14,4 +14,6 @@
 import org.openstreetmap.josm.gui.mappaint.mapcss.Expression.FunctionExpression;
 import org.openstreetmap.josm.gui.mappaint.mapcss.Expression.LiteralExpression;
+import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.DescendentSelector;
+import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.GeneralSelector;
 import org.openstreetmap.josm.tools.Pair;
 
@@ -229,7 +231,6 @@
     Selector sel;
     List<Instruction> decl;
-    sel = selector();
-                     selectors.add(sel);
-    w();
+    sel = child_selector();
+                           selectors.add(sel);
     label_4:
     while (true) {
@@ -244,10 +245,43 @@
       jj_consume_token(COMMA);
       w();
-      sel = selector();
-                         selectors.add(sel);
-      w();
+      sel = child_selector();
+                               selectors.add(sel);
     }
     decl = declaration();
       {if (true) return new MapCSSRule(selectors, decl);}
+    throw new Error("Missing return statement in function");
+  }
+
+  final public Selector child_selector() throws ParseException {
+    boolean child = false;
+    Selector sel1, sel2 = null;
+    sel1 = selector();
+    w();
+    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+    case GREATER:
+    case LESS:
+      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+      case GREATER:
+        jj_consume_token(GREATER);
+                      child = true;
+        break;
+      case LESS:
+        jj_consume_token(LESS);
+                                                 child = false;
+        break;
+      default:
+        jj_la1[9] = jj_gen;
+        jj_consume_token(-1);
+        throw new ParseException();
+      }
+      w();
+      sel2 = selector();
+      w();
+      break;
+    default:
+      jj_la1[10] = jj_gen;
+      ;
+    }
+      {if (true) return sel2 != null ? new DescendentSelector(sel1, sel2, child) : sel1;}
     throw new Error("Missing return statement in function");
   }
@@ -267,5 +301,5 @@
       break;
     default:
-      jj_la1[9] = jj_gen;
+      jj_la1[11] = jj_gen;
       jj_consume_token(-1);
       throw new ParseException();
@@ -276,5 +310,5 @@
       break;
     default:
-      jj_la1[10] = jj_gen;
+      jj_la1[12] = jj_gen;
       ;
     }
@@ -288,5 +322,5 @@
         break;
       default:
-        jj_la1[11] = jj_gen;
+        jj_la1[13] = jj_gen;
         break label_5;
       }
@@ -300,5 +334,5 @@
         break;
       default:
-        jj_la1[12] = jj_gen;
+        jj_la1[14] = jj_gen;
         jj_consume_token(-1);
         throw new ParseException();
@@ -311,8 +345,8 @@
       break;
     default:
-      jj_la1[13] = jj_gen;
+      jj_la1[15] = jj_gen;
       ;
     }
-      {if (true) return new Selector(base.image, r, conditions, sub);}
+      {if (true) return new GeneralSelector(base.image, r, conditions, sub);}
     throw new Error("Missing return statement in function");
   }
@@ -337,15 +371,15 @@
           break;
         default:
-          jj_la1[14] = jj_gen;
+          jj_la1[16] = jj_gen;
           ;
         }
         break;
       default:
-        jj_la1[15] = jj_gen;
+        jj_la1[17] = jj_gen;
         ;
       }
       break;
     default:
-      jj_la1[16] = jj_gen;
+      jj_la1[18] = jj_gen;
       jj_consume_token(-1);
       throw new ParseException();
@@ -359,9 +393,9 @@
     Expression e;
     jj_consume_token(LSQUARE);
-    if (jj_2_1(3)) {
+    if (jj_2_1(2147483647)) {
       c = simple_key_condition();
       jj_consume_token(RSQUARE);
                                                  {if (true) return c;}
-    } else if (jj_2_2(5)) {
+    } else if (jj_2_2(2147483647)) {
       c = simple_key_value_condition();
       jj_consume_token(RSQUARE);
@@ -383,8 +417,43 @@
         break;
       default:
-        jj_la1[17] = jj_gen;
+        jj_la1[19] = jj_gen;
         jj_consume_token(-1);
         throw new ParseException();
       }
+    }
+    throw new Error("Missing return statement in function");
+  }
+
+  final public String tag_key() throws ParseException {
+    String s;
+    Token t;
+    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+    case STRING:
+      s = string();
+                     {if (true) return s;}
+      break;
+    case IDENT:
+      t = jj_consume_token(IDENT);
+                    s = t.image;
+      label_6:
+      while (true) {
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case COLON:
+          ;
+          break;
+        default:
+          jj_la1[20] = jj_gen;
+          break label_6;
+        }
+        jj_consume_token(COLON);
+        t = jj_consume_token(IDENT);
+                                                         s += ':' + t.image;
+      }
+                                                                                    {if (true) return s;}
+      break;
+    default:
+      jj_la1[21] = jj_gen;
+      jj_consume_token(-1);
+      throw new ParseException();
     }
     throw new Error("Missing return statement in function");
@@ -401,8 +470,8 @@
       break;
     default:
-      jj_la1[18] = jj_gen;
+      jj_la1[22] = jj_gen;
       ;
     }
-    key = string_or_ident();
+    key = tag_key();
     switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
     case QUESTION:
@@ -411,5 +480,5 @@
       break;
     default:
-      jj_la1[19] = jj_gen;
+      jj_la1[23] = jj_gen;
       ;
     }
@@ -423,5 +492,5 @@
     float f;
     Condition.Op op;
-    key = string_or_ident();
+    key = tag_key();
     switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
     case STAR:
@@ -452,5 +521,5 @@
           break;
         default:
-          jj_la1[20] = jj_gen;
+          jj_la1[24] = jj_gen;
           jj_consume_token(-1);
           throw new ParseException();
@@ -482,5 +551,5 @@
         break;
       default:
-        jj_la1[21] = jj_gen;
+        jj_la1[25] = jj_gen;
         jj_consume_token(-1);
         throw new ParseException();
@@ -510,5 +579,5 @@
         break;
       default:
-        jj_la1[22] = jj_gen;
+        jj_la1[26] = jj_gen;
         jj_consume_token(-1);
         throw new ParseException();
@@ -518,5 +587,5 @@
       break;
     default:
-      jj_la1[23] = jj_gen;
+      jj_la1[27] = jj_gen;
       jj_consume_token(-1);
       throw new ParseException();
@@ -534,5 +603,5 @@
       break;
     default:
-      jj_la1[24] = jj_gen;
+      jj_la1[28] = jj_gen;
       ;
     }
@@ -554,5 +623,5 @@
       break;
     default:
-      jj_la1[25] = jj_gen;
+      jj_la1[29] = jj_gen;
       jj_consume_token(-1);
       throw new ParseException();
@@ -569,5 +638,5 @@
     jj_consume_token(LBRACE);
     w();
-    label_6:
+    label_7:
     while (true) {
       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
@@ -576,6 +645,6 @@
         break;
       default:
-        jj_la1[26] = jj_gen;
-        break label_6;
+        jj_la1[30] = jj_gen;
+        break label_7;
       }
       key = jj_consume_token(IDENT);
@@ -597,5 +666,5 @@
           break;
         default:
-          jj_la1[27] = jj_gen;
+          jj_la1[31] = jj_gen;
           jj_consume_token(-1);
           throw new ParseException();
@@ -614,5 +683,5 @@
           break;
         default:
-          jj_la1[28] = jj_gen;
+          jj_la1[32] = jj_gen;
           jj_consume_token(-1);
           throw new ParseException();
@@ -675,5 +744,5 @@
         switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
         case PLUS:
-          label_7:
+          label_8:
           while (true) {
             jj_consume_token(PLUS);
@@ -688,11 +757,11 @@
               break;
             default:
-              jj_la1[29] = jj_gen;
-              break label_7;
+              jj_la1[33] = jj_gen;
+              break label_8;
             }
           }
           break;
         case STAR:
-          label_8:
+          label_9:
           while (true) {
             jj_consume_token(STAR);
@@ -707,11 +776,11 @@
               break;
             default:
-              jj_la1[30] = jj_gen;
-              break label_8;
+              jj_la1[34] = jj_gen;
+              break label_9;
             }
           }
           break;
         case MINUS:
-          label_9:
+          label_10:
           while (true) {
             jj_consume_token(MINUS);
@@ -726,11 +795,11 @@
               break;
             default:
-              jj_la1[31] = jj_gen;
-              break label_9;
+              jj_la1[35] = jj_gen;
+              break label_10;
             }
           }
           break;
         case SLASH:
-          label_10:
+          label_11:
           while (true) {
             jj_consume_token(SLASH);
@@ -745,6 +814,6 @@
               break;
             default:
-              jj_la1[32] = jj_gen;
-              break label_10;
+              jj_la1[36] = jj_gen;
+              break label_11;
             }
           }
@@ -781,5 +850,5 @@
             break;
           default:
-            jj_la1[33] = jj_gen;
+            jj_la1[37] = jj_gen;
             ;
           }
@@ -830,5 +899,5 @@
           break;
         default:
-          jj_la1[34] = jj_gen;
+          jj_la1[38] = jj_gen;
           jj_consume_token(-1);
           throw new ParseException();
@@ -836,10 +905,10 @@
         break;
       default:
-        jj_la1[35] = jj_gen;
+        jj_la1[39] = jj_gen;
         ;
       }
       break;
     default:
-      jj_la1[36] = jj_gen;
+      jj_la1[40] = jj_gen;
       jj_consume_token(-1);
       throw new ParseException();
@@ -878,5 +947,5 @@
         break;
       default:
-        jj_la1[37] = jj_gen;
+        jj_la1[41] = jj_gen;
         jj_consume_token(-1);
         throw new ParseException();
@@ -908,5 +977,5 @@
       arg = expression();
                            args.add(arg);
-      label_11:
+      label_12:
       while (true) {
         switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
@@ -915,6 +984,6 @@
           break;
         default:
-          jj_la1[38] = jj_gen;
-          break label_11;
+          jj_la1[42] = jj_gen;
+          break label_12;
         }
         jj_consume_token(COMMA);
@@ -925,5 +994,5 @@
       break;
     default:
-      jj_la1[39] = jj_gen;
+      jj_la1[43] = jj_gen;
       ;
     }
@@ -964,5 +1033,5 @@
       break;
     default:
-      jj_la1[40] = jj_gen;
+      jj_la1[44] = jj_gen;
       jj_consume_token(-1);
       throw new ParseException();
@@ -1048,21 +1117,615 @@
   }
 
-  private boolean jj_3R_30() {
-    if (jj_3R_46()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_25() {
+  private boolean jj_3R_69() {
+    if (jj_3R_47()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_26() {
     Token xsp;
     xsp = jj_scanpos;
     if (jj_scan_token(9)) {
     jj_scanpos = xsp;
+    if (jj_3R_44()) return true;
+    }
+    return false;
+  }
+
+  private boolean jj_3R_16() {
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_26()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private boolean jj_3R_37() {
+    if (jj_scan_token(STAR)) return true;
+    if (jj_scan_token(EQUAL)) return true;
+    if (jj_3R_49()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_51() {
+    if (jj_3R_49()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_36() {
+    if (jj_scan_token(DOLLAR)) return true;
+    if (jj_scan_token(EQUAL)) return true;
+    if (jj_3R_49()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_35() {
+    if (jj_scan_token(CARET)) return true;
+    if (jj_scan_token(EQUAL)) return true;
+    if (jj_3R_49()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_23() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_38()) {
+    jj_scanpos = xsp;
+    if (jj_3R_39()) {
+    jj_scanpos = xsp;
+    if (jj_3R_40()) {
+    jj_scanpos = xsp;
+    if (jj_3R_41()) return true;
+    }
+    }
+    }
+    if (jj_3R_42()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_50() {
+    if (jj_scan_token(TILDE)) return true;
+    if (jj_3R_70()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_34() {
+    if (jj_scan_token(TILDE)) return true;
+    if (jj_scan_token(EQUAL)) return true;
+    if (jj_3R_49()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_43() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_scan_token(9)) jj_scanpos = xsp;
+    return false;
+  }
+
+  private boolean jj_3R_53() {
+    if (jj_3R_24()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_33() {
+    if (jj_scan_token(EQUAL)) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_50()) {
+    jj_scanpos = xsp;
+    if (jj_3R_51()) return true;
+    }
+    return false;
+  }
+
+  private boolean jj_3R_32() {
+    if (jj_scan_token(EXCLAMATION)) return true;
+    if (jj_scan_token(EQUAL)) return true;
+    if (jj_3R_49()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_70() {
+    if (jj_scan_token(REGEX)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_22() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_32()) {
+    jj_scanpos = xsp;
+    if (jj_3R_33()) {
+    jj_scanpos = xsp;
+    if (jj_3R_34()) {
+    jj_scanpos = xsp;
+    if (jj_3R_35()) {
+    jj_scanpos = xsp;
+    if (jj_3R_36()) {
+    jj_scanpos = xsp;
+    if (jj_3R_37()) return true;
+    }
+    }
+    }
+    }
+    }
+    return false;
+  }
+
+  private boolean jj_3R_48() {
+    if (jj_scan_token(COLON)) return true;
+    if (jj_scan_token(IDENT)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_49() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_68()) {
+    jj_scanpos = xsp;
+    if (jj_3R_69()) return true;
+    }
+    return false;
+  }
+
+  private boolean jj_3R_68() {
+    if (jj_scan_token(IDENT)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_14() {
+    if (jj_3R_20()) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_22()) {
+    jj_scanpos = xsp;
+    if (jj_3R_23()) return true;
+    }
+    return false;
+  }
+
+  private boolean jj_3R_80() {
+    if (jj_scan_token(HEXCOLOR)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_47() {
+    if (jj_scan_token(STRING)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_79() {
+    if (jj_3R_24()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_78() {
+    if (jj_scan_token(PLUS)) return true;
+    if (jj_3R_24()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_71() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_77()) {
+    jj_scanpos = xsp;
+    if (jj_3R_78()) {
+    jj_scanpos = xsp;
+    if (jj_3R_79()) {
+    jj_scanpos = xsp;
+    if (jj_3R_80()) return true;
+    }
+    }
+    }
+    return false;
+  }
+
+  private boolean jj_3R_77() {
+    if (jj_3R_49()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_21() {
+    if (jj_scan_token(QUESTION)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_42() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_52()) {
+    jj_scanpos = xsp;
+    if (jj_3R_53()) return true;
+    }
+    return false;
+  }
+
+  private boolean jj_3R_52() {
+    if (jj_scan_token(MINUS)) return true;
+    if (jj_3R_24()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_19() {
+    if (jj_scan_token(EXCLAMATION)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_13() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_19()) jj_scanpos = xsp;
+    if (jj_3R_20()) return true;
+    xsp = jj_scanpos;
+    if (jj_3R_21()) jj_scanpos = xsp;
+    return false;
+  }
+
+  private boolean jj_3R_81() {
+    if (jj_scan_token(COMMA)) return true;
+    if (jj_3R_16()) return true;
+    if (jj_3R_17()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_24() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_scan_token(3)) {
+    jj_scanpos = xsp;
+    if (jj_scan_token(2)) return true;
+    }
+    return false;
+  }
+
+  private boolean jj_3R_31() {
+    if (jj_scan_token(IDENT)) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_48()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private boolean jj_3R_30() {
+    if (jj_3R_47()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_20() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_30()) {
+    jj_scanpos = xsp;
+    if (jj_3R_31()) return true;
+    }
+    return false;
+  }
+
+  private boolean jj_3R_76() {
+    if (jj_3R_17()) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_81()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private boolean jj_3_2() {
+    if (jj_3R_14()) return true;
+    if (jj_scan_token(RSQUARE)) return true;
+    return false;
+  }
+
+  private boolean jj_3_1() {
+    if (jj_3R_13()) return true;
+    if (jj_scan_token(RSQUARE)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_18() {
+    if (jj_scan_token(IDENT)) return true;
+    if (jj_3R_16()) return true;
+    if (jj_scan_token(LPAR)) return true;
+    if (jj_3R_16()) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_76()) jj_scanpos = xsp;
+    if (jj_scan_token(RPAR)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_55() {
+    if (jj_scan_token(LPAR)) return true;
+    if (jj_3R_16()) return true;
+    if (jj_3R_17()) return true;
+    if (jj_scan_token(RPAR)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_54() {
+    if (jj_3R_71()) return true;
+    return false;
+  }
+
+  private boolean jj_3_5() {
+    if (jj_3R_18()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_45() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3_5()) {
+    jj_scanpos = xsp;
+    if (jj_3R_54()) {
+    jj_scanpos = xsp;
+    if (jj_3R_55()) return true;
+    }
+    }
+    return false;
+  }
+
+  private boolean jj_3R_67() {
+    if (jj_scan_token(QUESTION)) return true;
+    if (jj_3R_16()) return true;
+    if (jj_3R_45()) return true;
+    if (jj_3R_16()) return true;
+    if (jj_scan_token(COLON)) return true;
+    if (jj_3R_16()) return true;
+    if (jj_3R_45()) return true;
+    if (jj_3R_16()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_66() {
+    if (jj_scan_token(PIPE)) return true;
+    if (jj_scan_token(PIPE)) return true;
+    if (jj_3R_16()) return true;
+    if (jj_3R_45()) return true;
+    if (jj_3R_16()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_65() {
+    if (jj_scan_token(AMPERSAND)) return true;
+    if (jj_scan_token(AMPERSAND)) return true;
+    if (jj_3R_16()) return true;
+    if (jj_3R_45()) return true;
+    if (jj_3R_16()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_64() {
+    if (jj_scan_token(LESS)) return true;
+    if (jj_3R_16()) return true;
+    if (jj_3R_45()) return true;
+    if (jj_3R_16()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_63() {
+    if (jj_scan_token(EQUAL)) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_scan_token(22)) jj_scanpos = xsp;
+    if (jj_3R_16()) return true;
+    if (jj_3R_45()) return true;
+    if (jj_3R_16()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_62() {
+    if (jj_scan_token(GREATER)) return true;
+    if (jj_3R_16()) return true;
+    if (jj_3R_45()) return true;
+    if (jj_3R_16()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_61() {
+    if (jj_scan_token(LESS_EQUAL)) return true;
+    if (jj_3R_16()) return true;
+    if (jj_3R_45()) return true;
+    if (jj_3R_16()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_60() {
+    if (jj_scan_token(GREATER_EQUAL)) return true;
+    if (jj_3R_16()) return true;
+    if (jj_3R_45()) return true;
+    if (jj_3R_16()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_75() {
+    if (jj_scan_token(SLASH)) return true;
+    if (jj_3R_16()) return true;
+    if (jj_3R_45()) return true;
+    if (jj_3R_16()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_59() {
+    Token xsp;
+    if (jj_3R_75()) return true;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_75()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private boolean jj_3R_74() {
+    if (jj_scan_token(MINUS)) return true;
+    if (jj_3R_16()) return true;
+    if (jj_3R_45()) return true;
+    if (jj_3R_16()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_58() {
+    Token xsp;
+    if (jj_3R_74()) return true;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_74()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private boolean jj_3R_73() {
+    if (jj_scan_token(STAR)) return true;
+    if (jj_3R_16()) return true;
+    if (jj_3R_45()) return true;
+    if (jj_3R_16()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_57() {
+    Token xsp;
+    if (jj_3R_73()) return true;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_73()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private boolean jj_3R_72() {
+    if (jj_scan_token(PLUS)) return true;
+    if (jj_3R_16()) return true;
+    if (jj_3R_45()) return true;
+    if (jj_3R_16()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_46() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_56()) {
+    jj_scanpos = xsp;
+    if (jj_3R_57()) {
+    jj_scanpos = xsp;
+    if (jj_3R_58()) {
+    jj_scanpos = xsp;
+    if (jj_3R_59()) {
+    jj_scanpos = xsp;
+    if (jj_3R_60()) {
+    jj_scanpos = xsp;
+    if (jj_3R_61()) {
+    jj_scanpos = xsp;
+    if (jj_3R_62()) {
+    jj_scanpos = xsp;
+    if (jj_3R_63()) {
+    jj_scanpos = xsp;
+    if (jj_3R_64()) {
+    jj_scanpos = xsp;
+    if (jj_3R_65()) {
+    jj_scanpos = xsp;
+    if (jj_3R_66()) {
+    jj_scanpos = xsp;
+    if (jj_3R_67()) return true;
+    }
+    }
+    }
+    }
+    }
+    }
+    }
+    }
+    }
+    }
+    }
+    return false;
+  }
+
+  private boolean jj_3R_56() {
+    Token xsp;
+    if (jj_3R_72()) return true;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_72()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private boolean jj_3R_29() {
+    if (jj_3R_45()) return true;
+    if (jj_3R_16()) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_46()) jj_scanpos = xsp;
+    return false;
+  }
+
+  private boolean jj_3R_28() {
+    if (jj_scan_token(MINUS)) return true;
+    if (jj_3R_16()) return true;
+    if (jj_3R_45()) return true;
+    if (jj_3R_16()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_27() {
+    if (jj_scan_token(EXCLAMATION)) return true;
+    if (jj_3R_16()) return true;
+    if (jj_3R_45()) return true;
+    if (jj_3R_16()) return true;
+    return false;
+  }
+
+  private boolean jj_3_4() {
+    if (jj_3R_17()) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_scan_token(27)) {
+    jj_scanpos = xsp;
+    if (jj_scan_token(13)) return true;
+    }
+    return false;
+  }
+
+  private boolean jj_3R_17() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_27()) {
+    jj_scanpos = xsp;
+    if (jj_3R_28()) {
+    jj_scanpos = xsp;
+    if (jj_3R_29()) return true;
+    }
+    }
+    return false;
+  }
+
+  private boolean jj_3_3() {
+    if (jj_3R_15()) return true;
+    if (jj_3R_16()) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_scan_token(27)) {
+    jj_scanpos = xsp;
+    if (jj_scan_token(13)) return true;
+    }
+    return false;
+  }
+
+  private boolean jj_3R_25() {
+    if (jj_scan_token(COMMA)) return true;
     if (jj_3R_43()) return true;
-    }
+    if (jj_3R_24()) return true;
     return false;
   }
 
   private boolean jj_3R_15() {
-    Token xsp;
+    if (jj_3R_24()) return true;
+    Token xsp;
+    if (jj_3R_25()) return true;
     while (true) {
       xsp = jj_scanpos;
@@ -1072,570 +1735,10 @@
   }
 
-  private boolean jj_3R_52() {
-    if (jj_scan_token(LPAR)) return true;
-    if (jj_3R_15()) return true;
-    if (jj_3R_16()) return true;
-    if (jj_scan_token(RPAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_51() {
-    if (jj_3R_66()) return true;
+  private boolean jj_3R_41() {
+    if (jj_scan_token(LESS)) return true;
     return false;
   }
 
   private boolean jj_3R_44() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3_5()) {
-    jj_scanpos = xsp;
-    if (jj_3R_51()) {
-    jj_scanpos = xsp;
-    if (jj_3R_52()) return true;
-    }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_42() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_scan_token(9)) jj_scanpos = xsp;
-    return false;
-  }
-
-  private boolean jj_3_5() {
-    if (jj_3R_17()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_50() {
-    if (jj_3R_23()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_64() {
-    if (jj_scan_token(QUESTION)) return true;
-    if (jj_3R_15()) return true;
-    if (jj_3R_44()) return true;
-    if (jj_3R_15()) return true;
-    if (jj_scan_token(COLON)) return true;
-    if (jj_3R_15()) return true;
-    if (jj_3R_44()) return true;
-    if (jj_3R_15()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_63() {
-    if (jj_scan_token(PIPE)) return true;
-    if (jj_scan_token(PIPE)) return true;
-    if (jj_3R_15()) return true;
-    if (jj_3R_44()) return true;
-    if (jj_3R_15()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_40() {
-    if (jj_scan_token(LESS)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_62() {
-    if (jj_scan_token(AMPERSAND)) return true;
-    if (jj_scan_token(AMPERSAND)) return true;
-    if (jj_3R_15()) return true;
-    if (jj_3R_44()) return true;
-    if (jj_3R_15()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_39() {
-    if (jj_scan_token(LESS_EQUAL)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_61() {
-    if (jj_scan_token(LESS)) return true;
-    if (jj_3R_15()) return true;
-    if (jj_3R_44()) return true;
-    if (jj_3R_15()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_38() {
-    if (jj_scan_token(GREATER)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_60() {
-    if (jj_scan_token(EQUAL)) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_scan_token(22)) jj_scanpos = xsp;
-    if (jj_3R_15()) return true;
-    if (jj_3R_44()) return true;
-    if (jj_3R_15()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_37() {
-    if (jj_scan_token(GREATER_EQUAL)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_65() {
-    if (jj_scan_token(REGEX)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_59() {
-    if (jj_scan_token(GREATER)) return true;
-    if (jj_3R_15()) return true;
-    if (jj_3R_44()) return true;
-    if (jj_3R_15()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_58() {
-    if (jj_scan_token(LESS_EQUAL)) return true;
-    if (jj_3R_15()) return true;
-    if (jj_3R_44()) return true;
-    if (jj_3R_15()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_36() {
-    if (jj_scan_token(STAR)) return true;
-    if (jj_scan_token(EQUAL)) return true;
-    if (jj_3R_19()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_70() {
-    if (jj_scan_token(SLASH)) return true;
-    if (jj_3R_15()) return true;
-    if (jj_3R_44()) return true;
-    if (jj_3R_15()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_57() {
-    if (jj_scan_token(GREATER_EQUAL)) return true;
-    if (jj_3R_15()) return true;
-    if (jj_3R_44()) return true;
-    if (jj_3R_15()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_48() {
-    if (jj_3R_19()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_35() {
-    if (jj_scan_token(DOLLAR)) return true;
-    if (jj_scan_token(EQUAL)) return true;
-    if (jj_3R_19()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_69() {
-    if (jj_scan_token(MINUS)) return true;
-    if (jj_3R_15()) return true;
-    if (jj_3R_44()) return true;
-    if (jj_3R_15()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_56() {
-    Token xsp;
-    if (jj_3R_70()) return true;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_70()) { jj_scanpos = xsp; break; }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_47() {
-    if (jj_scan_token(TILDE)) return true;
-    if (jj_3R_65()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_19() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_29()) {
-    jj_scanpos = xsp;
-    if (jj_3R_30()) return true;
-    }
-    return false;
-  }
-
-  private boolean jj_3R_29() {
-    if (jj_scan_token(IDENT)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_22() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_37()) {
-    jj_scanpos = xsp;
-    if (jj_3R_38()) {
-    jj_scanpos = xsp;
-    if (jj_3R_39()) {
-    jj_scanpos = xsp;
-    if (jj_3R_40()) return true;
-    }
-    }
-    }
-    if (jj_3R_41()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_34() {
-    if (jj_scan_token(CARET)) return true;
-    if (jj_scan_token(EQUAL)) return true;
-    if (jj_3R_19()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_68() {
-    if (jj_scan_token(STAR)) return true;
-    if (jj_3R_15()) return true;
-    if (jj_3R_44()) return true;
-    if (jj_3R_15()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_55() {
-    Token xsp;
-    if (jj_3R_69()) return true;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_69()) { jj_scanpos = xsp; break; }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_33() {
-    if (jj_scan_token(TILDE)) return true;
-    if (jj_scan_token(EQUAL)) return true;
-    if (jj_3R_19()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_67() {
-    if (jj_scan_token(PLUS)) return true;
-    if (jj_3R_15()) return true;
-    if (jj_3R_44()) return true;
-    if (jj_3R_15()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_54() {
-    Token xsp;
-    if (jj_3R_68()) return true;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_68()) { jj_scanpos = xsp; break; }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_53() {
-    Token xsp;
-    if (jj_3R_67()) return true;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_67()) { jj_scanpos = xsp; break; }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_45() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_53()) {
-    jj_scanpos = xsp;
-    if (jj_3R_54()) {
-    jj_scanpos = xsp;
-    if (jj_3R_55()) {
-    jj_scanpos = xsp;
-    if (jj_3R_56()) {
-    jj_scanpos = xsp;
-    if (jj_3R_57()) {
-    jj_scanpos = xsp;
-    if (jj_3R_58()) {
-    jj_scanpos = xsp;
-    if (jj_3R_59()) {
-    jj_scanpos = xsp;
-    if (jj_3R_60()) {
-    jj_scanpos = xsp;
-    if (jj_3R_61()) {
-    jj_scanpos = xsp;
-    if (jj_3R_62()) {
-    jj_scanpos = xsp;
-    if (jj_3R_63()) {
-    jj_scanpos = xsp;
-    if (jj_3R_64()) return true;
-    }
-    }
-    }
-    }
-    }
-    }
-    }
-    }
-    }
-    }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_46() {
-    if (jj_scan_token(STRING)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_32() {
-    if (jj_scan_token(EQUAL)) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_47()) {
-    jj_scanpos = xsp;
-    if (jj_3R_48()) return true;
-    }
-    return false;
-  }
-
-  private boolean jj_3R_31() {
-    if (jj_scan_token(EXCLAMATION)) return true;
-    if (jj_scan_token(EQUAL)) return true;
-    if (jj_3R_19()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_49() {
-    if (jj_scan_token(MINUS)) return true;
-    if (jj_3R_23()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_41() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_49()) {
-    jj_scanpos = xsp;
-    if (jj_3R_50()) return true;
-    }
-    return false;
-  }
-
-  private boolean jj_3R_28() {
-    if (jj_3R_44()) return true;
-    if (jj_3R_15()) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_45()) jj_scanpos = xsp;
-    return false;
-  }
-
-  private boolean jj_3R_21() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_31()) {
-    jj_scanpos = xsp;
-    if (jj_3R_32()) {
-    jj_scanpos = xsp;
-    if (jj_3R_33()) {
-    jj_scanpos = xsp;
-    if (jj_3R_34()) {
-    jj_scanpos = xsp;
-    if (jj_3R_35()) {
-    jj_scanpos = xsp;
-    if (jj_3R_36()) return true;
-    }
-    }
-    }
-    }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_27() {
-    if (jj_scan_token(MINUS)) return true;
-    if (jj_3R_15()) return true;
-    if (jj_3R_44()) return true;
-    if (jj_3R_15()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_26() {
-    if (jj_scan_token(EXCLAMATION)) return true;
-    if (jj_3R_15()) return true;
-    if (jj_3R_44()) return true;
-    if (jj_3R_15()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_23() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_scan_token(3)) {
-    jj_scanpos = xsp;
-    if (jj_scan_token(2)) return true;
-    }
-    return false;
-  }
-
-  private boolean jj_3R_16() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_26()) {
-    jj_scanpos = xsp;
-    if (jj_3R_27()) {
-    jj_scanpos = xsp;
-    if (jj_3R_28()) return true;
-    }
-    }
-    return false;
-  }
-
-  private boolean jj_3_4() {
-    if (jj_3R_16()) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_scan_token(27)) {
-    jj_scanpos = xsp;
-    if (jj_scan_token(13)) return true;
-    }
-    return false;
-  }
-
-  private boolean jj_3R_13() {
-    if (jj_3R_19()) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_21()) {
-    jj_scanpos = xsp;
-    if (jj_3R_22()) return true;
-    }
-    return false;
-  }
-
-  private boolean jj_3R_75() {
-    if (jj_scan_token(HEXCOLOR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_74() {
-    if (jj_3R_23()) return true;
-    return false;
-  }
-
-  private boolean jj_3_3() {
-    if (jj_3R_14()) return true;
-    if (jj_3R_15()) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_scan_token(27)) {
-    jj_scanpos = xsp;
-    if (jj_scan_token(13)) return true;
-    }
-    return false;
-  }
-
-  private boolean jj_3R_73() {
-    if (jj_scan_token(PLUS)) return true;
-    if (jj_3R_23()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_72() {
-    if (jj_3R_19()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_66() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_72()) {
-    jj_scanpos = xsp;
-    if (jj_3R_73()) {
-    jj_scanpos = xsp;
-    if (jj_3R_74()) {
-    jj_scanpos = xsp;
-    if (jj_3R_75()) return true;
-    }
-    }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_20() {
-    if (jj_scan_token(QUESTION)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_18() {
-    if (jj_scan_token(EXCLAMATION)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_12() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_18()) jj_scanpos = xsp;
-    if (jj_3R_19()) return true;
-    xsp = jj_scanpos;
-    if (jj_3R_20()) jj_scanpos = xsp;
-    return false;
-  }
-
-  private boolean jj_3R_24() {
-    if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_42()) return true;
-    if (jj_3R_23()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_76() {
-    if (jj_scan_token(COMMA)) return true;
-    if (jj_3R_15()) return true;
-    if (jj_3R_16()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_71() {
-    if (jj_3R_16()) return true;
-    Token xsp;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_76()) { jj_scanpos = xsp; break; }
-    }
-    return false;
-  }
-
-  private boolean jj_3R_14() {
-    if (jj_3R_23()) return true;
-    Token xsp;
-    if (jj_3R_24()) return true;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_24()) { jj_scanpos = xsp; break; }
-    }
-    return false;
-  }
-
-  private boolean jj_3_2() {
-    if (jj_3R_13()) return true;
-    if (jj_scan_token(RSQUARE)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_43() {
     if (jj_scan_token(COMMENT_START)) return true;
     if (jj_scan_token(COMMENT_END)) return true;
@@ -1643,19 +1746,16 @@
   }
 
-  private boolean jj_3_1() {
-    if (jj_3R_12()) return true;
-    if (jj_scan_token(RSQUARE)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_17() {
-    if (jj_scan_token(IDENT)) return true;
-    if (jj_3R_15()) return true;
-    if (jj_scan_token(LPAR)) return true;
-    if (jj_3R_15()) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_71()) jj_scanpos = xsp;
-    if (jj_scan_token(RPAR)) return true;
+  private boolean jj_3R_40() {
+    if (jj_scan_token(LESS_EQUAL)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_39() {
+    if (jj_scan_token(GREATER)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_38() {
+    if (jj_scan_token(GREATER_EQUAL)) return true;
     return false;
   }
@@ -1672,5 +1772,5 @@
   private int jj_la;
   private int jj_gen;
-  final private int[] jj_la1 = new int[41];
+  final private int[] jj_la1 = new int[45];
   static private int[] jj_la1_0;
   static private int[] jj_la1_1;
@@ -1680,8 +1780,8 @@
    }
    private static void jj_la1_init_0() {
-      jj_la1_0 = new int[] {0xc,0xc,0x12,0x200,0x200,0x200,0x10000000,0x402,0x10000000,0x402,0x40000000,0x2804000,0x2804000,0x4000000,0x4,0x0,0x4,0x8081011e,0x800000,0x0,0x1000012,0x1c00400,0x3c0000,0x1fc0400,0x800000,0x402,0x2,0x8002000,0x8002000,0x80000000,0x400,0x0,0x800,0x400000,0xa07c0c00,0xa07c0c00,0x8081011e,0x8001011e,0x10000000,0x8081011e,0x8000011e,};
+      jj_la1_0 = new int[] {0xc,0xc,0x12,0x200,0x200,0x200,0x10000000,0x402,0x10000000,0x300000,0x300000,0x402,0x40000000,0x2804000,0x2804000,0x4000000,0x4,0x0,0x4,0x8081011e,0x2000000,0x12,0x800000,0x0,0x1000012,0x1c00400,0x3c0000,0x1fc0400,0x800000,0x402,0x2,0x8002000,0x8002000,0x80000000,0x400,0x0,0x800,0x400000,0xa07c0c00,0xa07c0c00,0x8081011e,0x8001011e,0x10000000,0x8081011e,0x8000011e,};
    }
    private static void jj_la1_init_1() {
-      jj_la1_1 = new int[] {0x0,0x1,0x0,0x0,0x20,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x0,0x4,0x0,0x18,0x0,0x18,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x7,0x7,0x1,0x0,0x0,0x1,0x0,};
+      jj_la1_1 = new int[] {0x0,0x1,0x0,0x0,0x20,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x0,0x0,0x0,0x4,0x0,0x18,0x0,0x18,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x7,0x7,0x1,0x0,0x0,0x1,0x0,};
    }
   final private JJCalls[] jj_2_rtns = new JJCalls[5];
@@ -1700,5 +1800,5 @@
     jj_ntk = -1;
     jj_gen = 0;
-    for (int i = 0; i < 41; i++) jj_la1[i] = -1;
+    for (int i = 0; i < 45; i++) jj_la1[i] = -1;
     for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
   }
@@ -1715,5 +1815,5 @@
     jj_ntk = -1;
     jj_gen = 0;
-    for (int i = 0; i < 41; i++) jj_la1[i] = -1;
+    for (int i = 0; i < 45; i++) jj_la1[i] = -1;
     for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
   }
@@ -1726,5 +1826,5 @@
     jj_ntk = -1;
     jj_gen = 0;
-    for (int i = 0; i < 41; i++) jj_la1[i] = -1;
+    for (int i = 0; i < 45; i++) jj_la1[i] = -1;
     for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
   }
@@ -1737,5 +1837,5 @@
     jj_ntk = -1;
     jj_gen = 0;
-    for (int i = 0; i < 41; i++) jj_la1[i] = -1;
+    for (int i = 0; i < 45; i++) jj_la1[i] = -1;
     for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
   }
@@ -1747,5 +1847,5 @@
     jj_ntk = -1;
     jj_gen = 0;
-    for (int i = 0; i < 41; i++) jj_la1[i] = -1;
+    for (int i = 0; i < 45; i++) jj_la1[i] = -1;
     for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
   }
@@ -1757,5 +1857,5 @@
     jj_ntk = -1;
     jj_gen = 0;
-    for (int i = 0; i < 41; i++) jj_la1[i] = -1;
+    for (int i = 0; i < 45; i++) jj_la1[i] = -1;
     for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
   }
@@ -1874,5 +1974,5 @@
       jj_kind = -1;
     }
-    for (int i = 0; i < 41; i++) {
+    for (int i = 0; i < 45; i++) {
       if (jj_la1[i] == jj_gen) {
         for (int j = 0; j < 32; j++) {
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/parser/MapCSSParser.jj
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/parser/MapCSSParser.jj	(revision 3901)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/parser/MapCSSParser.jj	(revision 3902)
@@ -19,4 +19,6 @@
 import org.openstreetmap.josm.gui.mappaint.mapcss.Expression.FunctionExpression;
 import org.openstreetmap.josm.gui.mappaint.mapcss.Expression.LiteralExpression;
+import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.DescendentSelector;
+import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.GeneralSelector;
 import org.openstreetmap.josm.tools.Pair;
 
@@ -229,11 +231,25 @@
 }
 {
-    sel=selector() { selectors.add(sel); } w()
+    sel=child_selector() { selectors.add(sel); }
     (
         <COMMA> w()
-        sel=selector() { selectors.add(sel); } w()
+        sel=child_selector() { selectors.add(sel); }
     )*
     decl=declaration()
     { return new MapCSSRule(selectors, decl); }
+}
+
+Selector child_selector() :
+{
+    boolean child = false;
+    Selector sel1, sel2 = null;
+}
+{
+    sel1=selector() w()
+    (
+        ( <GREATER> { child = true; } | <LESS> { child = false; } ) w()
+        sel2=selector() w()
+    )?
+    { return sel2 != null ? new DescendentSelector(sel1, sel2, child) : sel1; }
 }
 
@@ -251,5 +267,5 @@
     ( ( c=condition() | c=pseudoclass() ) { conditions.add(c); } )*
     ( sub=subpart() )?
-    { return new Selector(base.image, r, conditions, sub); }
+    { return new GeneralSelector(base.image, r, conditions, sub); }
 }
 
@@ -277,8 +293,8 @@
     <LSQUARE>
     (
-        LOOKAHEAD(3)
+        LOOKAHEAD( simple_key_condition() <RSQUARE> )
             c=simple_key_condition() <RSQUARE> { return c; }
         |
-        LOOKAHEAD(5)
+        LOOKAHEAD( simple_key_value_condition() <RSQUARE> )
             c=simple_key_value_condition() <RSQUARE> { return c; }
         |
@@ -287,4 +303,15 @@
 }
 
+String tag_key() :
+{
+    String s;
+    Token t;
+}
+{
+        s=string() { return s; }
+    |
+        t=<IDENT> { s = t.image; } ( <COLON> t=<IDENT> { s += ':' + t.image; } )* { return s; }
+}
+
 Condition simple_key_condition() :
 {
@@ -295,5 +322,5 @@
 {
     ( <EXCLAMATION> { not = true; } )?
-    key=string_or_ident()
+    key=tag_key()
     ( <QUESTION> { yes = true; } )?
     { return new Condition.KeyCondition(key, not, yes); }
@@ -308,5 +335,5 @@
 }
 {
-    key=string_or_ident()
+    key=tag_key()
     (
             (
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/parser/MapCSSParserTokenManager.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/parser/MapCSSParserTokenManager.java	(revision 3901)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/parser/MapCSSParserTokenManager.java	(revision 3902)
@@ -12,4 +12,6 @@
 import org.openstreetmap.josm.gui.mappaint.mapcss.Expression.FunctionExpression;
 import org.openstreetmap.josm.gui.mappaint.mapcss.Expression.LiteralExpression;
+import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.DescendentSelector;
+import org.openstreetmap.josm.gui.mappaint.mapcss.Selector.GeneralSelector;
 import org.openstreetmap.josm.tools.Pair;
 
Index: trunk/styles/standard/potlatch2.mapcss
===================================================================
--- trunk/styles/standard/potlatch2.mapcss	(revision 3901)
+++ trunk/styles/standard/potlatch2.mapcss	(revision 3902)
@@ -282,9 +282,9 @@
 /* Addressing */
 
-node["addr:housenumber"],
-node["addr:housename"] { symbol-shape: circle; symbol-size: 8; symbol-fill-color: #B0E0E6; }
-node["addr:housenumber"]::hn_casing,
-node["addr:housename"]::hn_casing { z-index: -100; symbol-shape: circle; symbol-size: 10; symbol-fill-color: blue; }
-way["addr:interpolation"] { color: #B0E0E6; width: 3; dashes: 3,3;}
+node[addr:housenumber],
+node[addr:housename] { symbol-shape: circle; symbol-size: 8; symbol-fill-color: #B0E0E6; }
+node[addr:housenumber]::hn_casing,
+node[addr:housename]::hn_casing { z-index: -100; symbol-shape: circle; symbol-size: 10; symbol-fill-color: blue; }
+way[addr:interpolation] { color: #B0E0E6; width: 3; dashes: 3,3;}
 
 /****************
@@ -335,4 +335,12 @@
 way[landuse=cemetery]						{ color: #664466; width: 2; fill-color: #664466; opacity: 0.2; prop_area_small_name : 1;}
 /* Addressing. Nodes with addresses *and* match POIs should have a poi icon, so we put addressing first */
+/* Route relations */
+
+relation[type=route] > way::relation_underlay { z-index: -1; width: 13; color: blue; opacity: 0.3; linecap: none; }
+relation[type=route][route=bicycle][network=ncn] > way::relation_underlay { z-index: -1; width: 12; color: red; opacity: 0.3; linecap: none; }
+relation[type=route][route=bicycle][network=rcn] > way::relation_underlay { z-index: -1; width: 12; color: cyan; opacity: 0.3; linecap: none; }
+relation[type=route][route=bicycle][network=lcn] > way::relation_underlay { z-index: -1; width: 12; color: blue; opacity: 0.3; linecap: none; }
+relation[type=route][route=foot] > way::relation_underlay { z-index: -1; width: 10; color: #80ff80; opacity: 0.6; linecap: none; }
+
 
 /*@import("stylesheets/core_ways.css");*/
Index: trunk/styles_nodist/potlatch2/README
===================================================================
--- trunk/styles_nodist/potlatch2/README	(revision 3902)
+++ trunk/styles_nodist/potlatch2/README	(revision 3902)
@@ -0,0 +1,14 @@
+The Potlatch 2 styles need to be patched in order to work with the JOSM MapCSS implementation.
+
+The subversion externals definition has an explicit revision number set. 
+When updating from the remote repository, make sure to change the patched files accordingly.
+
+The ant task 'assemble' concatinates the patched files to the final style potlatch2.mapcss
+
+Another ant task 'update-externals' is a shortcut to change the svn property, such that the externals 
+points to the revision that is currently checked out.
+
+When committing, the following should be in sync:
+ * revision number in the svn externals property
+ * patched *.css files
+ * styles/standard/potlatch2.mapcss
Index: trunk/styles_nodist/potlatch2/build.xml
===================================================================
--- trunk/styles_nodist/potlatch2/build.xml	(revision 3901)
+++ trunk/styles_nodist/potlatch2/build.xml	(revision 3902)
@@ -1,17 +1,3 @@
-<project name="potlatch2styles_mod" basedir=".">
-<!--
-
-    The potlatch 2 styles need to be patched in order to work with the JOSM MapCSS implementation.
-    When updating from the potlatch2 repository, the workflow can be like this:
-     * copy files from 'patched' to 'source'
-     * cd source && svn up
-     * solve possible conflicts
-     * modify the new sections, such that they work with josm
-     * create potlatch2.mapcss (ant assemble)
-     * copy files from 'source' to 'patched'
-     * update externals definition to the current revision (ant update-externals)
-     * commit everything (style, patches and externals definition)
-     
--->
+<project name="potlatch2_patch_utils" basedir="." default="assemble">
 
     <!--    concatinate the files to one mapcss style file     -->
@@ -19,22 +5,10 @@
         <concat destfile="../../styles/standard/potlatch2.mapcss">
             <filelist dir="." files="prelude.css"/>        
-            <filelist dir="patched" files="core_ways.css,core_pois.css,core_landuse.css,potlatch.css"/>        
+            <filelist dir="patched" files="core_ways.css,core_pois.css,core_landuse.css,core_relations.css,potlatch.css"/>        
         </concat>
     </target>
     
-    
-    <target name="copy-patched-to-source">
-        <copy todir="source" overwrite="true"> 
-            <fileset dir="patched"/>
-        </copy>
-    </target>
-    
-    <target name="copy-source-to-patched">
-        <copy todir="patched" overwrite="true"> 
-            <filelist dir="source" files="core_ways.css,core_pois.css,core_landuse.css,potlatch.css"/>        
-        </copy>
-    </target>
 
-    <!--    Update the explicit revision number in the externals definition to the current revision. -->
+    <!--    update the explicit revision number in the externals definition to the currently checked out revison  -->
     <target name="update-externals" depends="source-revision">
         <exec executable="svn">
Index: trunk/styles_nodist/potlatch2/patched/core_pois.css
===================================================================
--- trunk/styles_nodist/potlatch2/patched/core_pois.css	(revision 3901)
+++ trunk/styles_nodist/potlatch2/patched/core_pois.css	(revision 3902)
@@ -89,7 +89,7 @@
 /* Addressing */
 
-node["addr:housenumber"],
-node["addr:housename"] { symbol-shape: circle; symbol-size: 8; symbol-fill-color: #B0E0E6; }
-node["addr:housenumber"]::hn_casing,
-node["addr:housename"]::hn_casing { z-index: -100; symbol-shape: circle; symbol-size: 10; symbol-fill-color: blue; }
-way["addr:interpolation"] { color: #B0E0E6; width: 3; dashes: 3,3;}
+node[addr:housenumber],
+node[addr:housename] { symbol-shape: circle; symbol-size: 8; symbol-fill-color: #B0E0E6; }
+node[addr:housenumber]::hn_casing,
+node[addr:housename]::hn_casing { z-index: -100; symbol-shape: circle; symbol-size: 10; symbol-fill-color: blue; }
+way[addr:interpolation] { color: #B0E0E6; width: 3; dashes: 3,3;}
Index: trunk/styles_nodist/potlatch2/patched/core_relations.css
===================================================================
--- trunk/styles_nodist/potlatch2/patched/core_relations.css	(revision 3902)
+++ trunk/styles_nodist/potlatch2/patched/core_relations.css	(revision 3902)
@@ -0,0 +1,8 @@
+/* Route relations */
+
+relation[type=route] > way::relation_underlay { z-index: -1; width: 13; color: blue; opacity: 0.3; linecap: none; }
+relation[type=route][route=bicycle][network=ncn] > way::relation_underlay { z-index: -1; width: 12; color: red; opacity: 0.3; linecap: none; }
+relation[type=route][route=bicycle][network=rcn] > way::relation_underlay { z-index: -1; width: 12; color: cyan; opacity: 0.3; linecap: none; }
+relation[type=route][route=bicycle][network=lcn] > way::relation_underlay { z-index: -1; width: 12; color: blue; opacity: 0.3; linecap: none; }
+relation[type=route][route=foot] > way::relation_underlay { z-index: -1; width: 10; color: #80ff80; opacity: 0.6; linecap: none; }
+
