Support punctuation after quotes

Change-Id: I33522a817f1e34f732d4d7131412e6d0e28e90a6
diff --git a/Changes b/Changes
index 46660ec..9612c12 100644
--- a/Changes
+++ b/Changes
@@ -1,5 +1,7 @@
-0.1.4 2022-03-11
+0.1.4 2022-03-27
     - Improved handling of ellipsis.
+    - Make algorithm more robust to nevere fail.
+    - Remove match option.
 
 0.1.3 2022-03-08
     - Introduced refined handling of sentences including speech.
diff --git a/datok_test.go b/datok_test.go
index 86dd428..9558661 100644
--- a/datok_test.go
+++ b/datok_test.go
@@ -932,11 +932,12 @@
 	w.Reset()
 	assert.True(dat.Transduce(strings.NewReader(text), w))
 	sentences = strings.Split(w.String(), "\n\n")
-	assert.Equal(len(sentences), 5)
+	assert.Equal(len(sentences), 6)
 	assert.Equal("Wüllersdorf\nwar\naufgestanden\n.", sentences[0])
 	assert.Equal("»\nIch\nfinde\nes\nfurchtbar\n,\ndaß\nSie\nrecht\nhaben\n,\naber\nSie\nhaben\nrecht\n.", sentences[1])
-	assert.Equal("Ich\nquäle\nSie\nnicht\nlänger\nmit\nmeinem\n'\nMuß\nes\nsein\n?\n'\n.\n \nDie\nWelt\nist\neinmal\n,\nwie\nsie\nist\n,\nund\ndie\nDinge\nverlaufen\nnicht\n,\nwie\nwir\nwollen\n,\nsondern\nwie\ndie\nandern\nwollen\n.", sentences[2])
-	assert.Equal("Das\nmit\ndem\n'\nGottesgericht\n'\n,\nwie\nmanche\nhochtrabend\nversichern\n,\nist\nfreilich\nein\nUnsinn\n,\nnichts\ndavon\n,\numgekehrt\n,\nunser\nEhrenkultus\nist\nein\nGötzendienst\n,\naber\nwir\nmüssen\nuns\nihm\nunterwerfen\n,\nsolange\nder\nGötze\ngilt\n.\n«", sentences[3])
+	assert.Equal("Ich\nquäle\nSie\nnicht\nlänger\nmit\nmeinem\n'\nMuß\nes\nsein\n?\n'\n.", sentences[2])
+	assert.Equal("Die\nWelt\nist\neinmal\n,\nwie\nsie\nist\n,\nund\ndie\nDinge\nverlaufen\nnicht\n,\nwie\nwir\nwollen\n,\nsondern\nwie\ndie\nandern\nwollen\n.", sentences[3])
+	assert.Equal("Das\nmit\ndem\n'\nGottesgericht\n'\n,\nwie\nmanche\nhochtrabend\nversichern\n,\nist\nfreilich\nein\nUnsinn\n,\nnichts\ndavon\n,\numgekehrt\n,\nunser\nEhrenkultus\nist\nein\nGötzendienst\n,\naber\nwir\nmüssen\nuns\nihm\nunterwerfen\n,\nsolange\nder\nGötze\ngilt\n.\n«", sentences[4])
 }
 
 func TestDoubleArrayLoadFactor1(t *testing.T) {
diff --git a/matrix_test.go b/matrix_test.go
index 1e5bdd1..2571978 100644
--- a/matrix_test.go
+++ b/matrix_test.go
@@ -394,11 +394,12 @@
 	w.Reset()
 	assert.True(mat.Transduce(strings.NewReader(text), w))
 	sentences = strings.Split(w.String(), "\n\n")
-	assert.Equal(len(sentences), 5)
+	assert.Equal(len(sentences), 6)
 	assert.Equal("Wüllersdorf\nwar\naufgestanden\n.", sentences[0])
 	assert.Equal("»\nIch\nfinde\nes\nfurchtbar\n,\ndaß\nSie\nrecht\nhaben\n,\naber\nSie\nhaben\nrecht\n.", sentences[1])
-	assert.Equal("Ich\nquäle\nSie\nnicht\nlänger\nmit\nmeinem\n'\nMuß\nes\nsein\n?\n'\n.\n \nDie\nWelt\nist\neinmal\n,\nwie\nsie\nist\n,\nund\ndie\nDinge\nverlaufen\nnicht\n,\nwie\nwir\nwollen\n,\nsondern\nwie\ndie\nandern\nwollen\n.", sentences[2])
-	assert.Equal("Das\nmit\ndem\n'\nGottesgericht\n'\n,\nwie\nmanche\nhochtrabend\nversichern\n,\nist\nfreilich\nein\nUnsinn\n,\nnichts\ndavon\n,\numgekehrt\n,\nunser\nEhrenkultus\nist\nein\nGötzendienst\n,\naber\nwir\nmüssen\nuns\nihm\nunterwerfen\n,\nsolange\nder\nGötze\ngilt\n.\n«", sentences[3])
+	assert.Equal("Ich\nquäle\nSie\nnicht\nlänger\nmit\nmeinem\n'\nMuß\nes\nsein\n?\n'\n.", sentences[2])
+	assert.Equal("Die\nWelt\nist\neinmal\n,\nwie\nsie\nist\n,\nund\ndie\nDinge\nverlaufen\nnicht\n,\nwie\nwir\nwollen\n,\nsondern\nwie\ndie\nandern\nwollen\n.", sentences[3])
+	assert.Equal("Das\nmit\ndem\n'\nGottesgericht\n'\n,\nwie\nmanche\nhochtrabend\nversichern\n,\nist\nfreilich\nein\nUnsinn\n,\nnichts\ndavon\n,\numgekehrt\n,\nunser\nEhrenkultus\nist\nein\nGötzendienst\n,\naber\nwir\nmüssen\nuns\nihm\nunterwerfen\n,\nsolange\nder\nGötze\ngilt\n.\n«", sentences[4])
 }
 
 func TestMatrixFullTokenizerTokenSplitter(t *testing.T) {
diff --git a/src/tokenizer.xfst b/src/tokenizer.xfst
index cf183b7..74f7c52 100644
--- a/src/tokenizer.xfst
+++ b/src/tokenizer.xfst
@@ -225,7 +225,7 @@
 define NotSmallCaps [? - a - b - c - d - e - f - g - h - i - j - k - l - m - n - o - p - q - r - s - t - u - v - w - x - y - z - ü - ö - ä];
 
 read regex Token .o. [
-  SP NLout [DQuotes | "›" (NLout DQuotes)| %‹ (NLout DQuotes)| %’ (NLout DQuotes)| "'" (NLout DQuotes)] @-> ... NLout \/ _ NLout \%,
+  SP NLout [DQuotes | "›" (NLout DQuotes) | %‹ (NLout DQuotes) | %’ (NLout DQuotes) | "'" (NLout DQuotes)] (NLout SP) @-> ... NLout \/ _ NLout \%,
 ] .o. [
   SP @-> ... NLout \/ NLout _ NLout [? - "”" - %" - "»" - "«" - "›" - %‹ - %’ - "'" - NLout]
 ] .o. [
diff --git a/testdata/tokenizer.datok b/testdata/tokenizer.datok
index df75e9b..9dddefa 100644
--- a/testdata/tokenizer.datok
+++ b/testdata/tokenizer.datok
Binary files differ
diff --git a/testdata/tokenizer.fst b/testdata/tokenizer.fst
index 5701081..def2160 100644
--- a/testdata/tokenizer.fst
+++ b/testdata/tokenizer.fst
Binary files differ
diff --git a/testdata/tokenizer.matok b/testdata/tokenizer.matok
index 75ce996..3591617 100644
--- a/testdata/tokenizer.matok
+++ b/testdata/tokenizer.matok
Binary files differ