Index: trunk/src/org/openstreetmap/josm/gui/mappaint/LabelCompositionStrategy.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/LabelCompositionStrategy.java	(revision 4006)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/LabelCompositionStrategy.java	(revision 4007)
@@ -48,4 +48,5 @@
     static public class StaticLabelCompositionStrategy extends LabelCompositionStrategy {
         private String defaultLabel;
+
         public StaticLabelCompositionStrategy(String defaultLabel){
             this.defaultLabel = defaultLabel;
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/MapPaintStyles.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/MapPaintStyles.java	(revision 4006)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/MapPaintStyles.java	(revision 4007)
@@ -21,6 +21,6 @@
 import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSStyleSource;
 import org.openstreetmap.josm.gui.mappaint.xml.XmlStyleSource;
+import org.openstreetmap.josm.gui.preferences.MapPaintPreference.MapPaintPrefMigration;
 import org.openstreetmap.josm.gui.preferences.SourceEntry;
-import org.openstreetmap.josm.gui.preferences.MapPaintPreference.MapPaintPrefMigration;
 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
 import org.openstreetmap.josm.io.MirroredInputStream;
@@ -42,9 +42,29 @@
         return styles;
     }
-    
+
+    /**
+     * Value holder for a reference to a tag name. A style instruction
+     * <pre>
+     *    text: a_tag_name;
+     * </pre>
+     * results in a tag reference for the tag <tt>a_tag_name</tt> in the
+     * style cascade.
+     */
+    public static class TagKeyReference {
+        public final String key;
+        public TagKeyReference(String key){
+            this.key = key;
+        }
+
+        @Override
+        public String toString() {
+            return "TagKeyReference{" + "key='" + key + "'}";
+        }
+    }
+
     public static class IconReference {
 
-        public String iconName;
-        public StyleSource source;
+        public final String iconName;
+        public final StyleSource source;
 
         public IconReference(String iconName, StyleSource source) {
@@ -59,6 +79,5 @@
     }
 
-    public static ImageIcon getIcon(IconReference ref, boolean sanitize)
-    {
+    public static ImageIcon getIcon(IconReference ref, boolean sanitize) {
         String namespace = ref.source.getPrefName();
         ImageIcon i = ImageProvider.getIfAvailable(getIconSourceDirs(ref.source), "mappaint."+namespace, null, ref.iconName, ref.source.zipIcons, sanitize);
@@ -112,5 +131,5 @@
             dirs.add("resource://images/styles/");
         }
-        
+
         return dirs;
     }
@@ -130,5 +149,5 @@
             source.loadStyleSource();
         }
-        
+
         fireMapPaintSylesUpdated();
     }
@@ -139,17 +158,14 @@
             in = new MirroredInputStream(entry.url);
             InputStream zip = in.getZipEntry("xml", "style");
-            if (zip != null) {
+            if (zip != null)
                 return new XmlStyleSource(entry);
-            }
             zip = in.getZipEntry("mapcss", "style");
