mittens 0.3.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/Gemfile +1 -0
  4. data/README.md +2 -2
  5. data/Rakefile +10 -3
  6. data/lib/mittens/version.rb +1 -1
  7. data/vendor/snowball/.github/workflows/ci.yml +144 -17
  8. data/vendor/snowball/.github/workflows/coverage.yml +117 -0
  9. data/vendor/snowball/.github/workflows/runtime-tests.yml +26 -0
  10. data/vendor/snowball/.gitignore +33 -7
  11. data/vendor/snowball/CONTRIBUTING.rst +7 -0
  12. data/vendor/snowball/COPYING +1 -1
  13. data/vendor/snowball/GNUmakefile +736 -298
  14. data/vendor/snowball/NEWS +1394 -7
  15. data/vendor/snowball/README.rst +8 -8
  16. data/vendor/snowball/ada/generate/generate.adb +5 -5
  17. data/vendor/snowball/ada/src/stemmer.adb +177 -188
  18. data/vendor/snowball/ada/src/stemmer.ads +86 -89
  19. data/vendor/snowball/ada/src/stemwords.adb +21 -5
  20. data/vendor/snowball/algorithms/czech.sbl +255 -0
  21. data/vendor/snowball/algorithms/danish.sbl +22 -10
  22. data/vendor/snowball/algorithms/english.sbl +7 -4
  23. data/vendor/snowball/algorithms/esperanto.sbl +6 -7
  24. data/vendor/snowball/algorithms/estonian.sbl +9 -4
  25. data/vendor/snowball/algorithms/finnish.sbl +33 -21
  26. data/vendor/snowball/algorithms/german.sbl +5 -0
  27. data/vendor/snowball/algorithms/indonesian.sbl +115 -96
  28. data/vendor/snowball/algorithms/italian.sbl +26 -1
  29. data/vendor/snowball/algorithms/lithuanian.sbl +13 -13
  30. data/vendor/snowball/algorithms/norwegian.sbl +17 -6
  31. data/vendor/snowball/algorithms/persian.sbl +387 -0
  32. data/vendor/snowball/algorithms/polish.sbl +177 -0
  33. data/vendor/snowball/algorithms/sesotho.sbl +115 -0
  34. data/vendor/snowball/algorithms/turkish.sbl +4 -4
  35. data/vendor/snowball/compiler/analyser.c +2002 -711
  36. data/vendor/snowball/compiler/driver.c +460 -298
  37. data/vendor/snowball/compiler/generator.c +439 -1965
  38. data/vendor/snowball/compiler/generator_ada.c +605 -430
  39. data/vendor/snowball/compiler/generator_c.c +2227 -0
  40. data/vendor/snowball/compiler/generator_csharp.c +365 -274
  41. data/vendor/snowball/compiler/generator_dart.c +1476 -0
  42. data/vendor/snowball/compiler/generator_go.c +348 -270
  43. data/vendor/snowball/compiler/generator_java.c +330 -233
  44. data/vendor/snowball/compiler/generator_js.c +534 -385
  45. data/vendor/snowball/compiler/generator_pascal.c +361 -320
  46. data/vendor/snowball/compiler/generator_php.c +1445 -0
  47. data/vendor/snowball/compiler/generator_python.c +399 -299
  48. data/vendor/snowball/compiler/generator_rust.c +370 -261
  49. data/vendor/snowball/compiler/generator_zig.c +1474 -0
  50. data/vendor/snowball/compiler/header.h +153 -86
  51. data/vendor/snowball/compiler/space.c +121 -63
  52. data/vendor/snowball/compiler/tokeniser.c +286 -182
  53. data/vendor/snowball/compiler/tokens.h +71 -0
  54. data/vendor/snowball/csharp/Snowball/Among.cs +14 -26
  55. data/vendor/snowball/csharp/Snowball/AssemblyInfo.cs +3 -3
  56. data/vendor/snowball/csharp/Snowball/Stemmer.cs +41 -45
  57. data/vendor/snowball/csharp/Stemwords/Program.cs +20 -14
  58. data/vendor/snowball/cxx/.gitignore +4 -0
  59. data/vendor/snowball/cxx/generate_algorithms.pl +87 -0
  60. data/vendor/snowball/cxx/stemmer.h +12 -0
  61. data/vendor/snowball/cxx/stemwords.cxx +176 -0
  62. data/vendor/snowball/cxx/utilities.cxx +2 -0
  63. data/vendor/snowball/dart/.gitignore +4 -0
  64. data/vendor/snowball/dart/analysis_options.yaml +1 -0
  65. data/vendor/snowball/dart/example/test_app.dart +65 -0
  66. data/vendor/snowball/dart/generate_algorithms.pl +21 -0
  67. data/vendor/snowball/dart/lib/snowball.dart +18 -0
  68. data/vendor/snowball/dart/lib/src/snowball.dart +339 -0
  69. data/vendor/snowball/dart/pubspec.yaml +17 -0
  70. data/vendor/snowball/doc/libstemmer_dart_README +37 -0
  71. data/vendor/snowball/doc/libstemmer_js_README +2 -2
  72. data/vendor/snowball/doc/libstemmer_php_README +38 -0
  73. data/vendor/snowball/doc/libstemmer_python_README +3 -3
  74. data/vendor/snowball/examples/stemwords.c +18 -3
  75. data/vendor/snowball/go/README.md +12 -4
  76. data/vendor/snowball/go/env.go +12 -14
  77. data/vendor/snowball/go/stemwords/main.go +2 -1
  78. data/vendor/snowball/java/org/tartarus/snowball/CharArraySequence.java +36 -0
  79. data/vendor/snowball/java/org/tartarus/snowball/SnowballProgram.java +17 -34
  80. data/vendor/snowball/java/org/tartarus/snowball/SnowballStemmer.java +0 -2
  81. data/vendor/snowball/javascript/base-stemmer.js +219 -252
  82. data/vendor/snowball/javascript/stemwords.js +86 -58
  83. data/vendor/snowball/libstemmer/mkmodules.pl +1 -1
  84. data/vendor/snowball/libstemmer/modules.txt +4 -0
  85. data/vendor/snowball/pascal/SnowballProgram.pas +18 -31
  86. data/vendor/snowball/php/base-stemmer.php +453 -0
  87. data/vendor/snowball/php/stemwords.php +25 -0
  88. data/vendor/snowball/python/create_init.py +16 -21
  89. data/vendor/snowball/python/pyproject.toml +3 -0
  90. data/vendor/snowball/python/setup.py +5 -7
  91. data/vendor/snowball/python/snowballstemmer/among.py +1 -2
  92. data/vendor/snowball/python/snowballstemmer/basestemmer.py +24 -33
  93. data/vendor/snowball/python/stemwords.py +72 -63
  94. data/vendor/snowball/runtime/api.c +11 -42
  95. data/vendor/snowball/runtime/api.h +11 -9
  96. data/vendor/snowball/runtime/snowball_runtime.h +110 -0
  97. data/vendor/snowball/runtime/utilities.c +282 -106
  98. data/vendor/snowball/rust/src/main.rs +2 -2
  99. data/vendor/snowball/rust/src/snowball/snowball_env.rs +7 -9
  100. data/vendor/snowball/tests/compilertest +62 -0
  101. data/vendor/snowball/tests/errors/ae-errors.sbl +53 -0
  102. data/vendor/snowball/tests/errors/ae-errors.stderr +8 -0
  103. data/vendor/snowball/tests/errors/bad-dollar.sbl +14 -0
  104. data/vendor/snowball/tests/errors/bad-dollar.stderr +4 -0
  105. data/vendor/snowball/tests/errors/bad-grouping-definition.sbl +9 -0
  106. data/vendor/snowball/tests/errors/bad-grouping-definition.stderr +6 -0
  107. data/vendor/snowball/tests/errors/missing-bra.sbl +6 -0
  108. data/vendor/snowball/tests/errors/missing-bra.stderr +3 -0
  109. data/vendor/snowball/tests/errors/missing-command.sbl +9 -0
  110. data/vendor/snowball/tests/errors/missing-command.stderr +1 -0
  111. data/vendor/snowball/tests/errors/missing-ket-backwardmode.sbl +3 -0
  112. data/vendor/snowball/tests/errors/missing-ket-backwardmode.stderr +1 -0
  113. data/vendor/snowball/tests/errors/missing-ket.sbl +7 -0
  114. data/vendor/snowball/tests/errors/missing-ket.stderr +6 -0
  115. data/vendor/snowball/tests/errors/notdefined.sbl +4 -0
  116. data/vendor/snowball/tests/errors/notdefined.stderr +2 -0
  117. data/vendor/snowball/tests/errors/string-omitted.sbl +5 -0
  118. data/vendor/snowball/tests/errors/string-omitted.stderr +1 -0
  119. data/vendor/snowball/tests/errors/undeclared.sbl +20 -0
  120. data/vendor/snowball/tests/errors/undeclared.stderr +9 -0
  121. data/vendor/snowball/tests/errors/unexpected-token.sbl +24 -0
  122. data/vendor/snowball/tests/errors/unexpected-token.stderr +17 -0
  123. data/vendor/snowball/tests/errors/wrongdirection.sbl +14 -0
  124. data/vendor/snowball/tests/errors/wrongdirection.stderr +1 -0
  125. data/vendor/snowball/tests/runtime/among.sbl +19 -0
  126. data/vendor/snowball/tests/runtime/arithmeticexpr.sbl +86 -0
  127. data/vendor/snowball/tests/runtime/attachinsert.sbl +47 -0
  128. data/vendor/snowball/tests/runtime/booleans.sbl +19 -0
  129. data/vendor/snowball/tests/runtime/externals.sbl +22 -0
  130. data/vendor/snowball/tests/runtime/hop.sbl +12 -0
  131. data/vendor/snowball/tests/runtime/integertests.sbl +60 -0
  132. data/vendor/snowball/tests/runtime/intlimits.sbl +25 -0
  133. data/vendor/snowball/tests/runtime/naming.sbl +20 -0
  134. data/vendor/snowball/tests/runtime/not.sbl +30 -0
  135. data/vendor/snowball/tests/runtime/or.sbl +17 -0
  136. data/vendor/snowball/tests/runtime/repeat.sbl +16 -0
  137. data/vendor/snowball/tests/runtime/setlimit.sbl +24 -0
  138. data/vendor/snowball/tests/runtime/sizelen.sbl +56 -0
  139. data/vendor/snowball/tests/runtime/slice.sbl +27 -0
  140. data/vendor/snowball/tests/runtime/stringdollar.sbl +39 -0
  141. data/vendor/snowball/tests/runtime/strings.sbl +66 -0
  142. data/vendor/snowball/tests/runtime/test.sbl +19 -0
  143. data/vendor/snowball/tests/stemtest.c +41 -1
  144. data/vendor/snowball/tests/syntax/canon.sbl +32 -0
  145. data/vendor/snowball/tests/syntax/canon.stderr +0 -0
  146. data/vendor/snowball/tests/syntax/canon.syntax +57 -0
  147. data/vendor/snowball/tests/syntax/emptyprogram.sbl +2 -0
  148. data/vendor/snowball/tests/syntax/emptyprogram.syntax +0 -0
  149. data/vendor/snowball/tests/syntax/groupings.sbl +11 -0
  150. data/vendor/snowball/tests/syntax/inline.sbl +144 -0
  151. data/vendor/snowball/tests/syntax/inline.stderr +0 -0
  152. data/vendor/snowball/tests/syntax/inline.syntax +121 -0
  153. data/vendor/snowball/tests/syntax/legacy.sbl +17 -0
  154. data/vendor/snowball/tests/syntax/legacy.stderr +5 -0
  155. data/vendor/snowball/tests/syntax/legacy.syntax +19 -0
  156. data/vendor/snowball/tests/syntax/loops.sbl +14 -0
  157. data/vendor/snowball/tests/syntax/loops.stderr +9 -0
  158. data/vendor/snowball/tests/syntax/loops.syntax +29 -0
  159. data/vendor/snowball/tests/syntax/noops.sbl +76 -0
  160. data/vendor/snowball/tests/syntax/noops.stderr +27 -0
  161. data/vendor/snowball/tests/syntax/noops.syntax +135 -0
  162. data/vendor/snowball/tests/syntax/simplifyae.sbl +21 -0
  163. data/vendor/snowball/tests/syntax/simplifyae.stderr +0 -0
  164. data/vendor/snowball/tests/syntax/simplifyae.syntax +39 -0
  165. data/vendor/snowball/tests/syntax/unused.sbl +18 -0
  166. data/vendor/snowball/tests/syntax/unused.stderr +7 -0
  167. data/vendor/snowball/tests/syntax/unused.syntax +3 -0
  168. data/vendor/snowball/zig/env.zig +599 -0
  169. data/vendor/snowball/zig/generate_algorithms.pl +19 -0
  170. data/vendor/snowball/zig/stemwords.zig +123 -0
  171. metadata +102 -4
  172. data/vendor/snowball/compiler/syswords.h +0 -86
  173. data/vendor/snowball/runtime/header.h +0 -62
