Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/MapPaintStyles.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/MapPaintStyles.java	(revision 3875)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/MapPaintStyles.java	(revision 3876)
@@ -136,5 +136,7 @@
         } finally {
             try {
-                in.close();
+                if (in != null) {
+                    in.close();
+                }
             } catch (IOException ex) {
             }
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/StyleSource.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/StyleSource.java	(revision 3875)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/StyleSource.java	(revision 3876)
@@ -49,7 +49,10 @@
     }
 
-    private ImageIcon pencil = ImageProvider.get("dialogs/mappaint", "pencil");
+    private static ImageIcon pencil;
 
     protected ImageIcon getSourceIcon() {
+        if (pencil == null) {
+            pencil = ImageProvider.get("dialogs/mappaint", "pencil");
+        }
         return pencil;
     }
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Condition.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Condition.java	(revision 3875)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Condition.java	(revision 3876)
@@ -2,8 +2,15 @@
 package org.openstreetmap.josm.gui.mappaint.mapcss;
 
+import static org.openstreetmap.josm.tools.Utils.equal;
+
+import java.util.EnumSet;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.gui.mappaint.Environment;
-import org.openstreetmap.josm.tools.Utils;
+import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.Op;
 
 abstract public class Condition {
@@ -11,5 +18,9 @@
     abstract public boolean applies(Environment e);
 
-    public static enum Op {EQ, NEQ}
+    public static enum Op { EQ, NEQ, GREATER_OR_EQUAL, GREATER, LESS_OR_EQUAL, LESS,
+        REGEX, ONE_OF, BEGINS_WITH, ENDS_WITH, CONTAINS }
+
+    public final static EnumSet<Op> COMPARISON_OPERATERS =
+            EnumSet.of(Op.GREATER_OR_EQUAL, Op.GREATER, Op.LESS_OR_EQUAL, Op.LESS);
 
     public static class KeyValueCondition extends Condition {
@@ -18,19 +29,58 @@
         public String v;
         public Op op;
+        private float v_float;
 
         public KeyValueCondition(String k, String v, Op op) {
-
             this.k = k;
             this.v = v;
             this.op = op;
+            if (COMPARISON_OPERATERS.contains(op)) {
+                v_float = Float.parseFloat(v);
+            }
         }
 
         @Override
-        public boolean applies(Environment e) {
+        public boolean applies(Environment env) {
+            String val = env.osm.get(k);
+            if (val == null)
+                return false;
             switch (op) {
                 case EQ:
-                    return Utils.equal(e.osm.get(k), v);
+                    return equal(val, v);
                 case NEQ:
-                    return !Utils.equal(e.osm.get(k), v);
+                    return !equal(val, v);
+                case REGEX:
+                    Pattern p = Pattern.compile(v);
+                    Matcher m = p.matcher(val);
+                    return m.find();
+                case ONE_OF:
+                    String[] parts = val.split(";");
+                    for (String part : parts) {
+                        if (equal(v, part.trim()))
+                            return true;
+                    }
+                    return false;
+                case BEGINS_WITH:
+                    return val.startsWith(v);
+                case ENDS_WITH:
+                    return val.endsWith(v);
+                case CONTAINS:
+                    return val.contains(v);
+            }
+            float val_float;
+            try {
+                val_float = Float.parseFloat(val);
+            } catch (NumberFormatException e) {
+                return false;
+            }
+            switch (op) {
+                case GREATER_OR_EQUAL:
+                    return val_float >= v_float;
+                case GREATER:
+                    return val_float > v_float;
+                case LESS_OR_EQUAL:
+                    return val_float <= v_float;
+                case LESS:
+                    return val_float < v_float;
                 default:
                     throw new AssertionError();
@@ -40,5 +90,5 @@
         @Override
         public String toString() {
-            return "[" + k + (op == Op.EQ ? "=" : "!=") + v + "]";
+            return "[" + k + "'" + op + "'" + v + "]";
         }
     }
@@ -77,5 +127,5 @@
         @Override
         public boolean applies(Environment e) {
-            if ("closed".equals(id)) {
+            if (equal(id, "closed")) {
                 if (e.osm instanceof Way && ((Way) e.osm).isClosed())
                     return true;
@@ -83,4 +133,10 @@
                     return true;
                 return false;
+            } else if (equal(id, "modified")) {
+                return e.osm.isModified() || e.osm.isNewOrUndeleted();
+            } else if (equal(id, "new")) {
+                return e.osm.isNew();
+            } else if (equal(id, "connection") && (e.osm instanceof Node)) {
+                return ((Node) e.osm).isConnectionNode();
             }
             return true;
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Instruction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Instruction.java	(revision 3875)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Instruction.java	(revision 3876)
@@ -30,5 +30,9 @@
         public AssignmentInstruction(String key, Object val) {
             this.key = key;
-            this.val = val;
+            if (val instanceof Expression.LiteralExpression) {
+                this.val = ((Expression.LiteralExpression) val).evaluate(null);
+            } else {
+                this.val = val;
+            }
         }
 
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSRule.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSRule.java	(revision 3875)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSRule.java	(revision 3876)
@@ -18,5 +18,5 @@
     @Override
     public String toString() {
-        return Utils.join(",", selectors) + " {\n  " + Utils.join(";\n  ", declaration) + "\n}";
+        return Utils.join(",", selectors) + " {\n  " + Utils.join("\n  ", declaration) + "\n}";
     }
 }
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/parser/MapCSSParser.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/parser/MapCSSParser.java	(revision 3875)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/parser/MapCSSParser.java	(revision 3876)
@@ -67,8 +67,29 @@
   }
 
+  final public float float_() throws ParseException {
+    float f;
+    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+    case MINUS:
+      jj_consume_token(MINUS);
+      f = ufloat();
+                         {if (true) return -f;}
+      break;
+    case UINT:
+    case UFLOAT:
+      f = ufloat();
+                                                     {if (true) return f;}
+      break;
+    default:
+      jj_la1[1] = jj_gen;
+      jj_consume_token(-1);
+      throw new ParseException();
+    }
+    throw new Error("Missing return statement in function");
+  }
+
   final public String string() throws ParseException {
     Token t;
     t = jj_consume_token(STRING);
-        {if (true) return t.image.substring(1, t.image.length() - 1).replace("\\\"", "\"").replace("\\\\", "\\");}
+      {if (true) return t.image.substring(1, t.image.length() - 1).replace("\\\"", "\"").replace("\\\\", "\\");}
     throw new Error("Missing return statement in function");
   }
@@ -87,8 +108,15 @@
       break;
     default:
-      jj_la1[1] = jj_gen;
+      jj_la1[2] = jj_gen;
       jj_consume_token(-1);
       throw new ParseException();
     }
+    throw new Error("Missing return statement in function");
+  }
+
+  final public String regex() throws ParseException {
+    Token t;
+    t = jj_consume_token(REGEX);
+      {if (true) return t.image.substring(1, t.image.length() - 1);}
     throw new Error("Missing return statement in function");
   }
@@ -103,5 +131,5 @@
       break;
     default:
-      jj_la1[2] = jj_gen;
+      jj_la1[3] = jj_gen;
       ;
     }
@@ -120,5 +148,5 @@
         break;
       default:
-        jj_la1[3] = jj_gen;
+        jj_la1[4] = jj_gen;
         break label_1;
       }
@@ -132,5 +160,5 @@
         break;
       default:
-        jj_la1[4] = jj_gen;
+        jj_la1[5] = jj_gen;
         jj_consume_token(-1);
         throw new ParseException();
@@ -158,5 +186,5 @@
         break;
       default:
-        jj_la1[5] = jj_gen;
+        jj_la1[6] = jj_gen;
         break label_2;
       }
@@ -182,10 +210,15 @@
         break;
       default:
-        jj_la1[6] = jj_gen;
+        jj_la1[7] = jj_gen;
         break label_3;
       }
-      r = rule();
-                 if (r != null) { sheet.rules.add(r); }
-      w();
+      try {
+        r = rule();
+                       if (r != null) { sheet.rules.add(r); }
+        w();
+      } catch (ParseException ex) {
+            error_skipto(RBRACE);
+            w();
+      }
     }
     jj_consume_token(0);
@@ -196,27 +229,22 @@
     Selector sel;
     List<Instruction> decl;
-    try {
+    sel = selector();
+                     selectors.add(sel);
+    w();
+    label_4:
+    while (true) {
+      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+      case COMMA:
+        ;
+        break;
+      default:
+        jj_la1[8] = jj_gen;
+        break label_4;
+      }
+      jj_consume_token(COMMA);
+      w();
       sel = selector();
                          selectors.add(sel);
       w();
-      label_4:
-      while (true) {
-        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-        case COMMA:
-          ;
-          break;
-        default:
-          jj_la1[7] = jj_gen;
-          break label_4;
-        }
-        jj_consume_token(COMMA);
-        w();
-        sel = selector();
-                             selectors.add(sel);
-        w();
-      }
-    } catch (ParseException ex) {
-        error_skipto(RBRACE);
-        {if (true) return null;}
     }
     decl = declaration();
@@ -239,5 +267,5 @@
       break;
     default:
-      jj_la1[8] = jj_gen;
+      jj_la1[9] = jj_gen;
       jj_consume_token(-1);
       throw new ParseException();
@@ -248,5 +276,5 @@
       break;
     default:
