Index: /applications/editors/josm/plugins/comfort0/src/net/simon04/comfort0/level0l/Level0LParser.jj
===================================================================
--- /applications/editors/josm/plugins/comfort0/src/net/simon04/comfort0/level0l/Level0LParser.jj	(revision 35290)
+++ /applications/editors/josm/plugins/comfort0/src/net/simon04/comfort0/level0l/Level0LParser.jj	(revision 35291)
@@ -1,5 +1,4 @@
 options {
   STATIC = false;
-  OUTPUT_DIRECTORY = "parsergen";
 }
 
@@ -15,16 +14,19 @@
 
 <DEFAULT> //HEADER
-SKIP: { " " }
-
-<DEFAULT> //HEADER
 TOKEN: {
-    <H_EOL: ("\n" | "\r" | "\r\n") > : DATA
-    | <H_ID: (["0"-"9"])+ >
+    <EOL: ("\n" | "\r" | "\r\n") >
+    | <ID: (["0"-"9"])+ >
     | <NODE: "node" >
     | <WAY: "way" >
     | <RELATION: "relation" >
+    | <WY: "wy" >
+    | <ND: "nd" >
+    | <REL: "rel" >
+    | <EQ: "=" > : VALUE
+    | <IDENT: ["a"-"z", "A"-"Z", "_"] (["a"-"z", "A"-"Z", "_", ":", "-", "0"-"9"])* >
     | <FLOAT: ("+" | "-")? (["0"-"9"])+ ("." (["0"-"9"])+)? >
     | <COLON: ":" >
     | <COMMA: "," >
+    | <WHITESPACE: ([" ", "\t"])+ >
     | <COMMENT_START: "#"> : COMMENT
 }
@@ -35,23 +37,10 @@
 <COMMENT>
 TOKEN: {
-    <C_EOL: ("\n" | "\r" | "\r\n") > : DATA
-}
-
-<DATA>
-TOKEN: {
-    <D_EOL: ("\n" | "\r" | "\r\n") >
-    | <D_SPACE: " " >
-    | <D_ID: (["0"-"9"])+ >
-    | <WY: "wy" >
-    | <ND: "nd" >
-    | <REL: "rel" >
-    | <EQ: "=" > : VALUE
-    | <IDENT: ["a"-"z", "A"-"Z", "_"] (["a"-"z", "A"-"Z", "_", "-", "0"-"9"])* >
-    | <D_COMMENT_START: "#"> : COMMENT
+    <C_EOL: ("\n" | "\r" | "\r\n") > : DEFAULT
 }
 
 <VALUE>
 TOKEN: {
-    <V_EOL: ("\n" | "\r" | "\r\n") > : DATA
+    <V_EOL: ("\n" | "\r" | "\r\n") > : DEFAULT
     | <TEXT: (~["\n", "\r"])+ >
 }
@@ -64,6 +53,14 @@
 {
     (
-        ( p = node() | p = way() | p = relation() )
+        p = node()
         { primitives.add(p); }
+    |
+        p = way()
+        { primitives.add(p); }
+    |
+        p = relation()
+        { primitives.add(p); }
+    |
+        <COMMENT_START> <C_EOL> | <EOL>
     )*
     <EOF>
@@ -79,13 +76,19 @@
     <NODE>
     { r = new NodeData(); }
-    id=<H_ID>
+    ( <WHITESPACE> )+
+    id=<ID>
     { r.setId(Long.parseLong(id.image)); }
+    ( <WHITESPACE> )*
     <COLON>
+    ( <WHITESPACE> )*
     lat=<FLOAT>
+    ( <WHITESPACE> )*
     <COMMA>
+    ( <WHITESPACE> )*
     lon=<FLOAT>
     { r.setCoor(new LatLon(Double.parseDouble(lat.image), Double.parseDouble(lon.image))); }
-    ( <COMMENT_START> <C_EOL> | <H_EOL> )
-    ( <D_SPACE> <D_SPACE> tag(r) )*
+    ( <WHITESPACE> )*
+    ( <COMMENT_START> <C_EOL> | <EOL> )
+    ( tag(r) )*
     { return r; }
 }
@@ -98,8 +101,10 @@
 {
     <WAY>
+    ( <WHITESPACE> )+
     { r = new WayData(); }
-    id=<H_ID>
+    id=<ID>
     { r.setId(Long.parseLong(id.image)); }
-    ( <COMMENT_START> <C_EOL> | <H_EOL> )
+    ( <WHITESPACE> )*
+    ( <COMMENT_START> <C_EOL> | <EOL> )
     way_data(r)
     { return r; }
@@ -113,8 +118,10 @@
 {
     <RELATION>
+    ( <WHITESPACE> )+
     { r = new RelationData(); }
-    id=<H_ID>
+    id=<ID>
     { r.setId(Long.parseLong(id.image)); }
-    ( <COMMENT_START> <C_EOL> | <H_EOL> )
+    ( <WHITESPACE> )*
+    ( <COMMENT_START> <C_EOL> | <EOL> )
     relation_data(r)
     { return r; }
@@ -124,8 +131,5 @@
 {}
 {
-    (
-        <D_SPACE> <D_SPACE>
-        ( way_node(r) | tag(r) )
-    )*
+    ( LOOKAHEAD(3) way_node(r) | tag(r) )*
 }
 
@@ -135,10 +139,11 @@
 }
 {
+    ( <WHITESPACE> )+
     <ND>
-    ( <D_SPACE> )+
-    id=<D_ID>
+    ( <WHITESPACE> )+
+    id=<ID>
     { r.getNodeIds().add(Long.parseLong(id.image)); }
-    ( <D_SPACE> )*
-    ( <D_COMMENT_START> <C_EOL> | <D_EOL> )
+    ( <WHITESPACE> )*
+    ( <COMMENT_START> <C_EOL> | <EOL> )
 }
 
@@ -146,8 +151,5 @@
 {}
 {
-    (
-        <D_SPACE> <D_SPACE>
-        ( relation_member(r) | tag(r) )
-    )*
+    ( LOOKAHEAD(3) relation_member(r) | tag(r) )*
 }
 
@@ -159,4 +161,5 @@
 }
 {
+    ( <WHITESPACE> )+
     (
         <ND> { type = OsmPrimitiveType.NODE; }
@@ -166,16 +169,14 @@
         <REL> { type = OsmPrimitiveType.RELATION; }
     )
-    <D_SPACE>
-    id=<D_ID>
+    ( <WHITESPACE> )+
+    id=<ID>
     (
-        <D_SPACE>
-        (
-            role=<IDENT> ( <D_SPACE> )*
-        |
-            ( <D_SPACE> )*
-        )
+        LOOKAHEAD(2)
+        ( <WHITESPACE> )+
+        role=<IDENT>
     )?
     { r.getMembers().add(new RelationMemberData(role != null ? role.image : "", type, Long.parseLong(id.image))); }
-    ( <D_COMMENT_START> <C_EOL> | <D_EOL> )
+    ( <WHITESPACE> )*
+    ( <COMMENT_START> <C_EOL> | <EOL> )
 }
 