@@ -7,7 +7,6 @@ routines (
7
7
  initial_apostrophe
8
8
  long_word
9
9
  merged_numeral
10
- not_after_letter
11
10
  pronoun
12
11
  standard_suffix
13
12
  ujn_suffix
@@ -124,19 +123,19 @@ backwardmode (
124
123
  loop 2 gopast vowel or (gopast '-' next) or gopast digit
125
124
  )
126
125
 
127
- define not_after_letter as ('-' or digit)
128
-
129
126
  define standard_suffix as (
130
- [substring try '-']
127
+ [
131
128
  among(
132
129
  'a' 'aj' 'ajn' 'an'
133
130
  'e' 'en'
134
131
  'i' 'as' 'is' 'os' 'u' 'us'
135
132
  'o' 'oj' 'ojn' 'on'
136
- 'j' not_after_letter
137
- 'jn' not_after_letter
138
- 'n' not_after_letter
133
+ ()
134
+ 'j' 'jn' 'n'
135
+ (test ('-' or digit))
139
136
  )
137
+ try '-'
138
+ ]
140
139
  delete
141
140
  )
142
141
  )
@@ -34,7 +34,7 @@ integers ( p1 )
34
34
  groupings ( V1 RV KI GI)
35
35
 
36
36
  define V1 'aeiou{o~}{a"}{o"}{u"}'
