mittens 0.3.3 → 0.3.5

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 (83) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/LICENSE.txt +1 -1
  4. data/README.md +1 -1
  5. data/ext/mittens/ext.c +68 -30
  6. data/ext/mittens/extconf.rb +2 -0
  7. data/lib/mittens/version.rb +1 -1
  8. data/vendor/snowball/.github/workflows/ci.yml +43 -3
  9. data/vendor/snowball/.github/workflows/coverage.yml +8 -5
  10. data/vendor/snowball/GNUmakefile +46 -16
  11. data/vendor/snowball/NEWS +437 -13
  12. data/vendor/snowball/README.rst +4 -4
  13. data/vendor/snowball/algorithms/earlymodernenglish.sbl +301 -0
  14. data/vendor/snowball/algorithms/french.sbl +1 -1
  15. data/vendor/snowball/algorithms/ukrainian.sbl +1251 -0
  16. data/vendor/snowball/compiler/analyser.c +460 -156
  17. data/vendor/snowball/compiler/driver.c +41 -36
  18. data/vendor/snowball/compiler/generator.c +24 -1
  19. data/vendor/snowball/compiler/generator_ada.c +46 -45
  20. data/vendor/snowball/compiler/generator_c.c +1094 -187
  21. data/vendor/snowball/compiler/generator_csharp.c +34 -11
  22. data/vendor/snowball/compiler/generator_dart.c +39 -11
  23. data/vendor/snowball/compiler/generator_go.c +6 -6
  24. data/vendor/snowball/compiler/generator_java.c +29 -8
  25. data/vendor/snowball/compiler/generator_js.c +65 -38
  26. data/vendor/snowball/compiler/generator_pascal.c +69 -26
  27. data/vendor/snowball/compiler/generator_php.c +33 -12
  28. data/vendor/snowball/compiler/generator_python.c +23 -4
  29. data/vendor/snowball/compiler/generator_rust.c +37 -13
  30. data/vendor/snowball/compiler/generator_zig.c +6 -6
  31. data/vendor/snowball/compiler/header.h +85 -14
  32. data/vendor/snowball/compiler/space.c +67 -38
  33. data/vendor/snowball/compiler/tokeniser.c +28 -16
  34. data/vendor/snowball/csharp/Snowball/AssemblyInfo.cs +2 -2
  35. data/vendor/snowball/csharp/Snowball/Stemmer.cs +1 -4
  36. data/vendor/snowball/cxx/generate_algorithms.pl +5 -4
  37. data/vendor/snowball/cxx/{utilities.cxx → snowball_runtime.cxx} +1 -1
  38. data/vendor/snowball/cxx/stemmer.h +4 -0
  39. data/vendor/snowball/cxx/stemwords.cxx +36 -6
  40. data/vendor/snowball/dart/lib/src/snowball.dart +2 -2
  41. data/vendor/snowball/dart/pubspec.yaml +1 -1
  42. data/vendor/snowball/doc/libstemmer_c_README +3 -0
  43. data/vendor/snowball/doc/libstemmer_php_README +1 -1
  44. data/vendor/snowball/doc/libstemmer_python_README +8 -6
  45. data/vendor/snowball/examples/stemwords.c +4 -14
  46. data/vendor/snowball/go/env.go +16 -4
  47. data/vendor/snowball/include/libstemmer.h +0 -3
  48. data/vendor/snowball/java/org/tartarus/snowball/SnowballProgram.java +4 -4
  49. data/vendor/snowball/javascript/base-stemmer.js +27 -40
  50. data/vendor/snowball/javascript/stemwords.js +34 -10
  51. data/vendor/snowball/libstemmer/libstemmer_c.in +5 -5
  52. data/vendor/snowball/libstemmer/mkmodules.pl +5 -3
  53. data/vendor/snowball/libstemmer/modules.txt +4 -2
  54. data/vendor/snowball/pascal/SnowballProgram.pas +2 -2
  55. data/vendor/snowball/php/base-stemmer.php +2 -2
  56. data/vendor/snowball/python/setup.py +5 -1
  57. data/vendor/snowball/python/snowballstemmer/basestemmer.py +1 -2
  58. data/vendor/snowball/runtime/api.c +14 -3
  59. data/vendor/snowball/runtime/api.h +13 -9
  60. data/vendor/snowball/runtime/{utilities.c → snowball_runtime.c} +115 -181
  61. data/vendor/snowball/runtime/snowball_runtime.h +35 -24
  62. data/vendor/snowball/rust/src/snowball/snowball_env.rs +1 -1
  63. data/vendor/snowball/tests/compilertest +3 -3
  64. data/vendor/snowball/tests/runtime/among.sbl +96 -2
  65. data/vendor/snowball/tests/runtime/attachinsert.sbl +4 -0
  66. data/vendor/snowball/tests/runtime/debug.out +7 -0
  67. data/vendor/snowball/tests/runtime/debug.sbl +9 -0
  68. data/vendor/snowball/tests/runtime/integertests.sbl +22 -0
  69. data/vendor/snowball/tests/runtime/marklimit.sbl +30 -0
  70. data/vendor/snowball/tests/runtime/naming.sbl +20 -0
  71. data/vendor/snowball/tests/runtime/reverse.sbl +11 -0
  72. data/vendor/snowball/tests/stemtest.c +2 -5
  73. data/vendor/snowball/tests/syntax/aeslicefrom.sbl +7 -0
  74. data/vendor/snowball/tests/syntax/canon.sbl +14 -0
  75. data/vendor/snowball/tests/syntax/canon.syntax +36 -0
  76. data/vendor/snowball/tests/syntax/inline.syntax +4 -4
  77. data/vendor/snowball/tests/syntax/localvar.sbl +38 -0
  78. data/vendor/snowball/tests/syntax/localvar.stderr +3 -0
  79. data/vendor/snowball/tests/syntax/localvar.syntax +76 -0
  80. data/vendor/snowball/tests/syntax/unused.sbl +5 -1
  81. data/vendor/snowball/tests/syntax/unused.stderr +3 -1
  82. data/vendor/snowball/zig/env.zig +24 -4
  83. metadata +14 -4