@@ -185,7 +186,9 @@
 }
 {
+    ( <WHITESPACE> )+
     k=<IDENT>
-    ( <D_SPACE> ) *
+    ( <WHITESPACE> )*
     <EQ>
+    ( <WHITESPACE> )*
     v=<TEXT>
     <V_EOL>
Index: /applications/editors/josm/plugins/comfort0/test/unit/net/simon04/comfort0/level0l/parsergen/Level0LParserTest.java
===================================================================
--- /applications/editors/josm/plugins/comfort0/test/unit/net/simon04/comfort0/level0l/parsergen/Level0LParserTest.java	(revision 35290)
+++ /applications/editors/josm/plugins/comfort0/test/unit/net/simon04/comfort0/level0l/parsergen/Level0LParserTest.java	(revision 35291)
@@ -1,12 +1,15 @@
 package net.simon04.comfort0.level0l.parsergen;
 
+import static org.CustomMatchers.hasSize;
 import static org.hamcrest.CoreMatchers.is;
 import static org.junit.Assert.assertThat;
 
 import java.io.StringReader;
+import java.util.List;
 
 import org.junit.Test;
 import org.openstreetmap.josm.data.osm.NodeData;
 import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
+import org.openstreetmap.josm.data.osm.PrimitiveData;
 import org.openstreetmap.josm.data.osm.RelationData;
 import org.openstreetmap.josm.data.osm.WayData;
@@ -73,3 +76,44 @@
         assertThat(relation.getKeys().size(), is(6));
     }
+
+    @Test
+    public void testExampleFromDocs() throws Exception {
+        // https://wiki.openstreetmap.org/wiki/Level0L#Examples
+        final String level0l = "" +
+                "node 298884269: 54.0901746, 12.2482632 # made by user SvenHRO (46882) in changeset 676636 on 2008-09-21T21:37:45Z\n" +
+                "node 261728686: 54.0906309, 12.2441924 # versions should be stored server-side\n" +
+                "node 1831881213: 54.0900666, 12.2539381 # comments are not allowed in tag values, '=' is screened (\\=) only in keys\n" +
+                "  name = Neu Broderstorf\n" +
+                "  traffic_sign = city_limit\n" +
+                "\n" +
+                "node 298884272: 54.0901447, 12.2516513\n" +
+                "\n" +
+                "way 26659127\n" +
+                "  nd 292403538\n" +
+                "  nd 298884289\n" +
+                "  nd 261728686\n" +
+                "  highway = unclassified\n" +
+                "  name = Pastower Straße\n" +
+                "\n" +
+                "relation 56688 # member types: nd, wy, rel; roles are put after ids\n" +
+                "  nd 294942404\n" +
+                "  nd 364933006\n" +
+                "  wy 4579143 forward\n" +
+                "  nd 249673494\n" +
+                "  name = Küstenbus Linie 123\n" +
+                "  network = VVW\n" +
+                "  operator = Regionalverkehr Küste\n" +
+                "  ref = 123\n" +
+                "  route = bus\n" +
+                "  type = route\n";
+        final List<PrimitiveData> primitives = new Level0LParser(new StringReader(level0l)).primitives();
+        assertThat(primitives, hasSize(6));
+        assertThat(primitives.get(0).toString(), is("298884269 null V NODE LatLon[lat=54.0901746,lon=12.2482632]"));
+        assertThat(primitives.get(1).toString(), is("261728686 null V NODE LatLon[lat=54.0906309,lon=12.2441924]"));
+        assertThat(primitives.get(2).toString(), is("1831881213 [name, Neu Broderstorf, traffic_sign, city_limit] V NODE LatLon[lat=54.0900666,lon=12.2539381]"));
+        assertThat(primitives.get(3).toString(), is("298884272 null V NODE LatLon[lat=54.0901447,lon=12.2516513]"));
+        assertThat(primitives.get(4).toString(), is("26659127 [highway, unclassified, name, Pastower Straße] V WAY[292403538, 298884289, 261728686]"));
+        assertThat(primitives.get(5).toString(), is("56688 [name, Küstenbus Linie 123, network, VVW, operator, Regionalverkehr Küste, ref, 123, route, bus, type, route] V REL [node 294942404, node 364933006, way 4579143, node 249673494]"));
+    }
+
 }