37
- define RV 'aeiuo'
37
+ define RV 'aeiuo{'}'
38
38
  define KI 'kptgbdshf{sv}z{zv}'
39
39
  define GI 'cjlmnqrvwxaeiou{o~}{a"}{o"}{u"}'
40
40
 
@@ -42,7 +42,12 @@ define mark_regions as (
42
42
 
43
43
  $p1 = limit
44
44
 
45
- gopast V1 gopast non-V1 setmark p1
45
+ (
46
+ hop 2 gopast '{'}'
47
+ ) or (
48
+ gopast V1 gopast non-V1
49
+ )
50
+ setmark p1
46
51
  )
47
52
 
48
53
 
@@ -131,7 +136,7 @@ backwardmode (
131
136
  'ikkude' (<-'iku') //plural genitive: õnnelikkude -> õnneliku
132
137
  'ikke' (<-'iku') //plural partitive: rahulikke -> rahuliku
133
138
  'ike' (<-'iku') //plural genitive: ohtlike -> ohtliku
134
- 'sid' (not LONGV delete) //plural partitive and sg2pst and pl3pst: auto-sid and laul-sid (exludes plural nominative with words like gaasid, roosid)
139
+ 'sid' (not LONGV delete) //plural partitive and sg2pst and pl3pst: auto-sid and laul-sid (excludes plural nominative with words like gaasid, roosid)
135
140
  // plural genitive and pl2: ministri-te, oluliste -> olulise and saada-te, laula-te;
136
141
  // also torte -> tort (if not in compound word) and kokkuvõtte -> kokkuvõte and roheliste -> rohelise, tegemiste -> tegemise, teadlaste -> teadlase
137
142
  'te' (
@@ -264,6 +269,6 @@ define stem as (
264
269
  do emphasis
265
270
  do ( verb or substantive )
266
271
  do undouble_kpt
267
-
272
+ ['{'}'] delete
268
273
  )
269
274
  )
@@ -11,7 +11,7 @@ routines (
11
11
  mark_regions
12
12
  R2
13
13
  particle_etc possessive
14
- LONG VI
14
+ LV VI A E I O U A_ O_
15
15
  case_ending
16
16
  i_plural
17
17
  t_plural
@@ -24,7 +24,7 @@ externals ( stem )
24
24
  integers ( p1 p2 )
25
25
  strings ( x )
26
26
  booleans ( ending_removed )
27
- groupings ( AEI C V1 V2 particle_end )
27
+ groupings ( AEI C v particle_end )
28
28
 
29
29
  stringescapes {}
30
30
 
@@ -32,20 +32,20 @@ stringescapes {}
32
32
 
33
33
  stringdef a" '{U+00E4}'
34
34
  stringdef o" '{U+00F6}'
35
+ stringdef o/ '{U+00F8}'
35
36
 
36
37
  define AEI 'a{a"}ei'
37
38
  define C 'bcdfghjklmnpqrstvwxz'
38
- define V1 'aeiouy{a"}{o"}'
39
- define V2 'aeiou{a"}{o"}'
40
- define particle_end V1 + 'nt'
39
+ define v 'aeiouy{a"}{o"}'
40
+ define particle_end v + 'nt'
41
41
 
42
42
  define mark_regions as (
43
43
 
44
44
  $p1 = limit
45
45
  $p2 = limit
46
46
 
47
- gopast V1 gopast non-V1 setmark p1
48
- gopast V1 gopast non-V1 setmark p2
47
+ gopast v gopast non-v setmark p1
48
+ gopast v gopast non-v setmark p2
49
49
  )
50
50
 
51
51
  backwardmode (
@@ -88,28 +88,39 @@ backwardmode (
88
88
  )
89
89
  )
90
90
 
91
- define LONG as
91
+ define LV as
92
92
  among('aa' 'ee' 'ii' 'oo' 'uu' '{a"}{a"}' '{o"}{o"}')
93
93
 
94
- define VI as ('i' V2)
94
+ define VI as
95
+ among('ai' 'ei' 'ii' 'oi' 'ui' '{a"}i' '{o"}i' '{'}')
96
+
97
+ define A as ('a' or '{'}')
98
+ define E as ('e' or '{'}')
99
+ define I as ('i' or '{'}')
100
+ define O as ('o' or '{'}')
101
+ define U as ('u' or '{'}')
102
+ define A_ as ('{a"}' or '{'}')
103
+ // -ø-hön seen with Norwegian place names, e.g. Bodøhön
104
+ define O_ as ('{o"}' or '{o/}' or '{'}')
95
105
 
96
106
  define case_ending as (
97
107
  setlimit tomark p1 for ([substring])
98
108
  among(
99
- 'han' ('a') //-.
100
- 'hen' ('e') // |
101
- 'hin' ('i') // |
102
- 'hon' ('o') // |
103
- 'h{a"}n' ('{a"}') // Illative [43]
104
- 'h{o"}n' ('{o"}') // |
109
+ 'h{a"}n' A_ //-.
110
+ 'h{o"}n' O_ // |
111
+ 'han' A // |
112
+ 'hen' E // |
113
+ 'hin' I // Illative [43]
114
+ 'hon' O // |
115
+ 'hun' U // |
105
116
  'siin' VI // |
106
- 'seen' LONG //-'
117
+ 'seen' LV //-'
107
118
 
108
119
  'den' VI
109
120
  'tten' VI // Genitive plurals [34]
110
121
  ()
111
122
  'n' // Genitive or Illative
112
- ( try ( LONG // Illative
123
+ ( try ( LV // Illative
113
124
  or 'ie' // Genitive
114
125
  and next ]
115
126
  )
@@ -117,7 +128,7 @@ backwardmode (
117
128
  )
118
129
 
119
130
  'a' '{a"}' //-.
120
- (V1 C) // |
131
+ (v C) // |
121
132
  'tta' 'tt{a"}' // Partitive [32]
122
133
  ('e') // |
123
134
  'ta' 't{a"}' //-'
@@ -160,7 +171,7 @@ backwardmode (
160
171
  )
161
172
  define t_plural as ( // [26]
162
173
  setlimit tomark p1 for (
163
- ['t'] test V1
174
+ ['t'] test v
164
175
  delete
165
176
  )
166
177
  setlimit tomark p2 for ([substring])
@@ -172,12 +183,13 @@ backwardmode (
172
183
  )
173
184
  define tidy as (
174
185
  setlimit tomark p1 for (
175
- do ( LONG and ([next] delete ) ) // undouble vowel
186
+ do ( LV and ([next] delete ) ) // undouble vowel
176
187
  do ( [AEI] C delete ) // remove trailing a, a", e, i
177
188
  do ( ['j'] 'o' or 'u' delete )
178
189
  do ( ['o'] 'j' delete )
179
190
  )
180
- goto non-V1 [C] -> x x delete // undouble consonant
191
+ do (goto non-v [C] -> x x delete) // undouble consonant
192
+ ['{'}'] delete
181
193
  )
182
194
  )
183
195
 
@@ -148,6 +148,11 @@ backwardmode (
148
148
  )
149
149
  )
150
150
  )
151
+ do (
152
+ [substring] among(
153
+ '{'}s' '{'}sch' '{'}' (next not atlimit delete)
154
+ )
155
+ )
151
156
  )
152
157
  )
153
158
 
@@ -34,11 +34,6 @@ routines (
34
34
  remove_first_order_prefix
35
35
  remove_second_order_prefix
36
36
  remove_suffix
37
- KER
38
- SUFFIX_KAN_OK
39
- SUFFIX_AN_OK
40
- SUFFIX_I_OK
41
- VOWEL
42
37
  )
43
38
 
44
39
  externals ( stem )
@@ -59,101 +54,112 @@ backwardmode (
59
54
  )
60
55
  )