-      jj_la1[9] = jj_gen;
+      jj_la1[10] = jj_gen;
       ;
     }
@@ -259,5 +287,5 @@
         break;
       default:
-        jj_la1[10] = jj_gen;
+        jj_la1[11] = jj_gen;
         break label_5;
       }
@@ -270,5 +298,5 @@
         break;
       default:
-        jj_la1[11] = jj_gen;
+        jj_la1[12] = jj_gen;
         jj_consume_token(-1);
         throw new ParseException();
@@ -277,10 +305,9 @@
     }
     switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-    case SLASH:
     case DCOLON:
       sub = subpart();
       break;
     default:
-      jj_la1[12] = jj_gen;
+      jj_la1[13] = jj_gen;
       ;
     }
@@ -308,15 +335,15 @@
           break;
         default:
-          jj_la1[13] = jj_gen;
+          jj_la1[14] = jj_gen;
           ;
         }
         break;
       default:
-        jj_la1[14] = jj_gen;
+        jj_la1[15] = jj_gen;
         ;
       }
       break;
     default:
-      jj_la1[15] = jj_gen;
+      jj_la1[16] = jj_gen;
       jj_consume_token(-1);
       throw new ParseException();
@@ -330,10 +357,12 @@
     Expression e;
     jj_consume_token(LSQUARE);
-    if (jj_2_1(2)) {
+    if (jj_2_1(3)) {
       c = simple_key_condition();
       jj_consume_token(RSQUARE);
-                                                   {if (true) return c;}
-    } else if (jj_2_2(3)) {
+                                                 {if (true) return c;}
+    } else if (jj_2_2(5)) {
       c = simple_key_value_condition();
+      jj_consume_token(RSQUARE);
+                                                       {if (true) return c;}
     } else {
       switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
@@ -348,14 +377,13 @@
       case MINUS:
         e = expression();
-                             c = new Condition.ExpressionCondition(e);
+        jj_consume_token(RSQUARE);
+                                       {if (true) return new Condition.ExpressionCondition(e);}
         break;
       default:
-        jj_la1[16] = jj_gen;
+        jj_la1[17] = jj_gen;
         jj_consume_token(-1);
         throw new ParseException();
       }
     }
-    jj_consume_token(RSQUARE);
-      {if (true) return c;}
     throw new Error("Missing return statement in function");
   }
@@ -370,5 +398,5 @@
       break;
     default:
-      jj_la1[17] = jj_gen;
+      jj_la1[18] = jj_gen;
       ;
     }
@@ -379,23 +407,107 @@
 
   final public Condition simple_key_value_condition() throws ParseException {
-    boolean not = false;
     String key;
     String val;
+    float f;
+    Condition.Op op;
     key = string_or_ident();
     switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-    case EXCLAMATION_EQUAL:
-      jj_consume_token(EXCLAMATION_EQUAL);
-                            not = true;
-      break;
+    case STAR:
     case EQUAL:
-      jj_consume_token(EQUAL);
+    case EXCLAMATION:
+    case TILDE:
+    case DOLLAR:
+    case CARET:
+      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+      case EXCLAMATION:
+        jj_consume_token(EXCLAMATION);
+        jj_consume_token(EQUAL);
+                                            op=Condition.Op.NEQ;
+        val = string_or_ident();
+        break;
+      case EQUAL:
+        jj_consume_token(EQUAL);
+                              op=Condition.Op.EQ;
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case TILDE:
+          jj_consume_token(TILDE);
+                                      op=Condition.Op.REGEX;
+          val = regex();
+          break;
+        case IDENT:
+        case STRING:
+          val = string_or_ident();
+          break;
+        default:
+          jj_la1[19] = jj_gen;
+          jj_consume_token(-1);
+          throw new ParseException();
+        }
+        break;
+      case TILDE:
+        jj_consume_token(TILDE);
+        jj_consume_token(EQUAL);
+                                      op=Condition.Op.ONE_OF;
+        val = string_or_ident();
+        break;
+      case CARET:
+        jj_consume_token(CARET);
+        jj_consume_token(EQUAL);
+                                      op=Condition.Op.BEGINS_WITH;
+        val = string_or_ident();
+        break;
+      case DOLLAR:
+        jj_consume_token(DOLLAR);
+        jj_consume_token(EQUAL);
+                                       op=Condition.Op.ENDS_WITH;
+        val = string_or_ident();
+        break;
+      case STAR:
+        jj_consume_token(STAR);
+        jj_consume_token(EQUAL);
+                                     op=Condition.Op.CONTAINS;
+        val = string_or_ident();
+        break;
+      default:
+        jj_la1[20] = jj_gen;
+        jj_consume_token(-1);
+        throw new ParseException();
+      }
+              {if (true) return new Condition.KeyValueCondition(key, val, op);}
+      break;
+    case GREATER_EQUAL:
+    case LESS_EQUAL:
+    case GREATER:
+    case LESS:
+      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+      case GREATER_EQUAL:
+        jj_consume_token(GREATER_EQUAL);
+                                      op=Condition.Op.GREATER_OR_EQUAL;
+        break;
+      case GREATER:
+        jj_consume_token(GREATER);
+                                op=Condition.Op.GREATER;
+        break;
+      case LESS_EQUAL:
+        jj_consume_token(LESS_EQUAL);
+                                   op=Condition.Op.LESS_OR_EQUAL;
+        break;
+      case LESS:
+        jj_consume_token(LESS);
+                             op=Condition.Op.LESS;
+        break;
+      default:
+        jj_la1[21] = jj_gen;
+        jj_consume_token(-1);
+        throw new ParseException();
+      }
+      f = float_();
+              {if (true) return new Condition.KeyValueCondition(key, Float.toString(f), op);}
       break;
     default:
-      jj_la1[18] = jj_gen;
+      jj_la1[22] = jj_gen;
       jj_consume_token(-1);
       throw new ParseException();
     }
-    val = string_or_ident();
-      {if (true) return new Condition.KeyValueCondition(key, val, not ? Condition.Op.NEQ : Condition.Op.EQ);}
     throw new Error("Missing return statement in function");
   }
@@ -411,5 +523,5 @@
       break;
     default:
-      jj_la1[19] = jj_gen;
+      jj_la1[23] = jj_gen;
       ;
     }
@@ -421,16 +533,5 @@
   final public String subpart() throws ParseException {
     Token t;
-    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-    case SLASH:
-      jj_consume_token(SLASH);
-      break;
-    case DCOLON:
-      jj_consume_token(DCOLON);
-      break;
-    default:
-      jj_la1[20] = jj_gen;
-      jj_consume_token(-1);
-      throw new ParseException();
-    }
+    jj_consume_token(DCOLON);
     switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
     case IDENT:
@@ -441,5 +542,5 @@
       break;
     default:
-      jj_la1[21] = jj_gen;
+      jj_la1[24] = jj_gen;
       jj_consume_token(-1);
       throw new ParseException();
@@ -452,84 +553,65 @@
     List<Instruction> ins = new ArrayList<Instruction>();
     Instruction i;
+    Token key;
+    Object val;
     jj_consume_token(LBRACE);
     w();
-    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-    case RBRACE:
-      jj_consume_token(RBRACE);
-                 {if (true) return ins;}
-      break;
-    default:
-      jj_la1[22] = jj_gen;
-      ;
-    }
-    try {
-      i = instruction();
-                          if (i != null) ins.add(i);
-      label_6:
-      while (true) {
-        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-        case SEMICOLON:
-          ;
-          break;
-        default:
-          jj_la1[23] = jj_gen;
-          break label_6;
-        }
-        jj_consume_token(SEMICOLON);
+    label_6:
+    while (true) {
+      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+      case IDENT:
+        ;
+        break;
+      default:
+        jj_la1[25] = jj_gen;
+        break label_6;
+      }
+      key = jj_consume_token(IDENT);
+      w();
+      jj_consume_token(COLON);
+      w();
+      if (jj_2_3(2147483647)) {
+        val = float_array();
+                  ins.add(new Instruction.AssignmentInstruction(key.image, val));
         w();
         switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
         case RBRACE:
           jj_consume_token(RBRACE);
-                         {if (true) return ins;}
+                             {if (true) return ins;}
+          break;
+        case SEMICOLON:
+          jj_consume_token(SEMICOLON);
+          w();
           break;
         default:
-          jj_la1[24] = jj_gen;
-          ;
+          jj_la1[26] = jj_gen;
+          jj_consume_token(-1);
+          throw new ParseException();
         }
-        i = instruction();
-                              if (i != null) ins.add(i);
-      }
-      jj_consume_token(RBRACE);
-                   {if (true) return ins;}
-    } catch (ParseException ex) {
-        error_skipto(RBRACE);
-        {if (true) return ins;}
-    }
-    throw new Error("Missing return statement in function");
-  }
-
-  final public Instruction instruction() throws ParseException {
-    Token key;
-    Object val;
-    key = jj_consume_token(IDENT);
-    w();
-    jj_consume_token(COLON);
-    w();
-    if (jj_2_3(2)) {
-      val = float_array();
-      w();
-    } else {
-      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-      case IDENT:
-      case UINT:
-      case UFLOAT:
-      case STRING:
-      case HEXCOLOR:
-      case LPAR:
-      case EXCLAMATION:
-      case PLUS:
-      case MINUS:
+      } else if (jj_2_4(2147483647)) {
         val = expression();
-        break;
-      default:
-        jj_la1[25] = jj_gen;
-        jj_consume_token(-1);
-        throw new ParseException();
-      }
-    }
-        if (val instanceof LiteralExpression)
-            {if (true) return new Instruction.AssignmentInstruction(key.image, ((LiteralExpression) val).evaluate(null));}
-        else
-            {if (true) return new Instruction.AssignmentInstruction(key.image, val);}
+                  ins.add(new Instruction.AssignmentInstruction(key.image, val));
+        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+        case RBRACE:
+          jj_consume_token(RBRACE);
+                             {if (true) return ins;}
+          break;
+        case SEMICOLON:
+          jj_consume_token(SEMICOLON);
+          w();
+          break;
+        default:
+          jj_la1[27] = jj_gen;
+          jj_consume_token(-1);
+          throw new ParseException();
+        }
+      } else {
+        val = readRaw();
+        w();
+                                    ins.add(new Instruction.AssignmentInstruction(key.image, val));
+      }
+    }
+    jj_consume_token(RBRACE);
+      {if (true) return ins;}
     throw new Error("Missing return statement in function");
   }