@@ -22,24 +22,27 @@ extern byte * get_input(const char * filename) {
22
22
  fprintf(stderr, "%s: Read error\n", filename);
23
23
  exit(1);
24
24
  }
25
+ SET_SIZE(u, size);
25
26
  } else {
26
27
  // Unseekable stream, e.g. piped stdin.
27
28
  size = 0;
28
29
  u = create_s(INITIAL_INPUT_BUFFER_SIZE);
29
30
  while (true) {
30
- int s = CAPACITY(u) - size;
31
- int r = fread(u + size, 1, s, input);
32
- if (r < 0) {
33
- fprintf(stderr, "%s: Read error\n", filename);
34
- exit(1);
31
+ size_t s = CAPACITY(u) - size;
32
+ size_t r = fread(u + size, 1, s, input);
33
+ size += (int)r;
34
+ SET_SIZE(u, size);
35
+ if (r < s) {
36
+ if (ferror(input)) {
37
+ fprintf(stderr, "%s: Read error\n", filename);
38
+ exit(1);
39
+ }
40
+ break;
35
41
  }
36
- size += r;
37
- if (r < s) break;
38
- u = increase_capacity_s(u, size);
42
+ u = reserve_s(u, size * 2);
39
43
  }
40
44
  }
41
45
  if (input != stdin) fclose(input);
42
- SET_SIZE(u, size);
43
46
  return u;
44
47
  }
45
48
 
@@ -171,12 +174,12 @@ static int read_literal_string(struct tokeniser * t, int c) {
171
174
  error1(t, "character values exceed 0x01ffff");
172
175
  }
173
176
  /* Ensure there's enough space for a max length
174
- * UTF-8 sequence. */
177
+ * UTF-8 sequence and then encode the character
178
+ * directly into that space. */
175
179
  int b_size = SIZE(t->b);