61
56
 
62
- // prefix not in {ke, peng, per}
63
- define SUFFIX_KAN_OK as (
64
- // On page 29, the example "kompas Q.31" says "Both Nazief and Porter
65
- // stemmer converted the word peledakan (blast, explotion [sic]) to
66
- // ledak (to blast, to explode)". However, the algorithm as described
67
- // doesn't behave in this way - grammatically the prefix pe- occurs as a
68
- // variation of both the first-order derivational prefix peng- and the
69
- // second-order derivational prefix per-, but table 2.5 doesn't include
70
- // "pe", only table 2.6 does, so "peledakan" is handled (incorrectly)
71
- // as having prefix "per" not "peng", and so we remove derivational
72
- // suffix "kan" rather than "an" to give stem leda. (Porter-style
73
- // stemmers remove the longest suffix they can amongst those available,
74
- // which this paper notes in the last paragraph on page 15).
75
- //
76
- // We resolve this by amending the condition on suffix "kan" to
77
- // "prefix ∉ {ke, peng, per}", which seems to make the stemmer's
78
- // behaviour match all the examples in the paper except for one:
79
- // "perbaikan" is shown in table 3.4 as stemming to "bai", but with
80
- // this change it now stems to "baik". The table notes that "baik" is
81
- // the actual root so this deviation is an improvement. In a sample
82
- // vocabulary derived from the most common words in id.wikipedia.org,
83
- // this change only affects 0.12% of words (76 out of 64,587, including
84
- // "peledakan" and "perbaikan").
85
- $prefix != 3 and $prefix != 2
86
- )
87
-
88
- // prefix not in {di, meng, ter}
89
- define SUFFIX_AN_OK as ( $prefix != 1 )
90
-
91
- define SUFFIX_I_OK as (
92
- // prefix not in {ke, peng, ber}
93
- $prefix <= 2
94
-
95
- // The rest of the condition from the paper is:
96
- // V|K...c₁c₁, c₁ ≠ s, c₂ ≠ i
97
- //
98
- // The meaning of this is unclear in several ways, and none of the
99
- // examples given of the stemmer's behaviour in the paper help to
100
- // resolve these issues.
101
- //
102
- // Notice that c₂ isn't actually used - the most obvious explanation
103
- // seems to be that "c₁c₁" should read "c₁c₂", or maybe "c₂c₁".
104
- //
105
- // Elsewhere the paper defines V... as meaning "the stem starts with
106
- // a vowel" and K... as meaning "the stem starts with a consonant".
107
- // The meaning of | isn't actually defined, but clearly means
108
- // alternation.
109
- //
110
- // However nowhere is the precedence of | vs ... defined, and there
111
- // isn't a standard precedence we could reasonably assume. In other
112
- // places where the paper says X|Y... it seems the | binds more
113
- // tightly, so it's (V|K)...cᵢcⱼ not V|(K...cᵢcⱼ). That seems a bit
114
- // odd as the first letter must be either a vowel or a consonant, so
115
- // that really just means "ends cᵢcⱼ" (and has at least one letter
116
- // before cᵢ but we only call SUFFIX_I_OK if $measure > 2 which
117
- // ensures that part). However, nowhere in the paper uses or defines
118
- // a notation such as ...X, which may explain this seemingly redundant
119
- // way of specifying this.
120
- //
121
- // The conditions elsewhere on prefix removal (e.g. V...) are clearly
122
- // on the stem left after the prefix is removed. None of the other
123
- // rules for suffix removal have conditions on the stem, but for
124
- // consistency with the prefix rules we might expect that the cᵢcⱼ
125
- // test is on what's left *after* removing the "i" suffix.
126
- //
127
- // Studying Indonesian wordlists and discussion with a native
128
- // speaker leads us to conclude that the purpose of this check is to
129
- // protect words of foreign origin (e.g. "televisi", "organisasi",
130
- // "komunikasi") from stemming, and the common feature of these is
131
- // that the word ends "-si", so we conclude that the condition here
132
- // should be read as "word does not end -si", and this is what we
133
- // have implemented.
134
- not 's'
135
- )
136
-
137
57
  define remove_suffix as (
138
58
  [substring] among (
139
- 'kan' SUFFIX_KAN_OK 'an' SUFFIX_AN_OK 'i' SUFFIX_I_OK
140
- (delete $measure-=1)
59
+ 'an' (
60
+ (
61
+ // prefix not in {ke, peng, per}. [See SUFFIX_KAN_NOTE]
62
+ ($prefix != 3 and $prefix != 2)
63
+ // Remove suffix 'kan'
64
+ 'k']
65
+ ) or (
66
+ // prefix not in {di, meng, ter}
67
+ $prefix != 1
68
+ )
69
+ )
70
+ 'i' (
71
+ // prefix not in {ke, peng, ber}
72
+ $prefix <= 2
73
+ // word does not end '-si'. [See SUFFIX_I_NOTE]
74
+ not 's'
75
+ )
141
76
  )