@@ -542,16 +624,16 @@
     case EXCLAMATION:
       jj_consume_token(EXCLAMATION);
-                          op = "not";
+                        op = "not";
       w();
       e = primary();
-                                                          args.add(e);
+                                                        args.add(e);
       w();
       break;
     case MINUS:
       jj_consume_token(MINUS);
-                    op = "minus";
+                  op = "minus";
       w();
       e = primary();
-                                                      args.add(e);
+                                                    args.add(e);
       w();
       break;
@@ -594,5 +676,5 @@
               break;
             default:
-              jj_la1[26] = jj_gen;
+              jj_la1[28] = jj_gen;
               break label_7;
             }
@@ -613,5 +695,5 @@
               break;
             default:
-              jj_la1[27] = jj_gen;
+              jj_la1[29] = jj_gen;
               break label_8;
             }
@@ -632,5 +714,5 @@
               break;
             default:
-              jj_la1[28] = jj_gen;
+              jj_la1[30] = jj_gen;
               break label_9;
             }
@@ -651,5 +733,5 @@
               break;
             default:
-              jj_la1[29] = jj_gen;
+              jj_la1[31] = jj_gen;
               break label_10;
             }
@@ -658,24 +740,24 @@
         case GREATER_EQUAL:
           jj_consume_token(GREATER_EQUAL);
-                                        op = "greater_equal";
+                                      op = "greater_equal";
           w();
           e = primary();
-                                                                                  args.add(e);
+                                                                                args.add(e);
           w();
           break;
         case LESS_EQUAL:
           jj_consume_token(LESS_EQUAL);
-                                     op = "less_equal";
+                                   op = "less_equal";
           w();
           e = primary();
-                                                                            args.add(e);
+                                                                          args.add(e);
           w();
           break;
         case GREATER:
           jj_consume_token(GREATER);
-                                  op = "greater";
+                                op = "greater";
           w();
           e = primary();
-                                                                      args.add(e);
+                                                                    args.add(e);
           w();
           break;
@@ -687,19 +769,19 @@
             break;
           default:
-            jj_la1[30] = jj_gen;
+            jj_la1[32] = jj_gen;
             ;
           }
-                                             op = "equal";
+                                           op = "equal";
           w();
           e = primary();
-                                                                               args.add(e);
+                                                                             args.add(e);
           w();
           break;
         case LESS:
           jj_consume_token(LESS);
-                               op = "less";
+                             op = "less";
           w();
           e = primary();
-                                                                args.add(e);
+                                                              args.add(e);
           w();
           break;
@@ -707,8 +789,8 @@
           jj_consume_token(AMPERSAND);
           jj_consume_token(AMPERSAND);
-                                                op = "and";
+                                              op = "and";
           w();
           e = primary();
-                                                                                args.add(e);
+                                                                              args.add(e);
           w();
           break;
@@ -716,25 +798,25 @@
           jj_consume_token(PIPE);
           jj_consume_token(PIPE);
-                                      op = "or";
+                                    op = "or";
           w();
           e = primary();
-                                                                     args.add(e);
+                                                                   args.add(e);
           w();
           break;
         case QUESTION:
           jj_consume_token(QUESTION);
-                                   op = "cond";
+                                 op = "cond";
           w();
           e = primary();
-                                                                    args.add(e);
+                                                                  args.add(e);
           w();
           jj_consume_token(COLON);
           w();
           e = primary();
-                                                                                                                 args.add(e);
+                                                                                                               args.add(e);
           w();
           break;
         default:
-          jj_la1[31] = jj_gen;
+          jj_la1[33] = jj_gen;
           jj_consume_token(-1);
           throw new ParseException();
@@ -742,10 +824,10 @@
         break;
       default:
-        jj_la1[32] = jj_gen;
+        jj_la1[34] = jj_gen;
         ;
       }
       break;
     default:
-      jj_la1[33] = jj_gen;
+      jj_la1[35] = jj_gen;
       jj_consume_token(-1);
       throw new ParseException();
@@ -761,5 +843,5 @@
     FunctionExpression fn;
     Object lit;
-    if (jj_2_4(2)) {
+    if (jj_2_5(2)) {
       // both function and identifier start with an identifier
               fn = function();
@@ -781,8 +863,8 @@
         nested = expression();
         jj_consume_token(RPAR);
-                                                    {if (true) return nested;}
+                                                {if (true) return nested;}
         break;
       default:
-        jj_la1[34] = jj_gen;
+        jj_la1[36] = jj_gen;
         jj_consume_token(-1);
         throw new ParseException();
@@ -821,5 +903,5 @@
           break;
         default:
-          jj_la1[35] = jj_gen;
+          jj_la1[37] = jj_gen;
           break label_11;
         }
@@ -831,5 +913,5 @@
       break;
     default:
-      jj_la1[36] = jj_gen;
+      jj_la1[38] = jj_gen;
       ;
     }
@@ -852,5 +934,5 @@
       jj_consume_token(PLUS);
       f = ufloat();
-                                {if (true) return new Instruction.RelativeFloat(f);}
+                            {if (true) return new Instruction.RelativeFloat(f);}
       break;
     case UINT:
@@ -870,5 +952,5 @@
       break;
     default:
-      jj_la1[37] = jj_gen;
+      jj_la1[39] = jj_gen;
       jj_consume_token(-1);
       throw new ParseException();