176
- if (CAPACITY(t->b) < b_size + 3) {
177
- t->b = increase_capacity_b(t->b, 3);
178
- }
179
- SET_SIZE(t->b, b_size + put_utf8(codepoint, t->b + b_size));
180
+ t->b = reserve_b(t->b, b_size + 4);
181
+ SET_SIZE(t->b, b_size + put_utf8(codepoint,
182
+ t->b + b_size));
180
183
  } else {
181
184
  if (t->encoding == ENC_SINGLEBYTE) {
182
185
  /* Only ISO-8859-1 is handled this way - for
@@ -533,7 +536,7 @@ extern int read_token(struct tokeniser * t) {
533
536
  for (r = t->includes; r; r = r->next) {
534
537
  byte * s = copy_s(r->s);
535
538
  s = add_sz_to_s(s, file);
536
- s[SIZE(s)] = 0;
539
+ s = ensure_nul_s(s);
537
540
  if (file_owned > 0) {
538
541
  free(file);
539
542
  } else {
@@ -546,7 +549,7 @@ extern int read_token(struct tokeniser * t) {
546
549
  }
547
550
  }
548
551
  if (u == NULL) {
549
- error(t, "Can't get '", (byte *)file, strlen(file), "'");
552
+ error(t, "Can't get '", (byte *)file, (int)strlen(file), "'");
550
553
  exit(1);
551
554
  }
552
555
  memmove(q, t, sizeof(struct input));
@@ -587,6 +590,15 @@ extern int peek_token(struct tokeniser * t) {
587
590
  return token;
588
591
  }
589
592
 
593
+ extern void push_token(struct tokeniser * t, int token) {
594
+ if (t->token_held) {
595
+ error1(t, "push_token() called but token already held");
596
+ exit(1);
597
+ }
598
+ t->token = token;
599
+ t->token_held = true;
600
+ }
601
+
590
602
  extern const char * name_of_token(int code) {
591
603
  for (int i = 0; i < NUM_ALPHA_TOKENS; i++) {
592
604
  if (alpha_tokens[i].code == code)
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
32
32
  // You can specify all the values or you can default the Build and Revision Numbers
33
33
  // by using the '*' as shown below:
34
34
  // [assembly: AssemblyVersion("1.0.*")]
35
- [assembly: AssemblyVersion(/*SNOWBALL_VERSION*/"3.1.1.0")]
36
- [assembly: AssemblyFileVersion(/*SNOWBALL_VERSION*/"3.1.1.0")]
35
+ [assembly: AssemblyVersion(/*SNOWBALL_VERSION*/"3.2.0.0")]
36
+ [assembly: AssemblyFileVersion(/*SNOWBALL_VERSION*/"3.2.0.0")]
@@ -190,11 +190,8 @@ namespace Snowball
190
190
  current.Clear();
191
191
  current.Insert(0, value);
192
192
 
193
- cursor = 0;
193
+ limit_backward = bra = ket = cursor = 0;
194
194
  limit = current.Length;
195
- limit_backward = 0;
196
- bra = cursor;
197
- ket = limit;
198
195
  }
199
196
 
200
197
 