77
+ delete $measure-=1
142
78
  )
79
+
80
+ // SUFFIX_KAN_NOTE:
81
+ // On page 29, the example "kompas Q.31" says "Both Nazief and Porter
82
+ // stemmer converted the word peledakan (blast, explotion [sic]) to
83
+ // ledak (to blast, to explode)". However, the algorithm as described
84
+ // doesn't behave in this way - grammatically the prefix pe- occurs as a
85
+ // variation of both the first-order derivational prefix peng- and the
86
+ // second-order derivational prefix per-, but table 2.5 doesn't include
87
+ // "pe", only table 2.6 does, so "peledakan" is handled (incorrectly)
88
+ // as having prefix "per" not "peng", and so we remove derivational
89
+ // suffix "kan" rather than "an" to give stem leda. (Porter-style
90
+ // stemmers remove the longest suffix they can amongst those available,
91
+ // which this paper notes in the last paragraph on page 15).
92
+ //
93
+ // We resolve this by amending the condition on suffix "kan" to
94
+ // "prefix ∉ {ke, peng, per}", which seems to make the stemmer's
95
+ // behaviour match all the examples in the paper except for one:
96
+ // "perbaikan" is shown in table 3.4 as stemming to "bai", but with
97
+ // this change it now stems to "baik". The table notes that "baik" is
98
+ // the actual root so this deviation is an improvement. In a sample
99
+ // vocabulary derived from the most common words in id.wikipedia.org,
100
+ // this change only affects 0.12% of words (76 out of 64,587, including
101
+ // "peledakan" and "perbaikan").
102
+
103
+ // SUFFIX_I_NOTE:
104
+ // The rest of the condition from the paper is:
105
+ // V|K...c₁c₁, c₁ ≠ s, c₂ ≠ i
106
+ //
107
+ // The meaning of this is unclear in several ways, and none of the
108
+ // examples given of the stemmer's behaviour in the paper help to
109
+ // resolve these issues.
110
+ //
111
+ // Notice that c₂ isn't actually used - the most obvious explanation
112
+ // seems to be that "c₁c₁" should read "c₁c₂", or maybe "c₂c₁".
113
+ //
114
+ // Elsewhere the paper defines V... as meaning "the stem starts with
115
+ // a vowel" and K... as meaning "the stem starts with a consonant".
116
+ // The meaning of | isn't actually defined, but clearly means
117
+ // alternation.
118
+ //
119
+ // However nowhere is the precedence of | vs ... defined, and there
120
+ // isn't a standard precedence we could reasonably assume. In other
121
+ // places where the paper says X|Y... it seems the | binds more
122
+ // tightly, so it's (V|K)...cᵢcⱼ not V|(K...cᵢcⱼ). That seems a bit
123
+ // odd as the first letter must be either a vowel or a consonant, so
124
+ // that really just means "ends cᵢcⱼ" (and has at least one letter
125
+ // before cᵢ but we only call remove_suffix if $measure > 2 which
126
+ // ensures that part). However, nowhere in the paper uses or defines
127
+ // a notation such as ...X, which may explain this seemingly redundant
128
+ // way of specifying this.
129
+ //
130
+ // The conditions elsewhere on prefix removal (e.g. V...) are clearly
131
+ // on the stem left after the prefix is removed. None of the other
132
+ // rules for suffix removal have conditions on the stem, but for
133
+ // consistency with the prefix rules we might expect that the cᵢcⱼ
134
+ // test is on what's left *after* removing the "i" suffix.
135
+ //
136
+ // Studying Indonesian wordlists and discussion with a native
137
+ // speaker leads us to conclude that the purpose of this check is to
138
+ // protect words of foreign origin (e.g. "televisi", "organisasi",
139
+ // "komunikasi") from stemming, and the common feature of these is
140
+ // that the word ends "-si", so we conclude that the condition here
141
+ // should be read as "word does not end -si", and this is what we
142
+ // have implemented.
143
143
  )