-            if (zip != null) {
+            if (zip != null)
                 return new MapCSSStyleSource(entry);
-            }
-            if (entry.url.toLowerCase().endsWith(".mapcss")) {
+            if (entry.url.toLowerCase().endsWith(".mapcss"))
                 return new MapCSSStyleSource(entry);
-            }
-            if (entry.url.toLowerCase().endsWith(".xml")) {
+            if (entry.url.toLowerCase().endsWith(".xml"))
                 return new XmlStyleSource(entry);
-            } else {
+            else {
                 InputStreamReader reader = new InputStreamReader(in);
                 WHILE: while (true) {
@@ -272,10 +288,9 @@
         Arrays.sort(selSorted);
 
-        if (i < 0) { // Up
+        if (i < 0) // Up
             return selSorted[0] >= -i;
-        } else
-        if (i > 0) { // Down
+        else if (i > 0) // Down
             return selSorted[selSorted.length-1] <= styles.getStyleSources().size() - 1 - i;
-        } else
+        else
             return true;
     }
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/TextElement.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/TextElement.java	(revision 4006)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/TextElement.java	(revision 4007)
@@ -9,5 +9,7 @@
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.gui.mappaint.LabelCompositionStrategy.DeriveLabelFromNameTagsCompositionStrategy;
+import org.openstreetmap.josm.gui.mappaint.LabelCompositionStrategy.StaticLabelCompositionStrategy;
 import org.openstreetmap.josm.gui.mappaint.LabelCompositionStrategy.TagLookupCompositionStrategy;
+import org.openstreetmap.josm.gui.mappaint.MapPaintStyles.TagKeyReference;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
 import org.openstreetmap.josm.tools.Utils;
@@ -81,14 +83,27 @@
      */
     protected static LabelCompositionStrategy buildLabelCompositionStrategy(Cascade c, boolean defaultAnnotate){
-        Keyword textKW = c.get("text", null, Keyword.class, true);
-        if (textKW == null) {
-            String textKey = c.get("text", null, String.class);
-            if (textKey == null) 
-                return defaultAnnotate ? AUTO_LABEL_COMPOSITION_STRATEGY : null;
-            return new TagLookupCompositionStrategy(textKey);
-        } else if (textKW.val.equals("auto"))
+        /*
+         * If the cascade includes a TagKeyReference we will lookup the rendered label
+         * from a tag value.
+         */
+        TagKeyReference tkr = c.get("text", null, TagKeyReference.class, true);
+        if (tkr != null)
+            return new TagLookupCompositionStrategy(tkr.key);
+
+        /*
+         * Check whether the label composition strategy is given by
+         * a keyword
+         */
+        Keyword keyword = c.get("text", null, Keyword.class, true);
+        if (equal(keyword, Keyword.AUTO))
             return AUTO_LABEL_COMPOSITION_STRATEGY;
-        else
-            return new TagLookupCompositionStrategy(textKW.val);
+
+        /*
+         * Do we have a static text label?
+         */
+        String text = c.get("text", null, String.class, true);
+        if (text != null)
+            return new StaticLabelCompositionStrategy(text);
+        return defaultAnnotate ? AUTO_LABEL_COMPOSITION_STRATEGY : null;
     }
 
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Expression.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Expression.java	(revision 4006)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Expression.java	(revision 4007)
@@ -16,10 +16,12 @@
 import org.openstreetmap.josm.actions.search.SearchCompiler.Match;
 import org.openstreetmap.josm.actions.search.SearchCompiler.ParseError;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.gui.mappaint.Cascade;
 import org.openstreetmap.josm.gui.mappaint.Environment;
+import org.openstreetmap.josm.tools.CheckParameterUtil;
 import org.openstreetmap.josm.tools.Utils;
 
 public interface Expression {
-
     public Object evaluate(Environment env);
 
@@ -27,6 +29,7 @@
         Object literal;
 
-        public LiteralExpression(Object lit) {
-            this.literal = lit;
+        public LiteralExpression(Object literal) {
+            CheckParameterUtil.ensureParameterNotNull(literal);
+            this.literal = literal;
         }
 
@@ -38,6 +41,4 @@
         @Override
         public String toString() {
-            if (literal == null)
-                return "Lit{<null>}";
             if (literal instanceof float[])
                 return Arrays.toString((float[]) literal);
@@ -47,4 +48,6 @@
 
     public static class FunctionExpression implements Expression {
+        //static Logger logger = Logger.getLogger(FunctionExpression.class.getName());
+
         String name;
         List<Expression> args;
@@ -73,7 +76,6 @@
                 if (args.length == 0)
                     return 0f;
-                if (args.length == 1) { // unary minus
+                if (args.length == 1)
                     return -args[0];
-                }
                 float res = args[0];
                 for (int i=1; i<args.length; ++i) {
@@ -160,6 +162,15 @@
             }
 
-            public String get_tag_value(String key) {
+            public String tag(String key) {
                 return env.osm.get(key);
+            }
+
+            // FIXME: respect parent selector chain
+            public String parent_tag(String key) {
+                for (Relation parent: OsmPrimitive.getFilteredList(env.osm.getReferrers(), Relation.class)) {
+                    String value = parent.get(key);
+                    if (value != null) return value;
+                }
+                return null;
             }
 
@@ -286,6 +297,7 @@
             }
             for (Method m : allMethods) {
-                if (!m.getName().equals(name))
+                if (!m.getName().equals(name)) {
                     continue;
+                }
                 Class<?>[] expectedParameterTypes = m.getParameterTypes();
                 Object[] convertedArgs = new Object[expectedParameterTypes.length];
@@ -304,6 +316,7 @@
                     convertedArgs[0] = arrayArg;
                 } else {
-                    if (args.size() != expectedParameterTypes.length)
+                    if (args.size() != expectedParameterTypes.length) {
                         continue;
+                    }
                     for (int i=0; i<args.size(); ++i) {
                         convertedArgs[i] = Cascade.convertTo(args.get(i).evaluate(env), expectedParameterTypes[i]);
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Instruction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Instruction.java	(revision 4006)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Instruction.java	(revision 4007)
@@ -4,5 +4,8 @@
 import java.util.Arrays;
 
+import org.openstreetmap.josm.gui.mappaint.Cascade;
 import org.openstreetmap.josm.gui.mappaint.Environment;
+import org.openstreetmap.josm.gui.mappaint.Keyword;
+import org.openstreetmap.josm.gui.mappaint.MapPaintStyles;
 import org.openstreetmap.josm.gui.mappaint.MapPaintStyles.IconReference;
 
@@ -12,5 +15,5 @@
 
     public static class RelativeFloat {
-        public float val;
+        public final float val;
 
         public RelativeFloat(float val) {
@@ -25,11 +28,36 @@
 
     public static class AssignmentInstruction extends Instruction {
-        String key;
-        Object val;
+        //static private final Logger logger = Logger.getLogger(AssignmentInstruction.class.getName());
+        public final String key;
+        public final Object val;
 
         public AssignmentInstruction(String key, Object val) {
             this.key = key;
             if (val instanceof Expression.LiteralExpression) {
-                this.val = ((Expression.LiteralExpression) val).evaluate(null);
+                Object litValue = ((Expression.LiteralExpression) val).evaluate(null);
+                if (key.equals("text")) {
+                    /* Special case for declaration 'text: ...'
+                     * 
+                     * - Treat the value 'auto' as keyword.
+                     * - Treat any other literal value 'litval' as as reference to tag with key 'litval'
+                     * 
+                     * - Accept function expressions as is. This allows for
+                     *     tag(a_tag_name)                 value of a tag
+                     *     eval("a static text")           a static text
+                     *     parent_tag(a_tag_name)          value of a tag of a parent relation
+                     */
+                    if (litValue.equals(Keyword.AUTO)) {
+                        this.val = Keyword.AUTO;
+                    } else {
+                        String s = Cascade.convertTo(litValue, String.class);
+                        if (s != null) {
+                            this.val = new MapPaintStyles.TagKeyReference(s);
+                        } else {
+                            this.val = litValue;
+                        }
+                    }
+                } else {
+                    this.val = litValue;
+                }
             } else {
                 this.val = val;
@@ -39,5 +67,10 @@
         @Override
         public void execute(Environment env) {
-            Object value = (val instanceof Expression) ? ((Expression) val).evaluate(env) : val;
+            Object value = null;
+            if (val instanceof Expression) {
+                value = ((Expression) val).evaluate(env);
+            } else {
+                value = val;
+            }
             if (key.equals("icon-image") || key.equals("fill-image") || key.equals("pattern-image")) {
                 if (value instanceof String) {
