Index: src/org/openstreetmap/josm/gui/mappaint/LabelCompositionStrategy.java
===================================================================
--- src/org/openstreetmap/josm/gui/mappaint/LabelCompositionStrategy.java	(revision 4002)
+++ src/org/openstreetmap/josm/gui/mappaint/LabelCompositionStrategy.java	(working copy)
@@ -47,6 +47,7 @@
 
     static public class StaticLabelCompositionStrategy extends LabelCompositionStrategy {
         private String defaultLabel;
+
         public StaticLabelCompositionStrategy(String defaultLabel){
             this.defaultLabel = defaultLabel;
         }
Index: src/org/openstreetmap/josm/gui/mappaint/MapPaintStyles.java
===================================================================
--- src/org/openstreetmap/josm/gui/mappaint/MapPaintStyles.java	(revision 4002)
+++ src/org/openstreetmap/josm/gui/mappaint/MapPaintStyles.java	(working copy)
@@ -20,8 +20,8 @@
 import org.openstreetmap.josm.gui.PleaseWaitRunnable;
 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;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -41,7 +41,52 @@
     {
         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 String key;
+        public TagKeyReference(String key){
+            this.key = key;
+        }
+
+        @Override
+        public String toString() {
+            return "TagKeyReference{" + "key='" + key + "'}";
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + ((key == null) ? 0 : key.hashCode());
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj)
+                return true;
+            if (obj == null)
+                return false;
+            if (getClass() != obj.getClass())
+                return false;
+            TagKeyReference other = (TagKeyReference) obj;
+            if (key == null) {
+                if (other.key != null)
+                    return false;
+            } else if (!key.equals(other.key))
+                return false;
+            return true;
+        }
+    }
+
     public static class IconReference {
 
         public String iconName;
@@ -111,7 +156,7 @@
             dirs.add("resource://images/styles/standard/");
             dirs.add("resource://images/styles/");
         }
-        
+
         return dirs;
     }
 
@@ -129,7 +174,7 @@
         for (StyleSource source : styles.getStyleSources()) {
             source.loadStyleSource();
         }
-        
+
         fireMapPaintSylesUpdated();
     }
 
@@ -138,34 +183,31 @@
         try {
             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) {
                     int c = reader.read();
                     switch (c) {
-                        case -1:
-                            break WHILE;
-                        case ' ':
-                        case '\t':
-                        case '\n':
-                        case '\r':
-                            continue;
-                        case '<':
-                            return new XmlStyleSource(entry);
-                        default:
-                            return new MapCSSStyleSource(entry);
+                    case -1:
+                        break WHILE;
+                    case ' ':
+                    case '\t':
+                    case '\n':
+                    case '\r':
+                        continue;
+                    case '<':
+                        return new XmlStyleSource(entry);
+                    default:
+                        return new MapCSSStyleSource(entry);
                     }
                 }
                 System.err.println("Warning: Could not detect style type. Using default (xml).");
@@ -271,13 +313,13 @@
         int[] selSorted = Arrays.copyOf(sel, sel.length);
         Arrays.sort(selSorted);
 
-        if (i < 0) { // Up
+        if (i < 0)
             return selSorted[0] >= -i;
-        } else
-        if (i > 0) { // Down
-            return selSorted[selSorted.length-1] <= styles.getStyleSources().size() - 1 - i;
-        } else
-            return true;
+            else
+                if (i > 0)
+                    return selSorted[selSorted.length-1] <= styles.getStyleSources().size() - 1 - i;
+                else
+                    return true;
     }
 
     public static void toggleStyleActive(int... sel) {
@@ -319,7 +361,7 @@
     }
 
     protected static final CopyOnWriteArrayList<MapPaintSylesUpdateListener> listeners