144
144
 
145
145
  define vowel 'aeiou'
146
146
 
147
- define VOWEL as ( vowel )
148
-
149
- define KER as ( non-vowel 'er' )
150
-
151
147
  define remove_first_order_prefix as (
152
148
  [substring] among (
153
- 'di' 'meng' 'men' 'me' 'ter' (delete $prefix=1 $measure-=1)
154
- 'ke' 'peng' 'pen' (delete $prefix=3 $measure-=1)
155
- 'meny' VOWEL ($prefix=1 <-'s' $measure-=1)
156
- 'peny' VOWEL ($prefix=3 <-'s' $measure-=1)
149
+ 'di' 'meng' 'me' 'ter'
150
+ (delete $prefix=1 $measure-=1)
151
+ 'men' (
152
+ ('y' test vowel ] <-'s' $prefix=1 $measure-=1)
153
+ or
154
+ (delete $prefix=1 $measure-=1)
155
+ )
156
+ 'ke' 'peng'
157
+ (delete $prefix=3 $measure-=1)
158
+ 'pen' (
159
+ ('y' test vowel ] <-'s' $prefix=3 $measure-=1)
160
+ or
161
+ (delete $prefix=3 $measure-=1)
162
+ )
157
163
  'mem' ($prefix=1 $measure-=1 vowel and <-'p' or delete)