@@ -26,6 +26,11 @@ sub add_name {
26
26
  open my $out, '>', $outname or die "Can't open output file '$outname': $!\n";
27
27
 
28
28
  print $out <<END;
29
+ // $outname: Snowball stemmer factory
30
+ //
31
+ // This file is generated by $0 from a list of module names.
32
+ // Do not edit manually.
33
+
29
34
  #include "stemmer.h"
30
35
  END
31
36
 
@@ -45,10 +50,6 @@ END
45
50
  close $in;
46
51
 
47
52
  print $out <<END;
48
- // $outname: Snowball stemmer factory
49
- //
50
- // This file is generated by $0 from a list of module names.
51
- // Do not edit manually.
52
53
 
53
54
  #include <string.h>
54
55
 
@@ -1,2 +1,2 @@
1
1
  #define SNOWBALL_RUNTIME_THROW_EXCEPTIONS
2
- #include "../runtime/utilities.c"
2
+ #include "../runtime/snowball_runtime.c"
@@ -4,7 +4,11 @@ namespace Snowball {
4
4
 
5
5
  class Stemmer {
6
6
  public:
7
+ #ifdef SNOWBALL_WIDE
8
+ virtual std::wstring operator()(const std::wstring& word) = 0;
9
+ #else
7
10
  virtual std::string operator()(const std::string& word) = 0;
11
+ #endif
8
12
  };
9
13
 
10
14
  Stemmer* make_stemmer(const char* language);
@@ -14,10 +14,13 @@
14
14
  const char * progname;
15
15
  static int pretty = 1;
16
16
 
17
- static void
18
- stem_file(Snowball::Stemmer& stemmer, std::istream& f_in, std::ostream& f_out)
17
+ template<typename Char>
18
+ void
19
+ stem_file(Snowball::Stemmer& stemmer,
20
+ std::basic_istream<Char>& f_in,
21
+ std::basic_ostream<Char>& f_out)
19
22
  {
20
- std::string word;
23
+ std::basic_string<Char> word;
21
24
 
22
25
  while (true) {
23
26
  int ch = f_in.get();
@@ -28,8 +31,12 @@ stem_file(Snowball::Stemmer& stemmer, std::istream& f_in, std::ostream& f_out)
28
31
  word.clear();
29
32
  int inlen = 0;
30
33
  while (ch != '\n' && ch >= 0) {
31
- /* Update count of utf-8 characters. */
32
- if (ch < 0x80 || ch > 0xBF) inlen += 1;
34
+ if (sizeof(Char) == 1) {
35
+ /* Update count of utf-8 characters. */
36
+ if (ch < 0x80 || ch > 0xBF) inlen += 1;
37
+ } else {
38
+ inlen += 1;
39
+ }
33
40
  /* force lower case: */
34
41
  if (ch < 128) ch = tolower(ch);
35
42
 
@@ -71,7 +78,7 @@ stem_file(Snowball::Stemmer& stemmer, std::istream& f_in, std::ostream& f_out)
71
78
  static void
72
79
  usage(int n)
73
80
  {
74
- printf("usage: %s [-l <language>] [-i <input file>] [-o <output file>] [-c <character encoding>] [-p[2]] [-h]\n"
81
+ printf("usage: %s [-l <language>] [-i <input file>] [-o <output file>] [-p[2]] [-h]\n"
75
82
  "\n"
76
83
  "The input file consists of a list of words to be stemmed, one per\n"
77
84
  "line. Words should be in lower case, but (for English) A-Z letters\n"
@@ -147,6 +154,7 @@ try {
147
154
  exit(1);
148
155
  }
149
156
 
157
+ #ifndef SNOWBALL_WIDE
150
158
  /* prepare the files */
151
159
  std::ifstream f_in;
152
160
  if (in) {
@@ -167,6 +175,28 @@ try {
167
175
 
168
176
  /* do the stemming process: */
169
177
  stem_file(*stemmer, in ? f_in : std::cin, out ? f_out : std::cout);
178
+ #else
179
+ /* prepare the files */
180
+ std::wifstream f_in;
181
+ f_in.open(in ? in : "/dev/stdin");
182
+ if (!f_in.is_open()) {
183
+ fprintf(stderr, "file %s not found\n", in);
184
+ exit(1);
185
+ }
186
+ std::wofstream f_out;
187
+ f_out.open(out ? out : "/dev/stdout");
188
+ if (!f_out.is_open()) {
189
+ fprintf(stderr, "file %s cannot be opened\n", out);
190
+ exit(1);
191
+ }
192
+
193
+ std::locale c_utf8("C.UTF8");
194
+ f_in.imbue(c_utf8);
195
+ f_out.imbue(c_utf8);
196
+
197
+ /* do the stemming process: */
198
+ stem_file(*stemmer, f_in, f_out);
199
+ #endif
170
200
 
171
201
  return 0;
172
202
  }
@@ -45,8 +45,8 @@ class SnowballProgram {
45
45
  cursor = 0;
46
46
  limit = current.length;
47
47
  limit_backward = 0;
48
- bra = cursor;
49
- ket = limit;
48
+ bra = 0;
49
+ ket = 0;
50
50
  }
51
51
 
52
52
  void copy_from(SnowballProgram other) {
@@ -1,6 +1,6 @@
1
1
  name: snowball
2
2
  description: This package provides stemmers generated from Snowball algorithms.
3
- version: 3.1.1 # SNOWBALL_VERSION
3
+ version: 3.2.0 # SNOWBALL_VERSION
4
4
  repository: https://github.com/snowballstem/snowball
5
5
  issue_tracker: https://github.com/snowballstem/snowball/issues
6
6
  topics:
@@ -6,6 +6,9 @@ available for download from:
6
6
 
7
7
  https://snowballstem.org/download.html
8
8
 
9
+ We aim to keep libstemmer compatible with ISO C90. We have CI tests which
10
+ build using modern compilers set to C90 mode, but if you hit compatibility
11
+ problems please report them.
9
12
 
10
13
  What is Stemming?
11
14
  -----------------
@@ -35,4 +35,4 @@ You can stem a word from PHP as follows:
35
35
  $stem = $stemmer->stemWord($word);
36
36
  printf("%s => %s\n", $word, $stem );
37
37
 
38
- // prints "compiled => compil"
38
+ // prints "compiled => compil"
@@ -1,11 +1,13 @@
1
1
  Snowball stemming library collection for Python
2
2
  ===============================================
3
3
 
4
- Python 3 (>= 3.3) is supported. We no longer support Python 2 as the Python
5
- developers stopped supporting it at the start of 2020. Snowball 2.1.0 was the
6
- last release to officially support Python 2; Snowball 3.0.1 was the last
7
- release which had the code to support Python 2, but we were no longer testing
8
- it.
4
+ Python >= 3.3 is supported, though the oldest version we currently test in CI
5
+ is Python 3.8.
6
+
7
+ We no longer support Python 2 as the Python developers stopped supporting it at
8
+ the start of 2020. Snowball 2.1.0 was the last release to officially support
9
+ Python 2; Snowball 3.0.1 was the last release which had the code to support
10
+ Python 2, but we were no longer testing it.
9
11
 
10
12
  What is Stemming?
11
13
  -----------------
@@ -69,7 +71,7 @@ Snowball's ``libstemmer_c`` and should provide results 100% compatible to
69
71
  **snowballstemmer**.
70
72
 
71
73
  **PyStemmer** is faster because it wraps generated C versions of the stemmers;
72
- **snowballstemmer** uses generate Python code and is slower but offers a pure
74
+ **snowballstemmer** uses generated Python code and is slower, but offers a pure
73
75
  Python solution.
74
76
 
75
77
  If PyStemmer is installed, ``snowballstemmer.stemmer`` returns a ``PyStemmer``
@@ -2,16 +2,15 @@
2
2
  * line interface for stemming using any of the algorithms provided.
3
3
  */
4
4
 
5
+ #ifdef _MSC_VER
6
+ # define _CRT_SECURE_NO_WARNINGS // Suppress stupid warning about fopen().
7
+ #endif
8
+
5
9
  #include <stdio.h>
6
10
  #include <stdlib.h> /* for malloc, free */
7
11
  #include <string.h> /* for memmove */
8
12
  #include <ctype.h> /* for isupper, tolower */
9
13
 
10
- #ifdef __cplusplus
11
- // Support compiling as C++ to test code generated by `snowball -c++`.
12
- # include <exception>
13
- #endif
14
-
15
14
  #include "libstemmer.h"
16
15
 
17
16
  const char * progname;
@@ -119,9 +118,6 @@ usage(int n)
119
118
 
120
119
  int
121
120
  main(int argc, char * argv[])
122
- #ifdef __cplusplus
123
- try
124
- #endif
125
121
  {
126
122
  const char * in = NULL;
127
123
  const char * out = NULL;
@@ -211,9 +207,3 @@ try
211
207
 
212
208
  return 0;
213
209
  }
214
- #ifdef __cplusplus
215
- catch (const std::exception& e) {
216
- fprintf(stderr, "Exception: %s\n", e.what());
217
- exit(1);
218
- }
219
- #endif
@@ -1,7 +1,7 @@
1
1
  package snowball
2
2
 
3
3
  import (
4
- "log"
4
+ "fmt"
5
5
  "strings"
6
6
  "unicode/utf8"
7
7
  )
@@ -38,7 +38,7 @@ func (env *Env) SetCurrent(s string) {
38
38
  env.Limit = len(s)
39
39
  env.LimitBackward = 0
40
40
  env.Bra = 0
41
- env.Ket = len(s)
41
+ env.Ket = 0
42
42
  }
43
43
 
44
44
  func (env *Env) ReplaceS(bra, ket int, s string) int32 {
@@ -463,8 +463,20 @@ func (env *Env) FindAmongB(amongs []*Among, ctx interface{}) int32 {
463
463
  }
464
464
  }
465
465
 
466
- func (env *Env) Debug(count, lineNumber int) {
467
- log.Printf("snowball debug, count: %d, line: %d", count, lineNumber)
466
+ func (env *Env) Debug(n, line int) {
467
+ length := len(env.current)
468
+ fmt.Printf("%3d (line %4d): [%d]'", n, line, length)
469
+ for i := 0; i <= length; i++ {
470
+ if env.LimitBackward == i { fmt.Print("{") }
471
+ if env.Bra == i { fmt.Print("[") }
472
+ if env.Cursor == i { fmt.Print("|") }
473
+ if env.Ket == i { fmt.Print("]") }
474
+ if env.Limit == i { fmt.Print("}") }
475
+ if (i < length) {
476
+ if env.current[i] == 0 { fmt.Print("#") } else { fmt.Print(env.current[i : i + 1]) }
477
+ }
478
+ }
479
+ fmt.Println("'")
468
480
  }
469
481
 
470
482
  func (env *Env) Clone() *Env {
@@ -7,9 +7,6 @@ extern "C" {
7
7
  struct sb_stemmer;
8
8
  typedef unsigned char sb_symbol;
9
9
 
10
- /* FIXME - should be able to get a version number for each stemming
11
- * algorithm (which will be incremented each time the output changes). */
12
-
13
10
  /** Returns an array of the names of the available stemming algorithms.
14
11
  * Note that these are the canonical names - aliases (ie, other names for
15
12
  * the same algorithm) will not be included in the list.
@@ -12,8 +12,8 @@ public class SnowballProgram {
12
12
  cursor = 0;
13
13
  length = limit = 0;
14
14
  limit_backward = 0;
15
- bra = cursor;
16
- ket = limit;
15
+ bra = 0;
16
+ ket = 0;
17
17
  }
18
18
 
19
19
  /**
@@ -42,8 +42,8 @@ public class SnowballProgram {
42
42
  cursor = 0;
43
43
  this.length = limit = length;
44
44
  limit_backward = 0;
45
- bra = cursor;
46
- ket = limit;
45
+ bra = 0;
46
+ ket = 0;
47
47
  }
48
48
 
49
49
  /**
@@ -20,8 +20,8 @@ export default class BaseStemmer {
20
20
  this.c = 0;
21
21
  this.limit = this.current.length;
22
22
  this.limit_backward = 0;
23
- this.bra = this.c;
24
- this.ket = this.limit;
23
+ this.bra = 0;
24
+ this.ket = 0;
25
25
  }
26
26
 
27
27
  /**
@@ -228,7 +228,7 @@ export default class BaseStemmer {
228
228
 
229
229
  /**
230
230
  * @param {Array<Array<string|number>>} v
231
- * @param {?function(): boolean} call_among_func
231
+ * @param {function(): boolean} [call_among_func]
232
232
  * @return {number}
233
233
  */
234
234
  find_among(v, call_among_func) {
@@ -250,15 +250,13 @@ export default class BaseStemmer {
250
250
  let common = common_i < common_j ? common_i : common_j; // smaller
251
251
  // w[0]: string, w[1]: result, w[2]: substring_i (optional), w[3]: function (optional)
252
252
  const w = v[k];
253
- let i2;
254
- // @ts-expect-error: w[0] always string.
255
- for (i2 = common; i2 < w[0].length; i2++) {
253
+ const s = /**@type{string}*/ (w[0]);
254
+ for (let i2 = common; i2 < s.length; i2++) {
256
255
  if (c + common === l) {
257
256
  diff = -1;
258
257
  break;
259
258
  }
260
- // @ts-expect-error: w[0] always string.
261
- diff = this.current.charCodeAt(c + common) - w[0].charCodeAt(i2);
259
+ diff = this.current.charCodeAt(c + common) - s.charCodeAt(i2);
262
260
  if (diff !== 0) break;
263
261
  common++;
264
262
  }
@@ -283,33 +281,28 @@ export default class BaseStemmer {
283
281
  }
284
282
  while (true) {
285
283
  const w = v[i];
286
- // @ts-expect-error: w[0] always string.
287
- if (common_i >= w[0].length) {
288
- // @ts-expect-error: w[0] always string.
289
- this.c = c + w[0].length;
290
- // @ts-expect-error: w[1] always number.
291
- if (w.length < 4) return w[1];
292
- // @ts-expect-error: w[3] always number.
293
- this.af = w[3];
284
+ const len = /**@type {string}*/ (w[0]).length;
285
+ if (common_i >= len) {
286
+ this.c = c + len;
287
+ if (w.length < 4) return /**@type {number}*/ (w[1]);
288
+ this.af = /**@type {number}*/ (w[3]);
294
289
  // @ts-expect-error: call_among_func never null here.
295
290
  if (call_among_func.call(this)) {
296
- // @ts-expect-error: w[0] always string.
297
- this.c = c + w[0].length;
298
- // @ts-expect-error: w[3] always number.
299
- return w[1];
291
+ this.c = c + len;
292
+ return /**@type {number}*/ (w[1]);
300
293
  }
301
294
  }
302
295
  // Tests for undefined (if w.length < 2) or 0.
303
296
  if (!w[2]) return 0;
304
- // @ts-expect-error: w[2] always number.
305
- i -= w[2];
297
+ i -= /**@type {number}*/ (w[2]);
306
298
  }
307
299
  }
308
300
 
309
301
  // find_among_b is for backwards processing. Same comments apply
310
302
  /**
311
303
  * @param {Array<Array<string|number>>} v
312
- * @param {?function(): boolean} call_among_func
304
+ * @param {function(): boolean} [call_among_func]
305
+ * @return {number}
313
306
  */
314
307
  find_among_b(v, call_among_func) {
315
308
  /** @protected */
@@ -329,15 +322,13 @@ export default class BaseStemmer {
329
322
  let diff = 0;
330
323
  let common = common_i < common_j ? common_i : common_j;
331
324
  const w = v[k];
332
- let i2;
333
- // @ts-expect-error: w[0] always string.
334
- for (i2 = w[0].length - 1 - common; i2 >= 0; i2--) {
325
+ const s = /**@type{string}*/ (w[0]);
326
+ for (let i2 = s.length - 1 - common; i2 >= 0; i2--) {
335
327
  if (c - common === lb) {
336
328
  diff = -1;
337
329
  break;
338
330
  }
339
- // @ts-expect-error: w[0] always string.
340
- diff = this.current.charCodeAt(c - 1 - common) - w[0].charCodeAt(i2);
331
+ diff = this.current.charCodeAt(c - 1 - common) - s.charCodeAt(i2);
341
332
  if (diff !== 0) break;
342
333
  common++;
343
334
  }
@@ -357,24 +348,20 @@ export default class BaseStemmer {
357
348
  }
358
349
  while (true) {
359
350
  const w = v[i];
360
- // @ts-expect-error: w[0] always string.
361
- if (common_i >= w[0].length) {
362
- // @ts-expect-error: w[0] always string.
363
- this.c = c - w[0].length;
364
- if (w.length < 4) return w[1];
365
- // @ts-expect-error: w[3] always number.
366
- this.af = w[3];
351
+ const len = /**@type {string}*/ (w[0]).length;
352
+ if (common_i >= len) {
353
+ this.c = c - len;
354
+ if (w.length < 4) return /**@type {number}*/ (w[1]);
355
+ this.af = /**@type {number}*/ (w[3]);
367
356
  // @ts-expect-error: call_among_func never null here.
368
357
  if (call_among_func.call(this)) {
369
- // @ts-expect-error: w[0] always string.
370
- this.c = c - w[0].length;
371
- return w[1];
358
+ this.c = c - len;
359
+ return /**@type {number}*/ (w[1]);
372
360
  }
373
361
  }
374
362
  // Tests for undefined (if w.length < 2) or 0.
375
363
  if (!w[2]) return 0;
376
- // @ts-expect-error: w[2] always number.
377
- i -= w[2];
364
+ i -= /**@type {number}*/ (w[2]);
378
365
  }
379
366
  }
380
367
 
@@ -1,3 +1,4 @@
1
+ import { Buffer } from 'node:buffer';
1
2
  import fs from 'node:fs';
2
3
  import process from 'node:process';
3
4
  import readline from 'node:readline';
@@ -19,8 +20,9 @@ The output file consists of the stemmed words, one per line.
19
20
  }
20
21
 
21
22
  {
22
- let input = '';
23
- let output = '';
23
+ let input;
24
+ let output;
25
+ /**@type {BufferEncoding}*/
24
26
  let encoding = 'utf8';
25
27
  let language = 'English';
26
28
  let usage_error = false;
@@ -45,7 +47,7 @@ The output file consists of the stemmed words, one per line.
45
47
  usage_error = true;
46
48
  break;
47
49
  }
48
- language = argv.shift();
50
+ language = /**@type {string}*/ (argv.shift());
49
51
  break;
50
52
  case "-i":
51
53
  if (argv.length === 0)
@@ -69,7 +71,16 @@ The output file consists of the stemmed words, one per line.
69
71
  usage_error = true;
70
72
  break;
71
73
  }
72
- encoding = argv.shift();
74
+ {
75
+ const enc = /**@type {string}*/ (argv.shift());
76
+ if (!Buffer.isEncoding(enc))
77
+ {
78
+ console.log('Unknown character encoding: ' + enc + '\n');
79
+ usage_error = true;
80
+ break;
81
+ }
82
+ encoding = enc;
83
+ }
73
84
  break;
74
85
  default:
75
86
  console.log('Unknown command line option: ' + arg + '\n');
@@ -85,13 +96,13 @@ The output file consists of the stemmed words, one per line.
85
96
 
86
97
  const stemmer = await create(language);
87
98
  let istream, ostream;
88
- if (input !== '') {
99
+ if (input !== undefined) {
89
100
  istream = fs.createReadStream(input, encoding);
90
101
  } else {
91
102
  istream = process.stdin;
92
103
  if (istream.setEncoding) istream.setEncoding(encoding);
93
104
  }
94
- if (output !== '') {
105
+ if (output !== undefined) {
95
106
  ostream = fs.createWriteStream(output, encoding);
96
107
  } else {
97
108
  ostream = process.stdout;
@@ -101,8 +112,17 @@ The output file consists of the stemmed words, one per line.
101
112
  stemming(stemmer, istream, ostream);
102
113
  }
103
114
 
104
- // function stemming (stemmer : Stemmer, input : Stream, output : Stream) {
105
- function stemming (stemmer, input, output) {
115
+ /**
116
+ * @typedef {object} Stemmer
117
+ * @property {function(string): string} stemWord
118
+ */
119
+
120
+ /**
121
+ * @param {Stemmer} stemmer
122
+ * @param {NodeJS.ReadableStream} input
123
+ * @param {NodeJS.WritableStream} output
124
+ */
125
+ function stemming(stemmer, input, output) {
106
126
  const lines = readline.createInterface({
107
127
  input: input,
108
128
  terminal: false
@@ -112,13 +132,16 @@ function stemming (stemmer, input, output) {
112
132
  });
113
133
  }
114
134
 
115
- async function create (name) {
135
+ /**
136
+ * @param {string} name
137
+ * @return {Promise<Stemmer>} name
138
+ */
139
+ async function create(name) {
116
140
  const lc_name = name.toLowerCase();
117
141
  if (/\W/.test(lc_name) || lc_name === 'base') {
118
142
  console.log('Unknown stemming language: ' + name + '\n');
119
143
  usage();
120
144
  process.exit(1);
121
- return;
122
145
  }
123
146
  const filename = `../js_out/${lc_name}-stemmer.js`;
124
147
  try {
@@ -127,5 +150,6 @@ async function create (name) {
127
150
  return new stemmerModule.default();
128
151
  } catch (error) {
129
152
  console.error(error);
153
+ process.exit(1);
130
154
  }
131
155
  }