-            = new CopyOnWriteArrayList<MapPaintSylesUpdateListener>();
+    = new CopyOnWriteArrayList<MapPaintSylesUpdateListener>();
 
     public static void addMapPaintSylesUpdateListener(MapPaintSylesUpdateListener listener) {
         if (listener != null) {
Index: src/org/openstreetmap/josm/gui/mappaint/TextElement.java
===================================================================
--- src/org/openstreetmap/josm/gui/mappaint/TextElement.java	(revision 4002)
+++ src/org/openstreetmap/josm/gui/mappaint/TextElement.java	(working copy)
@@ -8,7 +8,9 @@
 
 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;
 
@@ -80,16 +82,32 @@
      * @return the label composition strategy
      */
     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"))
-            return AUTO_LABEL_COMPOSITION_STRATEGY;
-        else
-            return new TagLookupCompositionStrategy(textKW.val);
+        /*
+         * 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 (keyword != null){
+            if (keyword.equals(Keyword.AUTO))
+                return AUTO_LABEL_COMPOSITION_STRATEGY;
+            return null; // unsupported keyword
+        }
+
+        /*
+         * 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;
     }
 
     /**
@@ -183,11 +201,11 @@
             return false;
         final TextElement other = (TextElement) obj;
         return  equal(labelCompositionStrategy, other.labelCompositionStrategy) &&
-                equal(font, other.font) &&
-                xOffset == other.xOffset &&
-                yOffset == other.yOffset &&
-                equal(color, other.color) &&
-                equal(haloRadius, other.haloRadius) &&
-                equal(haloColor, other.haloColor);
+        equal(font, other.font) &&
+        xOffset == other.xOffset &&
+        yOffset == other.yOffset &&
+        equal(color, other.color) &&
+        equal(haloRadius, other.haloRadius) &&
+        equal(haloColor, other.haloColor);
     }
 }
Index: src/org/openstreetmap/josm/gui/mappaint/mapcss/Expression.java
===================================================================
--- src/org/openstreetmap/josm/gui/mappaint/mapcss/Expression.java	(revision 4002)
+++ src/org/openstreetmap/josm/gui/mappaint/mapcss/Expression.java	(working copy)
@@ -15,12 +15,13 @@
 import org.openstreetmap.josm.actions.search.SearchCompiler;
 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.Utils;
 
 public interface Expression {
-
     public Object evaluate(Environment env);
 
     public static class LiteralExpression implements Expression {
@@ -46,6 +47,8 @@
     }
 
     public static class FunctionExpression implements Expression {
+        //static Logger logger = Logger.getLogger(FunctionExpression.class.getName());
+
         String name;
         List<Expression> args;
 
@@ -72,9 +75,8 @@
             public Float minus(float... args) {
                 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) {
                     res -= args[i];
@@ -163,6 +165,29 @@
                 return env.osm.get(key);
             }
 
+            public String tag(String key) {
+                return get_tag_value(key);
+            }
+
+            public String text(String value){
+                return value;
+            }
+
+            /**
+             * <p>Replies the value of a tag with name <tt>key</tt> provided by one of the parent
+             * relations of the OSM object in the environment, or null, if no such tag exists.</p>
+             * 
+             * @param key the tag key
+             * @return the tag value
+             */
+            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;
+            }
+
             public boolean has_tag_key(String key) {
                 return env.osm.hasKey(key);
             }
@@ -285,8 +310,9 @@
                 throw  new RuntimeException(ex);
             }
             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];
 
@@ -303,8 +329,9 @@
                     }
                     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]);
                         if (convertedArgs[i] == null)
Index: src/org/openstreetmap/josm/gui/mappaint/mapcss/Instruction.java
===================================================================
--- src/org/openstreetmap/josm/gui/mappaint/mapcss/Instruction.java	(revision 4002)
+++ src/org/openstreetmap/josm/gui/mappaint/mapcss/Instruction.java	(working copy)
@@ -4,6 +4,8 @@
 import java.util.Arrays;
 
 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;
 
 abstract public class Instruction {
@@ -24,13 +26,35 @@
     }
 
     public static class AssignmentInstruction extends Instruction {
+        //static private final Logger logger = Logger.getLogger(AssignmentInstruction.class.getName());
         String key;
         Object val;
 
         public AssignmentInstruction(String key, Object val) {
             this.key = key;
             if (val instanceof Expression.LiteralExpression) {
-                this.val = ((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
+                     *     text("a static text")           a static text
+                     *     parent_tag(a_tag_name)          value of a tag of a parent relation
+                     */
+                    Object value = ((Expression.LiteralExpression) val).evaluate(null);
+                    if (value != null){
+                        if (value.equals(Keyword.AUTO)) {
+                            this.val = Keyword.AUTO;
+                        } else {
+                            this.val = new MapPaintStyles.TagKeyReference(value.toString());
+                        }
+                    }
+                } else {
+                    this.val = ((Expression.LiteralExpression) val).evaluate(null);
+                }
             } else {
                 this.val = val;
             }
@@ -38,7 +62,12 @@
 
         @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")) {
                 if (value instanceof String) {
                     value = new IconReference((String) value, env.source);