@@ -879,4 +961,5 @@
   void error_skipto(int kind) throws ParseException {
     ParseException e = generateParseException();
+    System.err.println("Skipping to the next rule, because of an error:");
     System.err.println(e);
     if (sheet != null) {
@@ -891,4 +974,21 @@
   }
 
+/**
+ * read everything to the next semicolon
+ */
+  String readRaw() throws ParseException {
+    Token t;
+    StringBuilder s = new StringBuilder();
+    while (true) {
+        t = getNextToken();
+        if (t.kind == SEMICOLON || t.kind == EOF)
+            break;
+        s.append(t.image);
+    }
+    if (t.kind == EOF)
+        throw new ParseException("Reached end of file while parsing");
+    return s.toString();
+  }
+
   private boolean jj_2_1(int xla) {
     jj_la = xla; jj_lastpos = jj_scanpos = token;
@@ -919,40 +1019,586 @@
   }
 
-  private boolean jj_3R_12() {
+  private boolean jj_2_5(int xla) {
+    jj_la = xla; jj_lastpos = jj_scanpos = token;
+    try { return !jj_3_5(); }
+    catch(LookaheadSuccess ls) { return true; }
+    finally { jj_save(4, xla); }
+  }
+
+  private boolean jj_3R_29() {
+    if (jj_3R_45()) 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_16()) jj_scanpos = xsp;
-    if (jj_3R_17()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_20() {
-    if (jj_scan_token(COMMA)) return true;
-    return false;
-  }
-
-  private boolean jj_3_4() {
-    if (jj_3R_15()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_25() {
-    if (jj_scan_token(STRING)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_14() {
-    if (jj_3R_19()) return true;
-    Token xsp;
-    if (jj_3R_20()) return true;
+    if (jj_3R_70()) jj_scanpos = xsp;
+    if (jj_scan_token(RPAR)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_24() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_scan_token(9)) {
+    jj_scanpos = xsp;
+    if (jj_3R_42()) return true;
+    }
+    return false;
+  }
+
+  private boolean jj_3R_15() {
+    Token xsp;
     while (true) {
       xsp = jj_scanpos;
-      if (jj_3R_20()) { jj_scanpos = xsp; break; }
-    }
+      if (jj_3R_24()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private boolean jj_3R_51() {
+    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_50() {
+    if (jj_3R_65()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_41() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_scan_token(9)) jj_scanpos = xsp;
+    return false;
+  }
+
+  private boolean jj_3R_49() {
+    if (jj_3R_22()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_43() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3_5()) {
+    jj_scanpos = xsp;
+    if (jj_3R_50()) {
+    jj_scanpos = xsp;
+    if (jj_3R_51()) return true;
+    }
+    }
+    return false;
+  }
+
+  private boolean jj_3_5() {
+    if (jj_3R_17()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_63() {
+    if (jj_scan_token(QUESTION)) return true;
+    if (jj_3R_15()) return true;
+    if (jj_3R_43()) return true;
+    if (jj_3R_15()) return true;
+    if (jj_scan_token(COLON)) return true;
+    if (jj_3R_15()) return true;
+    if (jj_3R_43()) return true;
+    if (jj_3R_15()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_39() {
+    if (jj_scan_token(LESS)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_62() {
+    if (jj_scan_token(PIPE)) return true;
+    if (jj_scan_token(PIPE)) return true;
+    if (jj_3R_15()) return true;
+    if (jj_3R_43()) return true;
+    if (jj_3R_15()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_38() {
+    if (jj_scan_token(LESS_EQUAL)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_61() {
+    if (jj_scan_token(AMPERSAND)) return true;
+    if (jj_scan_token(AMPERSAND)) return true;
+    if (jj_3R_15()) return true;
+    if (jj_3R_43()) return true;
+    if (jj_3R_15()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_37() {
+    if (jj_scan_token(GREATER)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_64() {
+    if (jj_scan_token(REGEX)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_60() {
+    if (jj_scan_token(LESS)) return true;
+    if (jj_3R_15()) return true;
+    if (jj_3R_43()) return true;
+    if (jj_3R_15()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_36() {
+    if (jj_scan_token(GREATER_EQUAL)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_59() {
+    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_43()) return true;
+    if (jj_3R_15()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_58() {
+    if (jj_scan_token(GREATER)) return true;
+    if (jj_3R_15()) return true;
+    if (jj_3R_43()) return true;
+    if (jj_3R_15()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_57() {
+    if (jj_scan_token(LESS_EQUAL)) return true;
+    if (jj_3R_15()) return true;
+    if (jj_3R_43()) return true;
+    if (jj_3R_15()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_35() {
+    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_47() {
+    if (jj_3R_19()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_69() {
+    if (jj_scan_token(SLASH)) return true;
+    if (jj_3R_15()) return true;
+    if (jj_3R_43()) return true;
+    if (jj_3R_15()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_56() {
+    if (jj_scan_token(GREATER_EQUAL)) return true;
+    if (jj_3R_15()) return true;
+    if (jj_3R_43()) return true;
+    if (jj_3R_15()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_19() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_28()) {
+    jj_scanpos = xsp;
+    if (jj_3R_29()) return true;
+    }
+    return false;
+  }
+
+  private boolean jj_3R_28() {
+    if (jj_scan_token(IDENT)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_34() {
+    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_68() {
+    if (jj_scan_token(MINUS)) return true;
+    if (jj_3R_15()) return true;
+    if (jj_3R_43()) 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_46() {
+    if (jj_scan_token(TILDE)) return true;
+    if (jj_3R_64()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_21() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_36()) {
+    jj_scanpos = xsp;
+    if (jj_3R_37()) {
+    jj_scanpos = xsp;
+    if (jj_3R_38()) {
+    jj_scanpos = xsp;
+    if (jj_3R_39()) return true;
+    }
+    }
+    }
+    if (jj_3R_40()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_33() {
+    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_67() {
+    if (jj_scan_token(STAR)) return true;
+    if (jj_3R_15()) return true;
+    if (jj_3R_43()) 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_32() {
+    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_66() {
+    if (jj_scan_token(PLUS)) return true;
+    if (jj_3R_15()) return true;
+    if (jj_3R_43()) return true;
+    if (jj_3R_15()) return true;
+    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_52() {
+    Token xsp;
+    if (jj_3R_66()) return true;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_66()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private boolean jj_3R_44() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_52()) {
+    jj_scanpos = xsp;
+    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()) return true;
+    }
+    }
+    }
+    }
+    }
+    }
+    }
+    }
+    }
+    }
+    }
+    return false;
+  }
+
+  private boolean jj_3R_45() {
+    if (jj_scan_token(STRING)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_31() {
+    if (jj_scan_token(EQUAL)) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_46()) {
+    jj_scanpos = xsp;
+    if (jj_3R_47()) return true;
+    }
+    return false;
+  }
+
+  private boolean jj_3R_30() {
+    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_48() {
+    if (jj_scan_token(MINUS)) return true;
+    if (jj_3R_22()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_40() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_48()) {
+    jj_scanpos = xsp;
+    if (jj_3R_49()) 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()) {
+    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()) return true;
+    }
+    }
+    }
+    }
+    }
+    return false;
+  }
+
+  private boolean jj_3R_27() {
+    if (jj_3R_43()) return true;
+    if (jj_3R_15()) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_44()) jj_scanpos = xsp;
+    return false;
+  }
+
+  private boolean jj_3R_26() {
+    if (jj_scan_token(MINUS)) return true;
+    if (jj_3R_15()) return true;
+    if (jj_3R_43()) return true;
+    if (jj_3R_15()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_22() {
+    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_25() {
+    if (jj_scan_token(EXCLAMATION)) return true;
+    if (jj_3R_15()) return true;
+    if (jj_3R_43()) return true;
+    if (jj_3R_15()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_13() {
+    if (jj_3R_19()) return true;
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_20()) {
+    jj_scanpos = xsp;
+    if (jj_3R_21()) return true;
+    }
+    return false;
+  }
+
+  private boolean jj_3R_16() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_25()) {
+    jj_scanpos = xsp;
+    if (jj_3R_26()) {
+    jj_scanpos = xsp;
+    if (jj_3R_27()) 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_74() {
+    if (jj_scan_token(HEXCOLOR)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_73() {
+    if (jj_3R_22()) 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_72() {
+    if (jj_scan_token(PLUS)) return true;
+    if (jj_3R_22()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_71() {
+    if (jj_3R_19()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_65() {
+    Token xsp;
+    xsp = jj_scanpos;
+    if (jj_3R_71()) {
+    jj_scanpos = xsp;
+    if (jj_3R_72()) {
+    jj_scanpos = xsp;
+    if (jj_3R_73()) {
+    jj_scanpos = xsp;
+    if (jj_3R_74()) 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;
     return false;
   }
 
   private boolean jj_3R_23() {
-    if (jj_3R_25()) return true;
+    if (jj_scan_token(COMMA)) return true;
+    if (jj_3R_41()) return true;
+    if (jj_3R_22()) return true;
+    return false;
+  }
+
+  private boolean jj_3R_75() {
+    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_14() {
+    if (jj_3R_22()) return true;
+    Token xsp;
+    if (jj_3R_23()) return true;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_23()) { jj_scanpos = xsp; break; }
+    }
     return false;
   }
@@ -960,19 +1606,21 @@
   private boolean jj_3_2() {
     if (jj_3R_13()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_26() {
+    if (jj_scan_token(RSQUARE)) return true;
+    return false;
+  }
+
+  private boolean jj_3R_70() {
+    if (jj_3R_16()) return true;
+    Token xsp;
+    while (true) {
+      xsp = jj_scanpos;
+      if (jj_3R_75()) { jj_scanpos = xsp; break; }
+    }
+    return false;
+  }
+
+  private boolean jj_3R_42() {
     if (jj_scan_token(COMMENT_START)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_19() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_scan_token(3)) {
-    jj_scanpos = xsp;
-    if (jj_scan_token(2)) return true;
-    }
+    if (jj_scan_token(COMMENT_END)) return true;
     return false;
   }
@@ -981,72 +1629,4 @@
     if (jj_3R_12()) return true;
     if (jj_scan_token(RSQUARE)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_24() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_scan_token(7)) {
-    jj_scanpos = xsp;
-    if (jj_3R_26()) return true;
-    }
-    return false;
-  }
-
-  private boolean jj_3R_21() {
-    Token xsp;
-    while (true) {
-      xsp = jj_scanpos;
-      if (jj_3R_24()) { jj_scanpos = xsp; break; }
-    }
-    return false;
-  }
-
-  private boolean jj_3_3() {
-    if (jj_3R_14()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_18() {
-    if (jj_scan_token(EXCLAMATION_EQUAL)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_15() {
-    if (jj_scan_token(IDENT)) return true;
-    if (jj_3R_21()) return true;
-    if (jj_scan_token(LPAR)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_13() {
-    if (jj_3R_17()) return true;
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_18()) {
-    jj_scanpos = xsp;
-    if (jj_scan_token(20)) return true;
-    }
-    if (jj_3R_17()) return true;
-    return false;
-  }
-
-  private boolean jj_3R_17() {
-    Token xsp;
-    xsp = jj_scanpos;
-    if (jj_3R_22()) {
-    jj_scanpos = xsp;
-    if (jj_3R_23()) return true;
-    }
-    return false;
-  }
-
-  private boolean jj_3R_22() {
-    if (jj_scan_token(IDENT)) return true;
-    return false;
-  }
-
-  private boolean jj_3R_16() {
-    if (jj_scan_token(EXCLAMATION)) return true;
     return false;
   }
@@ -1063,5 +1643,5 @@
   private int jj_la;
   private int jj_gen;
-  final private int[] jj_la1 = new int[38];
+  final private int[] jj_la1 = new int[40];
   static private int[] jj_la1_0;
   static private int[] jj_la1_1;
@@ -1071,10 +1651,10 @@
    }
    private static void jj_la1_init_0() {
-      jj_la1_0 = new int[] {0xc,0x12,0x80,0x80,0x80,0x4000000,0x102,0x4000000,0x102,0x10000000,0x801000,0x801000,0x1000200,0x4,0x40000000,0x40000004,0x6020405e,0x200000,0x500000,0x200000,0x1000200,0x102,0x800,0x2000000,0x800,0x6020405e,0x20000000,0x100,0x40000000,0x200,0x100000,0xe81f0300,0xe81f0300,0x6020405e,0x2000405e,0x4000000,0x6020405e,0x2000005e,};
+      jj_la1_0 = new int[] {0xc,0xc,0x12,0x200,0x200,0x200,0x10000000,0x402,0x10000000,0x402,0x40000000,0x2004000,0x2004000,0x4000000,0x4,0x0,0x4,0x8081011e,0x800000,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,0x0,0x0,0x2,0x2,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x0,0x0,0x0,0x0,0x0,};
+      jj_la1_1 = new int[] {0x0,0x1,0x0,0x0,0x20,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x0,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[4];
+  final private JJCalls[] jj_2_rtns = new JJCalls[5];
   private boolean jj_rescan = false;
   private int jj_gc = 0;
@@ -1091,5 +1671,5 @@
     jj_ntk = -1;
     jj_gen = 0;
-    for (int i = 0; i < 38; i++) jj_la1[i] = -1;
+    for (int i = 0; i < 40; i++) jj_la1[i] = -1;
     for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
   }
@@ -1106,5 +1686,5 @@
     jj_ntk = -1;
     jj_gen = 0;
-    for (int i = 0; i < 38; i++) jj_la1[i] = -1;
+    for (int i = 0; i < 40; i++) jj_la1[i] = -1;
     for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
   }
@@ -1117,5 +1697,5 @@
     jj_ntk = -1;
     jj_gen = 0;
-    for (int i = 0; i < 38; i++) jj_la1[i] = -1;
+    for (int i = 0; i < 40; i++) jj_la1[i] = -1;
     for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
   }
@@ -1128,5 +1708,5 @@
     jj_ntk = -1;
     jj_gen = 0;
-    for (int i = 0; i < 38; i++) jj_la1[i] = -1;
+    for (int i = 0; i < 40; i++) jj_la1[i] = -1;
     for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
   }
@@ -1138,5 +1718,5 @@
     jj_ntk = -1;
     jj_gen = 0;
-    for (int i = 0; i < 38; i++) jj_la1[i] = -1;
+    for (int i = 0; i < 40; i++) jj_la1[i] = -1;
     for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
   }
@@ -1148,5 +1728,5 @@
     jj_ntk = -1;
     jj_gen = 0;
-    for (int i = 0; i < 38; i++) jj_la1[i] = -1;
+    for (int i = 0; i < 40; i++) jj_la1[i] = -1;
     for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
   }
@@ -1260,10 +1840,10 @@
   public ParseException generateParseException() {
     jj_expentries.clear();
-    boolean[] la1tokens = new boolean[37];
+    boolean[] la1tokens = new boolean[41];
     if (jj_kind >= 0) {
       la1tokens[jj_kind] = true;
       jj_kind = -1;
     }
-    for (int i = 0; i < 38; i++) {
+    for (int i = 0; i < 40; i++) {
       if (jj_la1[i] == jj_gen) {
         for (int j = 0; j < 32; j++) {
@@ -1277,5 +1857,5 @@
       }
     }
-    for (int i = 0; i < 37; i++) {
+    for (int i = 0; i < 41; i++) {
       if (la1tokens[i]) {
         jj_expentry = new int[1];
@@ -1304,5 +1884,5 @@
   private void jj_rescan_token() {
     jj_rescan = true;
-    for (int i = 0; i < 4; i++) {
+    for (int i = 0; i < 5; i++) {
     try {
       JJCalls p = jj_2_rtns[i];
@@ -1315,4 +1895,5 @@
             case 2: jj_3_3(); break;
             case 3: jj_3_4(); break;
+            case 4: jj_3_5(); break;
           }
         }
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/parser/MapCSSParser.jj
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/parser/MapCSSParser.jj	(revision 3875)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/parser/MapCSSParser.jj	(revision 3876)
@@ -36,5 +36,7 @@
 |   < UINT: ["1"-"9"] ( ["0"-"9"] )* >
 |   < UFLOAT: ( ["0"-"9"] )+ ( "." ( ["0"-"9"] )+ )? >
-|   < STRING: "\"" ( [" ","!","#"-"&","("-"[","]"-"~","\u0080"-"\uFFFF"] | "\\\"" | "\\\\" )*  "\"" >
+|   < STRING: "\"" ( [" ","!","#"-"[","]"-"~","\u0080"-"\uFFFF"] | "\\\"" | "\\\\" )*  "\"" >
+|   < #REGEX_CHAR_WITHOUT_STAR: [" "-")","+"-".","0"-"[","]"-"~","\u0080"-"\uFFFF"] | "\\/" | "\\\\" >
+|   < REGEX: "/" <REGEX_CHAR_WITHOUT_STAR> ( <REGEX_CHAR_WITHOUT_STAR> | "*" )*  "/" >
 |   < #H: ["0"-"9","a"-"f","A"-"F"] >
 |   < HEXCOLOR: "#" ( <H><H><H><H><H><H> | <H><H><H> ) >
@@ -54,5 +56,5 @@
 |   < EQUAL: "=" >
 |   < EXCLAMATION: "!" >
-|   < EXCLAMATION_EQUAL: "!=" >
+|   < TILDE: "~" >
 |   < COLON: ":" >
 |   < DCOLON: "::" >
@@ -65,4 +67,6 @@
 |   < AMPERSAND: "&" >
 |   < QUESTION: "?" >
+|   < DOLLAR: "$" >
+|   < CARET: "^" >
 |   < COMMENT_START: "/*" > : COMMENT
 |   < UNEXPECTED_CHAR : ~[] > // avoid TokenMgrErrors because they are hard to recover from
@@ -122,4 +126,12 @@
 }
 
+float float_() :
+{
+    float f;
+}
+{
+    <MINUS> f=ufloat() { return -f; } | f=ufloat() { return f; }
+}
+
 String string() :
 {
@@ -128,7 +140,5 @@
 {
     t=<STRING>
-    {
-        return t.image.substring(1, t.image.length() - 1).replace("\\\"", "\"").replace("\\\\", "\\");
-    }
+    { return t.image.substring(1, t.image.length() - 1).replace("\\\"", "\"").replace("\\\\", "\\"); }
 }
 
@@ -140,4 +150,13 @@
 {
     t=<IDENT> { return t.image; } | s=string() { return s; }
+}
+
+String regex() :
+{
+    Token t;
+}
+{
+    t=<REGEX>
+    { return t.image.substring(1, t.image.length() - 1); }
 }
 
@@ -159,5 +178,5 @@
 }
 {
-    ( <S> | ( <COMMENT_START> <COMMENT_END> ) )*
+    ( <S> | <COMMENT_START> <COMMENT_END> )*
 }
 
@@ -192,5 +211,12 @@
     { this.sheet = sheet; }
     w()
-    ( r=rule() { if (r != null) { sheet.rules.add(r); } } w() )*
+    (
+        try {
+            r=rule() { if (r != null) { sheet.rules.add(r); } } w()
+        } catch (ParseException ex) {
+            error_skipto(RBRACE);
+            w();
+        }
+    )*
     <EOF>
 }
@@ -203,14 +229,9 @@
 }
 {
-    try {
+    sel=selector() { selectors.add(sel); } w()
+    (
+        <COMMA> w()
         sel=selector() { selectors.add(sel); } w()
-        (
-            <COMMA> w()
-            sel=selector() { selectors.add(sel); } w()
-        )*
-    } catch (ParseException ex) {
-        error_skipto(RBRACE);
-        return null;
-    }
+    )*
     decl=declaration()
     { return new MapCSSRule(selectors, decl); }
@@ -241,6 +262,7 @@
     <PIPE_Z>
     (
-        ( <MINUS> max=uint() ) |
-        ( min=uint() ( <MINUS> ( max=uint() )? )? )
+            <MINUS> max=uint()
+        |
+            min=uint() ( <MINUS> ( max=uint() )? )?
     )
     { return new Pair<Integer, Integer>(min, max); }
@@ -254,15 +276,13 @@
 {
     <LSQUARE>
-    ( 
-        LOOKAHEAD(2)
-            ( c=simple_key_condition() <RSQUARE> { return c; } )
-        |   
+    (
         LOOKAHEAD(3)
-            c=simple_key_value_condition() 
-        |   
-            e=expression() { c = new Condition.ExpressionCondition(e); }
+            c=simple_key_condition() <RSQUARE> { return c; }
+        |
+        LOOKAHEAD(5)
+            c=simple_key_value_condition() <RSQUARE> { return c; }
+        |
+            e=expression() <RSQUARE> { return new Condition.ExpressionCondition(e); }
     )
-    <RSQUARE>
-    { return c; }
 }
 
@@ -280,13 +300,45 @@
 Condition simple_key_value_condition() :
 {
-    boolean not = false;
     String key;
     String val;
+    float f;
+    Condition.Op op;
 }
 {
     key=string_or_ident()
-    ( <EXCLAMATION_EQUAL> { not = true; } | <EQUAL> )
-    val=string_or_ident()
-    { return new Condition.KeyValueCondition(key, val, not ? Condition.Op.NEQ : Condition.Op.EQ); }
+    (
+            (
+                    <EXCLAMATION> <EQUAL> { op=Condition.Op.NEQ; } val=string_or_ident()
+                |
+                    <EQUAL> { op=Condition.Op.EQ; }
+                    (
+                            <TILDE> { op=Condition.Op.REGEX; }
+                            val=regex()
+                        |
+                            val=string_or_ident()
+                    )
+                |
+                    <TILDE> <EQUAL> { op=Condition.Op.ONE_OF; } val=string_or_ident()
+                |
+                    <CARET> <EQUAL> { op=Condition.Op.BEGINS_WITH; } val=string_or_ident()
+                |
+                    <DOLLAR> <EQUAL> { op=Condition.Op.ENDS_WITH; } val=string_or_ident()
+                |
+                    <STAR> <EQUAL> { op=Condition.Op.CONTAINS; } val=string_or_ident()
+            )
+            { return new Condition.KeyValueCondition(key, val, op); }
+        |
+            (
+                    <GREATER_EQUAL> { op=Condition.Op.GREATER_OR_EQUAL; }
+                |
+                    <GREATER> { op=Condition.Op.GREATER; }
+                |
+                    <LESS_EQUAL> { op=Condition.Op.LESS_OR_EQUAL; }
+                |
+                    <LESS> { op=Condition.Op.LESS; }
+            )
+            f=float_()
+            { return new Condition.KeyValueCondition(key, Float.toString(f), op); }
+    )
 }
 
@@ -307,5 +359,5 @@
 }
 {
-    ( <SLASH> | <DCOLON> )
+    <DCOLON>
     ( t=<IDENT> | t=<STAR> )
     { return t.image; }
@@ -316,42 +368,28 @@
     List<Instruction> ins = new ArrayList<Instruction>();
     Instruction i;
-}
-{
-    <LBRACE> w()
-    ( <RBRACE> { return ins; } )?
-    try {
-        i=instruction() { if (i != null) ins.add(i); }
-        (
-            <SEMICOLON> w()
-            ( <RBRACE> { return ins; } )?
-            i=instruction() { if (i != null) ins.add(i); }
-        )*
-        <RBRACE> { return ins; }
-    } catch (ParseException ex) {
-        error_skipto(RBRACE);
-        return ins;
-    }
-}
-
-Instruction instruction() :
-{
     Token key;
     Object val;
 }
 {
-    key=<IDENT> w()
-    <COLON> w()
-    (
-        LOOKAHEAD(2) // both number and float array start with a number
-            ( val=float_array() w() )
-        |
-            val=expression()
-    )
-    {
-        if (val instanceof LiteralExpression)
-            return new Instruction.AssignmentInstruction(key.image, ((LiteralExpression) val).evaluate(null));
-        else
-            return new Instruction.AssignmentInstruction(key.image, val);
-    }
+    <LBRACE> w()
+    (
+        key=<IDENT> w() <COLON> w()
+        (
+            LOOKAHEAD( float_array() w() ( <SEMICOLON> | <RBRACE> ) )
+                val=float_array()
+                { ins.add(new Instruction.AssignmentInstruction(key.image, val)); }
+                w()
+                ( <RBRACE> { return ins; } | <SEMICOLON> w() )
+            |
+            LOOKAHEAD( expression() ( <SEMICOLON> | <RBRACE> ) )
+                val=expression()
+                { ins.add(new Instruction.AssignmentInstruction(key.image, val)); }
+                ( <RBRACE> { return ins; } | <SEMICOLON> w() )
+            |
+                val=readRaw() w() { ins.add(new Instruction.AssignmentInstruction(key.image, val)); }
+        )
+    )*
+    <RBRACE>
+    { return ins; }
 }
 
@@ -364,9 +402,9 @@
 {
     (
-        ( <EXCLAMATION> { op = "not"; } w() e=primary() { args.add(e); } w() )
-    |
-        ( <MINUS> { op = "minus"; } w() e=primary() { args.add(e); } w() )
-    |
-    
+        <EXCLAMATION> { op = "not"; } w() e=primary() { args.add(e); } w()
+    |
+        <MINUS> { op = "minus"; } w() e=primary() { args.add(e); } w()
+    |
+
         (
             e=primary() { args.add(e); } w()
@@ -380,19 +418,19 @@
                     ( <SLASH> { op = "divided_by"; } w() e=primary() { args.add(e); } w() )+
                 |
-                    ( <GREATER_EQUAL> { op = "greater_equal"; } w() e=primary() { args.add(e); } w() )
-                |
-                    ( <LESS_EQUAL> { op = "less_equal"; } w() e=primary() { args.add(e); } w() )
-                |
-                    ( <GREATER> { op = "greater"; } w() e=primary() { args.add(e); } w() )
-                |
-                    ( <EQUAL> ( <EQUAL> )? { op = "equal"; } w() e=primary() { args.add(e); } w() )
-                |
-                    ( <LESS> { op = "less"; } w() e=primary() { args.add(e); } w() )
-                |
-                    ( <AMPERSAND> <AMPERSAND> { op = "and"; } w() e=primary() { args.add(e); } w() )
-                |
-                    ( <PIPE> <PIPE> { op = "or"; } w() e=primary() { args.add(e); } w() )
-                |
-                    ( <QUESTION> { op = "cond"; } w() e=primary() { args.add(e); } w() <COLON> w() e=primary() { args.add(e); } w() )
+                    <GREATER_EQUAL> { op = "greater_equal"; } w() e=primary() { args.add(e); } w()
+                |
+                    <LESS_EQUAL> { op = "less_equal"; } w() e=primary() { args.add(e); } w()
+                |
+                    <GREATER> { op = "greater"; } w() e=primary() { args.add(e); } w()
+                |
+                    <EQUAL> ( <EQUAL> )? { op = "equal"; } w() e=primary() { args.add(e); } w()
+                |
+                    <LESS> { op = "less"; } w() e=primary() { args.add(e); } w()
+                |
+                    <AMPERSAND> <AMPERSAND> { op = "and"; } w() e=primary() { args.add(e); } w()
+                |
+                    <PIPE> <PIPE> { op = "or"; } w() e=primary() { args.add(e); } w()
+                |
+                    <QUESTION> { op = "cond"; } w() e=primary() { args.add(e); } w() <COLON> w() e=primary() { args.add(e); } w()
             )?
         )
@@ -417,5 +455,5 @@
         lit=literal() { return new LiteralExpression(lit); }
     |
-        ( <LPAR> w() nested=expression() <RPAR> ) { return nested; }
+        <LPAR> w() nested=expression() <RPAR> { return nested; }
 }
 
@@ -447,5 +485,5 @@
         val=string_or_ident() { return val; }
     |
-        ( <PLUS> f=ufloat() ) { return new Instruction.RelativeFloat(f); }
+        <PLUS> f=ufloat() { return new Instruction.RelativeFloat(f); }
     |
         f=ufloat() { return f; }
@@ -466,4 +504,5 @@
 void error_skipto(int kind) {
     ParseException e = generateParseException();
+    System.err.println("Skipping to the next rule, because of an error:");
     System.err.println(e);
     if (sheet != null) {
@@ -478,2 +517,20 @@
 }
 
+JAVACODE
+/**
+ * read everything to the next semicolon
+ */
+String readRaw() {
+    Token t;
+    StringBuilder s = new StringBuilder();
+    while (true) {
+        t = getNextToken();
+        if (t.kind == SEMICOLON || t.kind == EOF)
+            break;
+        s.append(t.image);
+    }
+    if (t.kind == EOF)
+        throw new ParseException("Reached end of file while parsing");
+    return s.toString();
+}
+
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/parser/MapCSSParserConstants.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/parser/MapCSSParserConstants.java	(revision 3875)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/parser/MapCSSParserConstants.java	(revision 3876)
@@ -20,65 +20,73 @@
   int STRING = 4;
   /** RegularExpression Id. */
-  int H = 5;
+  int REGEX_CHAR_WITHOUT_STAR = 5;
   /** RegularExpression Id. */
-  int HEXCOLOR = 6;
+  int REGEX = 6;
   /** RegularExpression Id. */
-  int S = 7;
+  int H = 7;
   /** RegularExpression Id. */
-  int STAR = 8;
+  int HEXCOLOR = 8;
   /** RegularExpression Id. */
-  int SLASH = 9;
+  int S = 9;
   /** RegularExpression Id. */
-  int LBRACE = 10;
+  int STAR = 10;
   /** RegularExpression Id. */
-  int RBRACE = 11;
+  int SLASH = 11;
   /** RegularExpression Id. */
-  int LSQUARE = 12;
+  int LBRACE = 12;
   /** RegularExpression Id. */
-  int RSQUARE = 13;
+  int RBRACE = 13;
   /** RegularExpression Id. */
-  int LPAR = 14;
+  int LSQUARE = 14;
   /** RegularExpression Id. */
-  int RPAR = 15;
+  int RSQUARE = 15;
   /** RegularExpression Id. */
-  int GREATER_EQUAL = 16;
+  int LPAR = 16;
   /** RegularExpression Id. */
-  int LESS_EQUAL = 17;
+  int RPAR = 17;
   /** RegularExpression Id. */
-  int GREATER = 18;
+  int GREATER_EQUAL = 18;
   /** RegularExpression Id. */
-  int LESS = 19;
+  int LESS_EQUAL = 19;
   /** RegularExpression Id. */
-  int EQUAL = 20;
+  int GREATER = 20;
   /** RegularExpression Id. */
-  int EXCLAMATION = 21;
+  int LESS = 21;
   /** RegularExpression Id. */
-  int EXCLAMATION_EQUAL = 22;
+  int EQUAL = 22;
   /** RegularExpression Id. */
-  int COLON = 23;
+  int EXCLAMATION = 23;
   /** RegularExpression Id. */
-  int DCOLON = 24;
+  int TILDE = 24;
   /** RegularExpression Id. */
-  int SEMICOLON = 25;
+  int COLON = 25;
   /** RegularExpression Id. */
-  int COMMA = 26;
+  int DCOLON = 26;
   /** RegularExpression Id. */
-  int PIPE = 27;
+  int SEMICOLON = 27;
   /** RegularExpression Id. */
-  int PIPE_Z = 28;
+  int COMMA = 28;
   /** RegularExpression Id. */
-  int PLUS = 29;
+  int PIPE = 29;
   /** RegularExpression Id. */
-  int MINUS = 30;
+  int PIPE_Z = 30;
   /** RegularExpression Id. */
-  int AMPERSAND = 31;
+  int PLUS = 31;
   /** RegularExpression Id. */
-  int QUESTION = 32;
+  int MINUS = 32;
   /** RegularExpression Id. */
-  int COMMENT_START = 33;
+  int AMPERSAND = 33;
   /** RegularExpression Id. */
-  int UNEXPECTED_CHAR = 34;
+  int QUESTION = 34;
   /** RegularExpression Id. */
-  int COMMENT_END = 35;
+  int DOLLAR = 35;
+  /** RegularExpression Id. */
+  int CARET = 36;
+  /** RegularExpression Id. */
+  int COMMENT_START = 37;
+  /** RegularExpression Id. */
+  int UNEXPECTED_CHAR = 38;
+  /** RegularExpression Id. */
+  int COMMENT_END = 39;
 
   /** Lexical state. */
@@ -94,4 +102,6 @@
     "<UFLOAT>",
     "<STRING>",
+    "<REGEX_CHAR_WITHOUT_STAR>",
+    "<REGEX>",
     "<H>",
     "<HEXCOLOR>",
@@ -111,5 +121,5 @@
     "\"=\"",
     "\"!\"",
-    "\"!=\"",
+    "\"~\"",
     "\":\"",
     "\"::\"",
@@ -122,8 +132,10 @@
     "\"&\"",
     "\"?\"",
+    "\"$\"",
+    "\"^\"",
     "\"/*\"",
     "<UNEXPECTED_CHAR>",
     "\"*/\"",
-    "<token of kind 36>",
+    "<token of kind 40>",
   };
 
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/parser/MapCSSParserTokenManager.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/parser/MapCSSParserTokenManager.java	(revision 3875)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/parser/MapCSSParserTokenManager.java	(revision 3876)
@@ -26,4 +26,8 @@
    switch (pos)
    {
+      case 0:
+         if ((active0 & 0x2000000800L) != 0L)
+            return 14;
+         return -1;
       default :
          return -1;
@@ -45,49 +49,54 @@
    {
       case 33:
+         return jjStopAtPos(0, 23);
+      case 36:
+         return jjStopAtPos(0, 35);
+      case 38:
+         return jjStopAtPos(0, 33);
+      case 40:
+         return jjStopAtPos(0, 16);
+      case 41:
+         return jjStopAtPos(0, 17);
+      case 42:
+         return jjStopAtPos(0, 10);
+      case 43:
+         return jjStopAtPos(0, 31);
+      case 44:
+         return jjStopAtPos(0, 28);
+      case 45:
+         return jjStopAtPos(0, 32);
+      case 47:
+         jjmatchedKind = 11;
+         return jjMoveStringLiteralDfa1_0(0x2000000000L);
+      case 58:
+         jjmatchedKind = 25;
+         return jjMoveStringLiteralDfa1_0(0x4000000L);
+      case 59:
+         return jjStopAtPos(0, 27);
+      case 60:
          jjmatchedKind = 21;
-         return jjMoveStringLiteralDfa1_0(0x400000L);
-      case 38:
-         return jjStopAtPos(0, 31);
-      case 40:
+         return jjMoveStringLiteralDfa1_0(0x80000L);
+      case 61:
+         return jjStopAtPos(0, 22);
+      case 62:
+         jjmatchedKind = 20;
+         return jjMoveStringLiteralDfa1_0(0x40000L);
+      case 63:
+         return jjStopAtPos(0, 34);
+      case 91:
          return jjStopAtPos(0, 14);
-      case 41:
+      case 93:
          return jjStopAtPos(0, 15);
-      case 42:
-         return jjStopAtPos(0, 8);
-      case 43:
-         return jjStopAtPos(0, 29);
-      case 44:
-         return jjStopAtPos(0, 26);
-      case 45:
-         return jjStopAtPos(0, 30);
-      case 47:
-         jjmatchedKind = 9;
-         return jjMoveStringLiteralDfa1_0(0x200000000L);
-      case 58:
-         jjmatchedKind = 23;
-         return jjMoveStringLiteralDfa1_0(0x1000000L);
-      case 59:
-         return jjStopAtPos(0, 25);
-      case 60:
-         jjmatchedKind = 19;
-         return jjMoveStringLiteralDfa1_0(0x20000L);
-      case 61:
-         return jjStopAtPos(0, 20);
-      case 62:
-         jjmatchedKind = 18;
-         return jjMoveStringLiteralDfa1_0(0x10000L);
-      case 63:
-         return jjStopAtPos(0, 32);
-      case 91:
+      case 94:
+         return jjStopAtPos(0, 36);
+      case 123:
          return jjStopAtPos(0, 12);
-      case 93:
+      case 124:
+         jjmatchedKind = 29;
+         return jjMoveStringLiteralDfa1_0(0x40000000L);
+      case 125:
          return jjStopAtPos(0, 13);
-      case 123:
-         return jjStopAtPos(0, 10);
-      case 124:
-         jjmatchedKind = 27;
-         return jjMoveStringLiteralDfa1_0(0x10000000L);
-      case 125:
-         return jjStopAtPos(0, 11);
+      case 126:
+         return jjStopAtPos(0, 24);
       default :
          return jjMoveNfa_0(0, 0);
@@ -104,22 +113,20 @@
    {
       case 42:
-         if ((active0 & 0x200000000L) != 0L)
-            return jjStopAtPos(1, 33);
+         if ((active0 & 0x2000000000L) != 0L)
+            return jjStopAtPos(1, 37);
          break;
       case 58:
-         if ((active0 & 0x1000000L) != 0L)
-            return jjStopAtPos(1, 24);
+         if ((active0 & 0x4000000L) != 0L)
+            return jjStopAtPos(1, 26);
          break;
       case 61:
-         if ((active0 & 0x10000L) != 0L)
-            return jjStopAtPos(1, 16);
-         else if ((active0 & 0x20000L) != 0L)
-            return jjStopAtPos(1, 17);
-         else if ((active0 & 0x400000L) != 0L)
-            return jjStopAtPos(1, 22);
+         if ((active0 & 0x40000L) != 0L)
+            return jjStopAtPos(1, 18);
+         else if ((active0 & 0x80000L) != 0L)
+            return jjStopAtPos(1, 19);
          break;
       case 122:
-         if ((active0 & 0x10000000L) != 0L)
-            return jjStopAtPos(1, 28);
+         if ((active0 & 0x40000000L) != 0L)
+            return jjStopAtPos(1, 30);
          break;
       default :
@@ -137,5 +144,5 @@
 {
    int startsAt = 0;
-   jjnewStateCnt = 22;
+   jjnewStateCnt = 30;
    int i = 1;
    jjstateSet[0] = startState;
@@ -152,4 +159,8 @@
             switch(jjstateSet[--i])
             {
+               case 14:
+                  if ((0xffff7bff00000000L & l) != 0L)
+                     jjCheckNAddStates(0, 2);
+                  break;
                case 0:
                   if ((0x3ff000000000000L & l) != 0L)
@@ -161,12 +172,14 @@
                   else if ((0x100003600L & l) != 0L)
                   {
-                     if (kind > 7)
-                        kind = 7;
-                     jjCheckNAdd(21);
+                     if (kind > 9)
+                        kind = 9;
+                     jjCheckNAdd(29);
                   }
                   else if (curChar == 35)
-                     jjstateSet[jjnewStateCnt++] = 14;
+                     jjstateSet[jjnewStateCnt++] = 22;
+                  else if (curChar == 47)
+                     jjAddStates(3, 4);
                   else if (curChar == 34)
-                     jjCheckNAddStates(0, 2);
+                     jjCheckNAddStates(5, 7);
                   if ((0x3fe000000000000L & l) != 0L)
                   {
@@ -218,9 +231,9 @@
                case 11:
                   if (curChar == 34)
-                     jjCheckNAddStates(0, 2);
+                     jjCheckNAddStates(5, 7);
                   break;
                case 8:
-                  if ((0xffffff7b00000000L & l) != 0L)
-                     jjCheckNAddStates(0, 2);
+                  if ((0xfffffffb00000000L & l) != 0L)
+                     jjCheckNAddStates(5, 7);
                   break;
                case 9:
@@ -229,38 +242,54 @@
                   break;
                case 13:
+                  if (curChar == 47)
+                     jjAddStates(3, 4);
+                  break;
+               case 15:
+                  if ((0xffff7fff00000000L & l) != 0L)
+                     jjCheckNAddStates(0, 2);
+                  break;
+               case 16:
+                  if (curChar == 47 && kind > 6)
+                     kind = 6;
+                  break;
+               case 19:
+                  if (curChar == 47)
+                     jjCheckNAddStates(0, 2);
+                  break;
+               case 21:
                   if (curChar == 35)
-                     jjstateSet[jjnewStateCnt++] = 14;
-                  break;
-               case 14:
+                     jjstateSet[jjnewStateCnt++] = 22;
+                  break;
+               case 22:
                   if ((0x3ff000000000000L & l) != 0L)
-                     jjAddStates(3, 4);
-                  break;
-               case 15:
+                     jjAddStates(8, 9);
+                  break;
+               case 23:
                   if ((0x3ff000000000000L & l) != 0L)
-                     jjstateSet[jjnewStateCnt++] = 16;
-                  break;
-               case 16:
+                     jjstateSet[jjnewStateCnt++] = 24;
+                  break;
+               case 24:
                   if ((0x3ff000000000000L & l) != 0L)
-                     jjstateSet[jjnewStateCnt++] = 17;
-                  break;
-               case 17:
+                     jjstateSet[jjnewStateCnt++] = 25;
+                  break;
+               case 25:
                   if ((0x3ff000000000000L & l) != 0L)
-                     jjstateSet[jjnewStateCnt++] = 18;
-                  break;
-               case 18:
-               case 20:
+                     jjstateSet[jjnewStateCnt++] = 26;
+                  break;
+               case 26:
+               case 28:
                   if ((0x3ff000000000000L & l) != 0L)
-                     jjCheckNAdd(19);
-                  break;
-               case 19:
-                  if ((0x3ff000000000000L & l) != 0L && kind > 6)
-                     kind = 6;
-                  break;
-               case 21:
+                     jjCheckNAdd(27);
+                  break;
+               case 27:
+                  if ((0x3ff000000000000L & l) != 0L && kind > 8)
+                     kind = 8;
+                  break;
+               case 29:
                   if ((0x100003600L & l) == 0L)
                      break;
-                  if (kind > 7)
-                     kind = 7;
-                  jjCheckNAdd(21);
+                  if (kind > 9)
+                     kind = 9;
+                  jjCheckNAdd(29);
                   break;
                default : break;
@@ -275,4 +304,10 @@
             switch(jjstateSet[--i])
             {
+               case 14:
+                  if ((0x7fffffffefffffffL & l) != 0L)
+                     jjCheckNAddStates(0, 2);
+                  else if (curChar == 92)
+                     jjCheckNAddTwoStates(19, 18);
+                  break;
                case 0:
                case 1:
@@ -285,38 +320,54 @@
                case 8:
                   if ((0x7fffffffefffffffL & l) != 0L)
-                     jjCheckNAddStates(0, 2);
+                     jjCheckNAddStates(5, 7);
                   break;
                case 10:
                   if (curChar == 92)
-                     jjAddStates(5, 6);
+                     jjAddStates(10, 11);
                   break;
                case 12:
                   if (curChar == 92)
+                     jjCheckNAddStates(5, 7);
+                  break;
+               case 15:
+                  if ((0x7fffffffefffffffL & l) != 0L)
                      jjCheckNAddStates(0, 2);
                   break;
-               case 14:
+               case 17:
+                  if (curChar == 92)
+                     jjCheckNAddTwoStates(18, 19);
+                  break;
+               case 18:
+                  if (curChar == 92)
+                     jjCheckNAddStates(0, 2);
+                  break;
+               case 20:
+                  if (curChar == 92)
+                     jjCheckNAddTwoStates(19, 18);
+                  break;
+               case 22:
                   if ((0x7e0000007eL & l) != 0L)
-                     jjAddStates(3, 4);
-                  break;
-               case 15:
+                     jjAddStates(8, 9);
+                  break;
+               case 23:
                   if ((0x7e0000007eL & l) != 0L)
-                     jjstateSet[jjnewStateCnt++] = 16;
-                  break;
-               case 16:
+                     jjstateSet[jjnewStateCnt++] = 24;
+                  break;
+               case 24:
                   if ((0x7e0000007eL & l) != 0L)
-                     jjstateSet[jjnewStateCnt++] = 17;
-                  break;
-               case 17:
+                     jjstateSet[jjnewStateCnt++] = 25;
+                  break;
+               case 25:
                   if ((0x7e0000007eL & l) != 0L)
-                     jjstateSet[jjnewStateCnt++] = 18;
-                  break;
-               case 18:
-               case 20:
+                     jjstateSet[jjnewStateCnt++] = 26;
+                  break;
+               case 26:
+               case 28:
                   if ((0x7e0000007eL & l) != 0L)
-                     jjCheckNAdd(19);
-                  break;
-               case 19:
-                  if ((0x7e0000007eL & l) != 0L && kind > 6)
-                     kind = 6;
+                     jjCheckNAdd(27);
+                  break;
+               case 27:
+                  if ((0x7e0000007eL & l) != 0L && kind > 8)
+                     kind = 8;
                   break;
                default : break;
@@ -335,7 +386,12 @@
             switch(jjstateSet[--i])
             {
+               case 14:
+               case 15:
+                  if (jjCanMove_0(hiByte, i1, i2, l1, l2))
+                     jjCheckNAddStates(0, 2);
+                  break;
                case 8:
                   if (jjCanMove_0(hiByte, i1, i2, l1, l2))
-                     jjAddStates(0, 2);
+                     jjAddStates(5, 7);
                   break;
                default : break;
@@ -350,5 +406,5 @@
       }
       ++curPos;
-      if ((i = jjnewStateCnt) == (startsAt = 22 - (jjnewStateCnt = startsAt)))
+      if ((i = jjnewStateCnt) == (startsAt = 30 - (jjnewStateCnt = startsAt)))
          return curPos;
       try { curChar = input_stream.readChar(); }
@@ -361,5 +417,5 @@
    {
       case 42:
-         return jjMoveStringLiteralDfa1_1(0x800000000L);
+         return jjMoveStringLiteralDfa1_1(0x8000000000L);
       default :
          return 1;
@@ -375,6 +431,6 @@
    {
       case 47:
-         if ((active0 & 0x800000000L) != 0L)
-            return jjStopAtPos(1, 35);
+         if ((active0 & 0x8000000000L) != 0L)
+            return jjStopAtPos(1, 39);
          break;
       default :
@@ -384,5 +440,5 @@
 }
 static final int[] jjnextStates = {
-   8, 9, 10, 15, 20, 11, 12, 
+   15, 16, 17, 14, 20, 8, 9, 10, 23, 28, 11, 12, 
 };
 private static final boolean jjCanMove_0(int hiByte, int i1, int i2, long l1, long l2)
@@ -401,8 +457,8 @@
 /** Token literal values. */
 public static final String[] jjstrLiteralImages = {
-"", null, null, null, null, null, null, null, "\52", "\57", "\173", "\175", 
-"\133", "\135", "\50", "\51", "\76\75", "\74\75", "\76", "\74", "\75", "\41", 
-"\41\75", "\72", "\72\72", "\73", "\54", "\174", "\174\172", "\53", "\55", "\46", "\77", 
-"\57\52", null, "\52\57", null, };
+"", null, null, null, null, null, null, null, null, null, "\52", "\57", 
+"\173", "\175", "\133", "\135", "\50", "\51", "\76\75", "\74\75", "\76", "\74", "\75", 
+"\41", "\176", "\72", "\72\72", "\73", "\54", "\174", "\174\172", "\53", "\55", 
+"\46", "\77", "\44", "\136", "\57\52", null, "\52\57", null, };
 
 /** Lexer state names. */
@@ -415,15 +471,15 @@
 public static final int[] jjnewLexState = {
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-   -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 0, -1, 
+   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 0, -1, 
 };
 static final long[] jjtoToken = {
-   0xfffffffdfL, 
+   0xffffffff5fL, 
 };
 static final long[] jjtoSkip = {
-   0x1000000000L, 
+   0x10000000000L, 
 };
 protected SimpleCharStream input_stream;
-private final int[] jjrounds = new int[22];
-private final int[] jjstateSet = new int[44];
+private final int[] jjrounds = new int[30];
+private final int[] jjstateSet = new int[60];
 protected char curChar;
 /** Constructor. */
@@ -452,5 +508,5 @@
    int i;
    jjround = 0x80000001;
-   for (i = 22; i-- > 0;)
+   for (i = 30; i-- > 0;)
       jjrounds[i] = 0x80000000;
 }
@@ -529,7 +585,7 @@
        jjmatchedPos = 0;
        curPos = jjMoveStringLiteralDfa0_0();
-       if (jjmatchedPos == 0 && jjmatchedKind > 34)
+       if (jjmatchedPos == 0 && jjmatchedKind > 38)
        {
-          jjmatchedKind = 34;
+          jjmatchedKind = 38;
        }
        break;
@@ -538,7 +594,7 @@
        jjmatchedPos = 0;
        curPos = jjMoveStringLiteralDfa0_1();
-       if (jjmatchedPos == 0 && jjmatchedKind > 36)
+       if (jjmatchedPos == 0 && jjmatchedKind > 40)
        {
-          jjmatchedKind = 36;
+          jjmatchedKind = 40;
        }
        break;
