Index: trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Condition.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Condition.java	(revision 6558)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Condition.java	(revision 6560)
@@ -22,5 +22,5 @@
     abstract public boolean applies(Environment e);
 
-    public static Condition create(String k, String v, Op op, Context context, boolean considerValAsKey) {
+    public static Condition createKeyValueCondition(String k, String v, Op op, Context context, boolean considerValAsKey) {
         switch (context) {
         case PRIMITIVE:
@@ -41,5 +41,5 @@
     }
 
-    public static Condition create(String k, boolean not, KeyMatchType matchType, Context context) {
+    public static Condition createKeyCondition(String k, boolean not, KeyMatchType matchType, Context context) {
         switch (context) {
         case PRIMITIVE:
@@ -57,9 +57,13 @@
     }
 
-    public static Condition create(String id, boolean not, Context context) {
+    public static Condition createPseudoClassCondition(String id, boolean not, Context context) {
         return new PseudoClassCondition(id, not);
     }
 
-    public static Condition create(Expression e, Context context) {
+    public static Condition createClassCondition(String id, boolean not, Context context) {
+        return new ClassCondition(id, not);
+    }
+
+    public static Condition createExpressionCondition(Expression e, Context context) {
         return new ExpressionCondition(e);
     }
@@ -275,4 +279,25 @@
     }
 
+    public static class ClassCondition extends Condition {
+
+        public final String id;
+        public final boolean not;
+
+        public ClassCondition(String id, boolean not) {
+            this.id = id;
+            this.not = not;
+        }
+
+        @Override
+        public boolean applies(Environment env) {
+            return not ^ env.mc.getCascade(env.layer).containsKey(id);
+        }
+
+        @Override
+        public String toString() {
+            return (not ? "!" : "") + "." + id;
+        }
+    }
+
     public static class PseudoClassCondition extends Condition {
 
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/ExpressionFactory.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/ExpressionFactory.java	(revision 6558)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/ExpressionFactory.java	(revision 6560)
@@ -84,4 +84,9 @@
         Environment env;
 
+        /**
+         * Identity function for compatibility with MapCSS specification.
+         * @param o any object
+         * @return {@code o} unchanged
+         */
         public static Object eval(Object o) {
             return o;
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParser.jj
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParser.jj	(revision 6558)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParser.jj	(revision 6560)
@@ -42,5 +42,6 @@
 TOKEN:
 {
-    < IDENT: ["a"-"z","A"-"Z","_"] ( ["a"-"z","A"-"Z","_","-","0"-"9"] )* >
+    < SET: ("set" | "SET") >
+|   < IDENT: ["a"-"z","A"-"Z","_"] ( ["a"-"z","A"-"Z","_","-","0"-"9"] )* >
 |   < UINT: ["1"-"9"] ( ["0"-"9"] )* >
 |   < UFLOAT: ( ["0"-"9"] )+ ( "." ( ["0"-"9"] )+ )? >
@@ -78,4 +79,5 @@
 |   < DOLLAR: "$" >
 |   < CARET: "^" >
+|   < FULLSTOP: "." >
 |   < COMMENT_START: "/*" > : COMMENT
 |   < UNEXPECTED_CHAR : ~[] > // avoid TokenMgrErrors because they are hard to recover from
@@ -271,5 +273,5 @@
     (
         ( <GREATER> { parentSelector = false; } | <LESS> { parentSelector = true; } ) 
-        ( ( c=condition(Context.LINK) | c=pseudoclass(Context.LINK) ) { conditions.add(c); } )*
+        ( ( c=condition(Context.LINK) | c=class_or_pseudoclass(Context.LINK) ) { conditions.add(c); } )*
         { selLink = new LinkSelector(conditions); }
         w()
@@ -290,5 +292,5 @@
     ( base=<IDENT> | base=<STAR> )
     ( r=zoom() )?
-    ( ( c=condition(Context.PRIMITIVE) | c=pseudoclass(Context.PRIMITIVE) ) { conditions.add(c); } )*
+    ( ( c=condition(Context.PRIMITIVE) | c=class_or_pseudoclass(Context.PRIMITIVE) ) { conditions.add(c); } )*
     ( sub=subpart() )?
     { return new GeneralSelector(base.image, r, conditions, sub); }
@@ -327,5 +329,5 @@
             c=simple_key_value_condition(context) s() <RSQUARE> { return c; }
         |
-            e=expression() <RSQUARE> { return Condition.create(e, context); }
+            e=expression() <RSQUARE> { return Condition.createExpressionCondition(e, context); }
     )
 }
@@ -357,5 +359,5 @@
     ( LOOKAHEAD(2) <QUESTION> <EXCLAMATION> { matchType = Condition.KeyMatchType.FALSE; } )?
     (              <QUESTION>               { matchType = Condition.KeyMatchType.TRUE;  } )?
-    { return Condition.create(key, not, matchType, context); }
+    { return Condition.createKeyCondition(key, not, matchType, context); }
 }
 
@@ -418,17 +420,24 @@
             f=float_() { val=Float.toString(f); }
     )
-    { return Condition.create(key, val, op, context, considerValAsKey); }
-}
-
-Condition pseudoclass(Context context) :
+    { return Condition.createKeyValueCondition(key, val, op, context, considerValAsKey); }
+}
+
+Condition class_or_pseudoclass(Context context) :
 {
     Token t;
     boolean not = false;
+    boolean pseudo;
 }
 {
     ( <EXCLAMATION> { not = true; } )? 
-    <COLON>
+    (
+        <FULLSTOP> { pseudo = false; }
+    |
+        <COLON> { pseudo = true; }
+    )
     t=<IDENT>
-    { return Condition.create(t.image, not, context); }
+    { return pseudo
+        ? Condition.createPseudoClassCondition(t.image, not, context)
+        : Condition.createClassCondition(t.image, not, context); }
 }
 
@@ -448,9 +457,16 @@
     Instruction i;
     Token key;
-    Object val;
+    Object val = null;
 }
 {
     <LBRACE> w()
     (
+        (
+        <SET> w() key=<IDENT> w()
+        ( <EQUAL> val=expression() )?
+        { ins.add(new Instruction.AssignmentInstruction(key.image, val == null ? true : val)); }
+        ( <RBRACE> { return ins; } | <SEMICOLON> w() )
+        )
+        |
         key=<IDENT> w() <COLON> w()
         (
