diff --git a/src/org/openstreetmap/josm/actions/search/PushbackTokenizer.java b/src/org/openstreetmap/josm/actions/search/PushbackTokenizer.java
index aedd0fd..9063a32 100644
--- a/src/org/openstreetmap/josm/actions/search/PushbackTokenizer.java
+++ b/src/org/openstreetmap/josm/actions/search/PushbackTokenizer.java
@@ -39,6 +39,7 @@ public class PushbackTokenizer {
     private Long currentNumber;
     private Long currentRange;
     private int c;
+    private boolean isRange;
 
     public PushbackTokenizer(Reader search) {
         this.search = search;
@@ -156,21 +157,29 @@ public class PushbackTokenizer {
                 return Token.OR;
             if ("and".equalsIgnoreCase(currentText))
                 return nextToken();
+            // try parsing number
             try {
                 currentNumber = Long.parseLong(currentText);
             } catch (NumberFormatException e) {
                 currentNumber = null;
             }
+            // if text contains "-", try parsing a range
             int pos = currentText.indexOf('-', 1);
-            if (pos > 0) {
+            isRange = pos > 0;
+            if (isRange) {
                 try {
                     currentNumber = Long.parseLong(currentText.substring(0, pos));
-                    currentRange = Long.parseLong(currentText.substring(pos + 1));
                 } catch (NumberFormatException e) {
                     currentNumber = null;
+                }
+                try {
+                    currentRange = Long.parseLong(currentText.substring(pos + 1));
+                } catch (NumberFormatException e) {
+                    currentRange = null;
+                    }
+                } else {
                     currentRange = null;
                 }
-            }
             return Token.KEY;
         }
     }
@@ -203,13 +212,21 @@ public class PushbackTokenizer {
     }
 
     public Range readRange(String errorMessage) throws ParseError {
-        if ((nextToken() == Token.KEY) && (currentNumber != null)) {
-            if (currentRange == null)
+        if (nextToken() != Token.KEY || (currentNumber == null && currentRange == null)) {
+            throw new ParseError(errorMessage);
+        } else if (!isRange && currentNumber != null) {
+            if (currentNumber >= 0) {
                 return new Range(currentNumber, currentNumber);
-            else
-                return new Range(currentNumber, currentRange);
-        } else
+            } else {
+                return new Range(0, Math.abs(currentNumber));
+            }
+        } else if (isRange && currentRange == null) {
+            return new Range(currentNumber, Integer.MAX_VALUE);
+        } else if (currentNumber != null && currentRange != null) {
+            return new Range(currentNumber, currentRange);
+        } else {
             throw new ParseError(errorMessage);
+        }
     }
 
     public String getText() {
diff --git a/src/org/openstreetmap/josm/actions/search/SearchAction.java b/src/org/openstreetmap/josm/actions/search/SearchAction.java
index 4d7938f..2257951 100644
--- a/src/org/openstreetmap/josm/actions/search/SearchAction.java
+++ b/src/org/openstreetmap/josm/actions/search/SearchAction.java
@@ -194,11 +194,11 @@ public class SearchAction extends JosmAction implements ParameterizedAction {
                     + "<li>"+tr("<b>id:</b>... - object with given ID (0 for new objects)")+"</li>"
                     + "<li>"+tr("<b>version:</b>... - object with given version (0 objects without an assigned version)")+"</li>"
                     + "<li>"+tr("<b>changeset:</b>... - object with given changeset id (0 objects without assigned changeset)")+"</li>"
-                    + "<li>"+tr("<b>nodes:</b>... - object with given number of nodes (nodes:count or nodes:min-max)")+"</li>"
-                    + "<li>"+tr("<b>tags:</b>... - object with given number of tags (tags:count or tags:min-max)")+"</li>"
+                    + "<li>"+tr("<b>nodes:</b>... - object with given number of nodes (nodes:count, nodes:min-max, nodes:min- or nodes:-max)")+"</li>"
+                    + "<li>"+tr("<b>tags:</b>... - object with given number of tags (nodes:count, nodes:min-max, nodes:min- or nodes:-max)")+"</li>"
                     + "<li>"+tr("<b>role:</b>... - object with given role in a relation")+"</li>"
                     + "<li>"+tr("<b>timestamp:</b>... -  objects with this timestamp (<b>2009-11-12T14:51:09Z</b>, <b>2009-11-12</b> or <b>T14:51</b> ...)")+"</li>"
-                    + "<li>"+tr("<b>areasize:</b>... - closed ways with area between MIN and MAX m\u00b2. (areasize:MIN-MAX or areasize:MAX)")+"</li>"
+                    + "<li>"+tr("<b>areasize:</b>... - closed ways with given area in m\u00b2 (areasize:min-max or areasize:max)")+"</li>"
                     + "<li>"+tr("<b>modified</b> - all changed objects")+"</li>"
                     + "<li>"+tr("<b>selected</b> - all selected objects")+"</li>"
                     + "<li>"+tr("<b>incomplete</b> - all incomplete objects")+"</li>"
diff --git a/src/org/openstreetmap/josm/actions/search/SearchCompiler.java b/src/org/openstreetmap/josm/actions/search/SearchCompiler.java
index 8300913..b34d0c1 100644
--- a/src/org/openstreetmap/josm/actions/search/SearchCompiler.java
+++ b/src/org/openstreetmap/josm/actions/search/SearchCompiler.java
@@ -508,43 +508,74 @@ public class SearchCompiler {
         }
     }
 
-    private static class NodeCountRange extends Match {
+    private abstract static class CountRange extends Match {
+
         private int minCount;
         private int maxCount;
-        public NodeCountRange(int minCount, int maxCount) {
-            if(maxCount < minCount) {
-                this.minCount = maxCount;
-                this.maxCount = minCount;
+
+        public CountRange(int minCount, int maxCount) {
+            this.minCount = Math.min(minCount, maxCount);
+            this.maxCount = Math.max(minCount, maxCount);
+        }
+
+        protected abstract Integer getCount(OsmPrimitive osm);
+
+        protected abstract String getCountString();
+
+        @Override
+        public boolean match(OsmPrimitive osm) {
+            Integer count = getCount(osm);
+            if (count == null) {
+                return false;
             } else {
-                this.minCount = minCount;
-                this.maxCount = maxCount;
+                return (count >= minCount) && (count <= maxCount);
             }
         }
-        @Override public boolean match(OsmPrimitive osm) {
-            if(!(osm instanceof Way)) return false;
-            int size = ((Way)osm).getNodesCount();
-            return (size >= minCount) && (size <= maxCount);
+
+        @Override
+        public String toString() {
+            return getCountString() + "=" + minCount + "-" + maxCount;
         }
-        @Override public String toString() {return "nodes="+minCount+"-"+maxCount;}
     }
 
-    private static class TagCountRange extends Match {
-        private int minCount;
-        private int maxCount;
-        public TagCountRange(int minCount, int maxCount) {
-            if(maxCount < minCount) {
-                this.minCount = maxCount;
-                this.maxCount = minCount;
+
+
+    private static class NodeCountRange extends CountRange {
+
+        public NodeCountRange(int minCount, int maxCount) {
+            super(minCount, maxCount);
+        }
+
+        @Override
+        protected Integer getCount(OsmPrimitive osm) {
+            if (!(osm instanceof Way)) {
+                return null;
             } else {
-                this.minCount = minCount;
-                this.maxCount = maxCount;
+                return ((Way) osm).getNodesCount();
             }
         }
-        @Override public boolean match(OsmPrimitive osm) {
-            int size = osm.getKeys().size();
-            return (size >= minCount) && (size <= maxCount);
+
+        @Override
+        protected String getCountString() {
+            return "nodes";
+        }
+    }
+
+    private static class TagCountRange extends CountRange {
+
+        public TagCountRange(int minCount, int maxCount) {
+            super(minCount, maxCount);
+        }
+
+        @Override
+        protected Integer getCount(OsmPrimitive osm) {
+            return osm.getKeys().size();
+        }
+
+        @Override
+        protected String getCountString() {
+            return "tags";
         }
-        @Override public String toString() {return "tags="+minCount+"-"+maxCount;}
     }
 
     private static class Modified extends Match {
@@ -636,24 +667,24 @@ public class SearchCompiler {
      * 
      * @author Ole Jørgen Brønner
      */
-    private static class Area extends Match {
-        private int min, max;
-
-        public Area(int min, int max) {
-            this.min = min;
-            this.max = max;
-            if (min == max) {
-                this.min = 0;
+    private static class Area extends CountRange {
+
+        public Area(int minCount, int maxCount) {
+            super(minCount, maxCount);
+        }
+
+        @Override
+        protected Integer getCount(OsmPrimitive osm) {
+            if (!(osm instanceof Way && ((Way) osm).isClosed())) {
+                return null;
             }
+            Way way = (Way) osm;
+            return (int) Geometry.closedWayArea(way);
         }
 
         @Override
-        public boolean match(OsmPrimitive osm) {
-            if(!(osm instanceof Way && ((Way) osm).isClosed()))
-                return false;
-            Way way = (Way)osm;
-            double area = Geometry.closedWayArea(way);
-            return (min <= area && area <= max);
+        protected String getCountString() {
+            return "area";
         }
     }
 