158
164
  'pem' ($prefix=3 $measure-=1 vowel and <-'p' or delete)
159
165
  )
@@ -165,13 +171,26 @@ define remove_second_order_prefix as (
165
171
  // is intended so that e.g. "pelajaran" stems to "ajar" not "lajar".
166
172
  // This change only affects a very small number of words (11 out of
167
173
  // 64,587) and only for the better.
168
- [substring] among (
169
- 'per' 'pe' (delete $prefix=2 $measure-=1)
170
- 'pelajar' (<-'ajar' $measure-=1)
171
- 'ber' (delete $prefix=4 $measure-=1)
172
- 'belajar' (<-'ajar' $prefix=4 $measure-=1)
173
- 'be' KER (delete $prefix=4 $measure-=1)
174
+ [among (
175
+ 'pe' (
176
+ ( 'r'] $prefix=2 )
177
+ or
178
+ ( 'l'] 'ajar' )
179
+ or
180
+ ( ] $prefix=2 )
181
+ )
182
+ 'be' (
183
+ ( 'r'] )
184
+ or
185
+ ( 'l'] 'ajar')
186
+ or
187
+ ( ] non-vowel 'er' )
188
+ $prefix=4
189
+ )
174
190
  )
191
+ // All prefixes we remove here contain exactly one vowel.
192
+ $measure-=1
193
+ delete
175
194
  )
176
195
 
