diff --git a/HOCON.md b/HOCON.md
index dfe46799..e85f1b4b 100644
--- a/HOCON.md
+++ b/HOCON.md
@@ -441,6 +441,7 @@ number-to-string library function).
    be a two-element path with `foo10` and `0` as the elements.
  - `foo"10.0"` is an unquoted then a quoted string which are
    concatenated, so this is a single-element path.
+ - `1.2.3` is the three-element path with `1`,`2`,`3`
 
 Unlike value concatenations, path expressions are _always_
 converted to a string, even if they are just a single value.
diff --git a/config/src/main/java/com/typesafe/config/impl/Tokenizer.java b/config/src/main/java/com/typesafe/config/impl/Tokenizer.java
index 4332aa7b..0da23070 100644
--- a/config/src/main/java/com/typesafe/config/impl/Tokenizer.java
+++ b/config/src/main/java/com/typesafe/config/impl/Tokenizer.java
@@ -355,7 +355,15 @@ final class Tokenizer {
                     return Tokens.newLong(lineOrigin, Long.parseLong(s), s);
                 }
             } catch (NumberFormatException e) {
-                throw problem(s, "Invalid number: '" + s + "'", true /* suggestQuotes */, e);
+                // not a number after all, see if it's an unquoted string.
+                for (char u : s.toCharArray()) {
+                    if (notInUnquotedText.indexOf(u) >= 0)
+                        throw problem(asString(u), "Reserved character '" + asString(u)
+                                      + "' is not allowed outside quotes", true /* suggestQuotes */);
+                }
+                // no evil chars so we just decide this was a string and
+                // not a number.
+                return Tokens.newUnquotedText(lineOrigin, s);
             }
         }
 