177
196
  define stem as (
@@ -1,5 +1,6 @@
1
1
 
2
2
  routines (
3
+ elisions
3
4
  prelude postlude mark_regions
4
5
  RV R1 R2
5
6
  attached_pronoun
@@ -31,6 +32,29 @@ stringdef u` '{U+00F9}'
31
32
 
32
33
  define v 'aeiou{a`}{e`}{i`}{o`}{u`}'
33
34
 
35
+ define elisions as (
36
+ [ substring ] not atlimit among (
37
+ // 'c{'}' doesn't seem useful to remove here.
38
+ 'd{'}' // e.g. d'Italia ("of Italy")
39
+ 'l{'}' // e.g. l'anno ("the year")
40
+ 'm{'}' // e.g. m'ama ("he loves me")
41
+ 's{'}' // e.g. s'innamora ("he falls in love")
42
+ 't{'}' // e.g. t'amo ("I love you")
43
+ 'v{'}' // e.g. v'adoro ("I adore you")
44
+ 'all{'}' // e.g. all'università ("at university")
45
+ 'dall{'}' // e.g. dall'album ("from the album")
46
+ 'dell{'}' // e.g. dell'anno ("of the year")
47
+ 'gl{'}' // e.g. gl'inglesi ("the English")
48
+ 'nell{'}' // e.g. nell'estate ("in the summer")
49
+ 'quell{'}' // e.g. quell'anno ("that year")
50
+ 'quest{'}' // e.g. quest'anno ("this year")
51
+ 'sull{'}' // e.g. sull'isola ("on the island")
52
+ 'tutt{'}' // e.g. tutt'Europa ("all of Europe")
53
+ 'un{'}' // e.g. un'eccentricità ("an eccentricity")
54
+ )
55
+ delete
56
+ )
57
+
34
58
  define prelude as (
35
59
  test repeat (
36
60
  [substring] among(
@@ -96,7 +120,7 @@ backwardmode (
96
120
  'cela' 'cele' 'celi' 'celo' 'cene'
97
121
  'vela' 'vele' 'veli' 'velo' 'vene'
98
122
  )
99
- among( (RV)
123
+ substring RV among(
100
124
  'ando' 'endo' (delete)
101
125
  'ar' 'er' 'ir' (<- 'e')
102
126
  )
@@ -181,6 +205,7 @@ backwardmode (
181
205
  )
182
206
 
183
207
  define stem as (
208
+ do elisions
184
209
  do prelude
185
210
  do mark_regions
186
211
  backwards (
@@ -4,7 +4,7 @@ externals ( stem )
4
4
  stringescapes { }
5
5
 
6
6
  /* Special characters in Unicode Latin Extended-A */
7
- // ' nosine
7
+ // k nosine
8
8
  stringdef ak '{U+0105}' // ą a + ogonek
9
9
  stringdef ek '{U+0119}' // ę e + ogonek
10
10
  stringdef ik '{U+012F}' // į i + ogonek
@@ -111,21 +111,20 @@ backwardmode (
111
111
 
112
112
 
113
113
  // V linksniuote (declension V)
114
- 'ies' 'ens' 'enio' 'ers' // avies, vandens, sesers
115
- 'eniui' 'eriai' // vandeniui, eriai
116
- 'en{ik}' 'er{ik}' // vandenį, seserį
117
- 'imi' 'eniu' 'erimi' 'eria' // avimi, vandeniu, seserimi, seseria
118
- 'enyje' 'eryje' // vandenyje, seseryje
119
- 'ie' 'enie' 'erie' // avie, vandenie, seserie
120
-
121
- 'enys' 'erys' // vandenys, seserys
114
+ 'ies' 'ens' 'enio' // avies, vandens, sesers
115
+ 'eniui' // vandeniui
116
+ 'en{ik}' // vandenį
117
+ 'imi' 'eniu' // avimi, vandeniu
118
+ 'enyje' // vandenyje
119
+ 'ie' 'enie' // avie, vandenide
120
+
121
+ 'enys' // vandenys
122
122
  // 'en{uk}' konfliktas su 'žandenų' 'antenų'
123
- 'er{uk}' // seserų
124
- 'ims' 'enims' 'erims' // avims, vandemins, seserims
123
+ 'ims' 'enims' // avims, vandemins
125
124
  'enis' // vandenis
126
125
  'imis' // žebenkštimis
127
126
  'enimis' // vandenimis
128
- 'yse' 'enyse' 'eryse' // avyse, vandenyse, seseryse
127
+ 'yse' 'enyse' // avyse, vandenyse
129
128
 
130
129
 
131
130
  // Būdvardžiai (Adjectives)
@@ -355,7 +354,7 @@ define stem as (
355
354
 
356
355
  do (
357
356
  // priešdėlis 'a' ilgeniuose nei 6 raidės žodžiuose, pvz. 'a-liejus'.
358
- try (test 'a' $(len > 6) hop 1)
357
+ try ('a' $(len > 6))
359
358
 
360
359
  gopast v gopast non-v setmark p1
361
360
  )
@@ -367,6 +366,7 @@ define stem as (
367
366
  do step2
368
367
  do fix_chdz
369
368
  do fix_gd
369
+ ['{'}'] delete
370
370
  )
371
371
 
372
372
  )
@@ -7,7 +7,7 @@ routines (
7
7
 
8
8
  externals ( stem )
9
9
 
10
- integers ( p1 x )
10
+ integers ( p1 )
11
11
 
12
12
  groupings ( v s_ending )
13
13
 
@@ -28,12 +28,21 @@ define v 'ae{e^}io{o`}{o'}{o^}uy{ae}{ao}{o/}'
28
28
  define s_ending 'bcdfghjlmnoptvyz'
29
29
 
30
30
  define mark_regions as (
31
-
32
31
  $p1 = limit
33
32
 
34
- test ( hop 3 setmark x )
35
- gopast v gopast non-v setmark p1
36
- try ( $p1 < x $p1 = x )
33
+ do (
34
+ (
35
+ // If there's an apostrophe, start R1 after it to handle
36
+ // acronym loanwords such as "pc'en" and "ep'en".
37
+ gopast '{'}'
38
+ ) or (
39
+ gopast v gopast non-v
40
+ )
41
+ setmark p1
42
+ )
43
+
44
+ // Ensure at least 3 characters before R1.
45
+ test (hop 3 do ($p1 < cursor $p1 = cursor))
37
46
  )
38
47
 
39
48
  backwardmode (
@@ -85,10 +94,12 @@ backwardmode (
85
94
 
86
95
  define stem as (
87
96
 
88
- do mark_regions
97
+ mark_regions
89
98
  backwards (
90
99
  do main_suffix
91
100
  do consonant_pair
92
101
  do other_suffix
102
+ // Remove trailing apostrophe.
103
+ ['{'}'] delete
93
104
  )
94
105
  )