diff --git a/config/src/test/scala/com/typesafe/config/impl/ConfParserTest.scala b/config/src/test/scala/com/typesafe/config/impl/ConfParserTest.scala
index c865c651..566d50a7 100644
--- a/config/src/test/scala/com/typesafe/config/impl/ConfParserTest.scala
+++ b/config/src/test/scala/com/typesafe/config/impl/ConfParserTest.scala
@@ -124,6 +124,7 @@ class ConfParserTest extends TestUtils {
         assertEquals(path("a  b"), parsePath(" a  b"))
         assertEquals(path("a", "b.c", "d"), parsePath("a.\"b.c\".d"))
         assertEquals(path("3", "14"), parsePath("3.14"))
+        assertEquals(path("3", "14", "159"), parsePath("3.14.159"))
         assertEquals(path("a3", "14"), parsePath("a3.14"))
         assertEquals(path(""), parsePath("\"\""))
         assertEquals(path("a", "", "b"), parsePath("a.\"\".b"))
@@ -133,6 +134,9 @@ class ConfParserTest extends TestUtils {
         assertEquals(path("a-c"), parsePath("a-c"))
         assertEquals(path("a_c"), parsePath("a_c"))
         assertEquals(path("-"), parsePath("\"-\""))
+        assertEquals(path("-"), parsePath("-"))
+        assertEquals(path("-foo"), parsePath("-foo"))
+        assertEquals(path("-10"), parsePath("-10"))
 
         // here 10.0 is part of an unquoted string
         assertEquals(path("foo10", "0"), parsePath("foo10.0"))
@@ -140,6 +144,8 @@ class ConfParserTest extends TestUtils {
         assertEquals(path("10", "0foo"), parsePath("10.0foo"))
         // just a number
         assertEquals(path("10", "0"), parsePath("10.0"))
+        // multiple-decimal number
+        assertEquals(path("1", "2", "3", "4"), parsePath("1.2.3.4"))
 
         for (invalid <- Seq("", " ", "  \n   \n  ", "a.", ".b", "a..b", "a${b}c", "\"\".", ".\"\"")) {
             try {
@@ -152,11 +158,6 @@ class ConfParserTest extends TestUtils {
                     throw e;
             }
         }
-
-        intercept[ConfigException.Parse] {
-            // this gets parsed as a number since it starts with '-'
-            parsePath("-")
-        }
     }
 
     @Test
@@ -339,11 +340,6 @@ class ConfParserTest extends TestUtils {
         lineNumberTest(2, "\n\"foo\"")
         lineNumberTest(3, "\n\n\"foo\"")
 
-        // newline in middle of number uses the line the number was on
-        lineNumberTest(1, "1e\n")
-        lineNumberTest(2, "\n1e\n")
-        lineNumberTest(3, "\n\n1e\n")
-
         // newlines in triple-quoted string should not hose up the numbering
         lineNumberTest(1, "a : \"\"\"foo\"\"\"}")
         lineNumberTest(2, "a : \"\"\"foo\n\"\"\"}")
@@ -813,4 +809,14 @@ class ConfParserTest extends TestUtils {
         val conf = ConfigFactory.parseString("foo= \uFEFFbar\uFEFF")
         assertEquals("bar", conf.getString("foo"))
     }
+
+    @Test
+    def acceptMultiPeriodNumericPath() {
+        val conf1 = ConfigFactory.parseString("0.1.2.3=foobar1")
+        assertEquals("foobar1", conf1.getString("0.1.2.3"))
+        val conf2 = ConfigFactory.parseString("0.1.2.3.ABC=foobar2")
+        assertEquals("foobar2", conf2.getString("0.1.2.3.ABC"))
+        val conf3 = ConfigFactory.parseString("ABC.0.1.2.3=foobar3")
+        assertEquals("foobar3", conf3.getString("ABC.0.1.2.3"))
+    }
 }
diff --git a/config/src/test/scala/com/typesafe/config/impl/PathTest.scala b/config/src/test/scala/com/typesafe/config/impl/PathTest.scala
index b8a28aea..ccf05a94 100644
--- a/config/src/test/scala/com/typesafe/config/impl/PathTest.scala
+++ b/config/src/test/scala/com/typesafe/config/impl/PathTest.scala
@@ -67,6 +67,9 @@ class PathTest extends TestUtils {
             RenderTest("\" foo \"", path(" foo ")),
             // trailing space only
             RenderTest("\"foo \"", path("foo ")))
+            // numbers with decimal points
+            RenderTest("1.2", path("1", "2"))
+            RenderTest("1.2.3.4", path("1", "2", "3", "4"))
 
         for (t <- tests) {
             assertEquals(t.expected, t.path.render())
diff --git a/config/src/test/scala/com/typesafe/config/impl/TestUtils.scala b/config/src/test/scala/com/typesafe/config/impl/TestUtils.scala
index 440851df..eea01ba8 100644
--- a/config/src/test/scala/com/typesafe/config/impl/TestUtils.scala
+++ b/config/src/test/scala/com/typesafe/config/impl/TestUtils.scala
@@ -342,8 +342,6 @@ abstract trait TestUtils {
         // these two problems are ignored by the lift tokenizer
         "[:\"foo\", \"bar\"]", // colon in an array; lift doesn't throw (tokenizer erases it)
         "[\"foo\" : \"bar\"]", // colon in an array another way, lift ignores (tokenizer erases it)
-        "[ 10e3e3 ]", // two exponents. ideally this might parse to a number plus string "e3" but it's hard to implement.
-        "[ 1-e3 ]", // malformed number but all chars can appear in a number
         "[ \"hello ]", // unterminated string
         ParseTest(true, "{ \"foo\" , true }"), // comma instead of colon, lift is fine with this
         ParseTest(true, "{ \"foo\" : true \"bar\" : false }"), // missing comma between fields, lift fine with this
@@ -380,6 +378,7 @@ abstract trait TestUtils {
         "[ += ]",
         "+= 10",
         "10 +=",
+        "[ 10e+3e ]", // "+" not allowed in unquoted strings, and not a valid number
         ParseTest(true, "[ \"foo\nbar\" ]"), // unescaped newline in quoted string, lift doesn't care
         "[ # comment ]",
         "${ #comment }",
@@ -412,7 +411,8 @@ abstract trait TestUtils {
         "[ \"//comment\" ]", // quoted // comment
         // this long one is mostly to test rendering
         """{ "foo" : { "bar" : "baz", "woo" : "w00t" }, "baz" : { "bar" : "baz", "woo" : [1,2,3,4], "w00t" : true, "a" : false, "b" : 3.14, "c" : null } }""",
-        "{}")
+        "{}",
+        ParseTest(true, "[ 10e+3 ]")) // "+" in a number (lift doesn't handle)
 
     private val validConfInvalidJson = List[ParseTest]("", // empty document
         " ", // empty document single space
@@ -504,7 +504,11 @@ abstract trait TestUtils {
         "a = [], a += b", // += operator with previous init
         "{ a = [], a += 10 }", // += in braces object with previous init
         "a += b", // += operator without previous init
-        "{ a += 10 }") // += in braces object without previous init
+        "{ a += 10 }", // += in braces object without previous init
+        "[ 10e3e3 ]", // two exponents. this should parse to a number plus string "e3"
+        "[ 1-e3 ]", // malformed number should end up as a string instead
+        "[ 1.0.0 ]", // two decimals, should end up as a string
+        "[ 1.0. ]")  // trailing decimal should end up as a string
 
     protected val invalidJson = validConfInvalidJson ++ invalidJsonInvalidConf;