TraceLab Component Library
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Properties
RussianStemmer.cs
Go to the documentation of this file.
1 /*
2  * Port of Snowball stemmers on C#
3  * Original stemmers can be found on http://snowball.tartarus.org
4  * Licence still BSD: http://snowball.tartarus.org/license.php
5  *
6  * Most of stemmers are ported from Java by Iveonik Systems ltd. (www.iveonik.com)
7  */
8 using System;
9 using System.Collections.Generic;
10 using System.Text;
11 
12 namespace TraceLab.Components.DevelopmentKit.Preprocessors.Stemmers.Snowball.Languages
13 {
18  {
19  private readonly static RussianStemmer methodObject = new RussianStemmer();
20 
21  private readonly static Among[] a_0 =
22  {
23  new Among ( "\u0432", -1, 1, null ),
24  new Among ( "\u0438\u0432", 0, 2, null ),
25  new Among ( "\u044B\u0432", 0, 2, null ),
26  new Among ( "\u0432\u0448\u0438", -1, 1, null ),
27  new Among ( "\u0438\u0432\u0448\u0438", 3, 2, null ),
28  new Among ( "\u044B\u0432\u0448\u0438", 3, 2, null ),
29  new Among ( "\u0432\u0448\u0438\u0441\u044C", -1, 1, null ),
30  new Among ( "\u0438\u0432\u0448\u0438\u0441\u044C", 6, 2, null ),
31  new Among ( "\u044B\u0432\u0448\u0438\u0441\u044C", 6, 2, null )
32  };
33 
34 
35  private readonly static Among[] a_1 =
36  {
37  new Among ( "\u0435\u0435", -1, 1, null ),
38  new Among ( "\u0438\u0435", -1, 1, null ),
39  new Among ( "\u043E\u0435", -1, 1, null ),
40  new Among ( "\u044B\u0435", -1, 1, null ),
41  new Among ( "\u0438\u043C\u0438", -1, 1, null ),
42  new Among ( "\u044B\u043C\u0438", -1, 1, null ),
43  new Among ( "\u0435\u0439", -1, 1, null ),
44  new Among ( "\u0438\u0439", -1, 1, null ),
45  new Among ( "\u043E\u0439", -1, 1, null ),
46  new Among ( "\u044B\u0439", -1, 1, null ),
47  new Among ( "\u0435\u043C", -1, 1, null ),
48  new Among ( "\u0438\u043C", -1, 1, null ),
49  new Among ( "\u043E\u043C", -1, 1, null ),
50  new Among ( "\u044B\u043C", -1, 1, null ),
51  new Among ( "\u0435\u0433\u043E", -1, 1, null ),
52  new Among ( "\u043E\u0433\u043E", -1, 1, null ),
53  new Among ( "\u0435\u043C\u0443", -1, 1, null ),
54  new Among ( "\u043E\u043C\u0443", -1, 1, null ),
55  new Among ( "\u0438\u0445", -1, 1, null ),
56  new Among ( "\u044B\u0445", -1, 1, null ),
57  new Among ( "\u0435\u044E", -1, 1, null ),
58  new Among ( "\u043E\u044E", -1, 1, null ),
59  new Among ( "\u0443\u044E", -1, 1, null ),
60  new Among ( "\u044E\u044E", -1, 1, null ),
61  new Among ( "\u0430\u044F", -1, 1, null ),
62  new Among ( "\u044F\u044F", -1, 1, null )
63  };
64 
65  private readonly static Among[] a_2 =
66  {
67  new Among ( "\u0435\u043C", -1, 1, null ),
68  new Among ( "\u043D\u043D", -1, 1, null ),
69  new Among ( "\u0432\u0448", -1, 1, null ),
70  new Among ( "\u0438\u0432\u0448", 2, 2, null ),
71  new Among ( "\u044B\u0432\u0448", 2, 2, null ),
72  new Among ( "\u0449", -1, 1, null ),
73  new Among ( "\u044E\u0449", 5, 1, null ),
74  new Among ( "\u0443\u044E\u0449", 6, 2, null )
75  };
76 
77 
78  private readonly static Among[] a_3 =
79  {
80  new Among ( "\u0441\u044C", -1, 1, null ),
81  new Among ( "\u0441\u044F", -1, 1, null )
82  };
83 
84 
85  private readonly static Among[] a_4 =
86  {
87  new Among ( "\u043B\u0430", -1, 1, null ),
88  new Among ( "\u0438\u043B\u0430", 0, 2, null ),
89  new Among ( "\u044B\u043B\u0430", 0, 2, null ),
90  new Among ( "\u043D\u0430", -1, 1, null ),
91  new Among ( "\u0435\u043D\u0430", 3, 2, null ),
92  new Among ( "\u0435\u0442\u0435", -1, 1, null ),
93  new Among ( "\u0438\u0442\u0435", -1, 2, null ),
94  new Among ( "\u0439\u0442\u0435", -1, 1, null ),
95  new Among ( "\u0435\u0439\u0442\u0435", 7, 2, null ),
96  new Among ( "\u0443\u0439\u0442\u0435", 7, 2, null ),
97  new Among ( "\u043B\u0438", -1, 1, null ),
98  new Among ( "\u0438\u043B\u0438", 10, 2, null ),
99  new Among ( "\u044B\u043B\u0438", 10, 2, null ),
100  new Among ( "\u0439", -1, 1, null ),
101  new Among ( "\u0435\u0439", 13, 2, null ),
102  new Among ( "\u0443\u0439", 13, 2, null ),
103  new Among ( "\u043B", -1, 1, null ),
104  new Among ( "\u0438\u043B", 16, 2, null ),
105  new Among ( "\u044B\u043B", 16, 2, null ),
106  new Among ( "\u0435\u043C", -1, 1, null ),
107  new Among ( "\u0438\u043C", -1, 2, null ),
108  new Among ( "\u044B\u043C", -1, 2, null ),
109  new Among ( "\u043D", -1, 1, null ),
110  new Among ( "\u0435\u043D", 22, 2, null ),
111  new Among ( "\u043B\u043E", -1, 1, null ),
112  new Among ( "\u0438\u043B\u043E", 24, 2, null ),
113  new Among ( "\u044B\u043B\u043E", 24, 2, null ),
114  new Among ( "\u043D\u043E", -1, 1, null ),
115  new Among ( "\u0435\u043D\u043E", 27, 2, null ),
116  new Among ( "\u043D\u043D\u043E", 27, 1, null ),
117  new Among ( "\u0435\u0442", -1, 1, null ),
118  new Among ( "\u0443\u0435\u0442", 30, 2, null ),
119  new Among ( "\u0438\u0442", -1, 2, null ),
120  new Among ( "\u044B\u0442", -1, 2, null ),
121  new Among ( "\u044E\u0442", -1, 1, null ),
122  new Among ( "\u0443\u044E\u0442", 34, 2, null ),
123  new Among ( "\u044F\u0442", -1, 2, null ),
124  new Among ( "\u043D\u044B", -1, 1, null ),
125  new Among ( "\u0435\u043D\u044B", 37, 2, null ),
126  new Among ( "\u0442\u044C", -1, 1, null ),
127  new Among ( "\u0438\u0442\u044C", 39, 2, null ),
128  new Among ( "\u044B\u0442\u044C", 39, 2, null ),
129  new Among ( "\u0435\u0448\u044C", -1, 1, null ),
130  new Among ( "\u0438\u0448\u044C", -1, 2, null ),
131  new Among ( "\u044E", -1, 2, null ),
132  new Among ( "\u0443\u044E", 44, 2, null )
133  };
134 
135 
136  private readonly static Among[] a_5 =
137  {
138  new Among ( "\u0430", -1, 1, null ),
139  new Among ( "\u0435\u0432", -1, 1, null ),
140  new Among ( "\u043E\u0432", -1, 1, null ),
141  new Among ( "\u0435", -1, 1, null ),
142  new Among ( "\u0438\u0435", 3, 1, null ),
143  new Among ( "\u044C\u0435", 3, 1, null ),
144  new Among ( "\u0438", -1, 1, null ),
145  new Among ( "\u0435\u0438", 6, 1, null ),
146  new Among ( "\u0438\u0438", 6, 1, null ),
147  new Among ( "\u0430\u043C\u0438", 6, 1, null ),
148  new Among ( "\u044F\u043C\u0438", 6, 1, null ),
149  new Among ( "\u0438\u044F\u043C\u0438", 10, 1, null ),
150  new Among ( "\u0439", -1, 1, null ),
151  new Among ( "\u0435\u0439", 12, 1, null ),
152  new Among ( "\u0438\u0435\u0439", 13, 1, null ),
153  new Among ( "\u0438\u0439", 12, 1, null ),
154  new Among ( "\u043E\u0439", 12, 1, null ),
155  new Among ( "\u0430\u043C", -1, 1, null ),
156  new Among ( "\u0435\u043C", -1, 1, null ),
157  new Among ( "\u0438\u0435\u043C", 18, 1, null ),
158  new Among ( "\u043E\u043C", -1, 1, null ),
159  new Among ( "\u044F\u043C", -1, 1, null ),
160  new Among ( "\u0438\u044F\u043C", 21, 1, null ),
161  new Among ( "\u043E", -1, 1, null ),
162  new Among ( "\u0443", -1, 1, null ),
163  new Among ( "\u0430\u0445", -1, 1, null ),
164  new Among ( "\u044F\u0445", -1, 1, null ),
165  new Among ( "\u0438\u044F\u0445", 26, 1, null ),
166  new Among ( "\u044B", -1, 1, null ),
167  new Among ( "\u044C", -1, 1, null ),
168  new Among ( "\u044E", -1, 1, null ),
169  new Among ( "\u0438\u044E", 30, 1, null ),
170  new Among ( "\u044C\u044E", 30, 1, null ),
171  new Among ( "\u044F", -1, 1, null ),
172  new Among ( "\u0438\u044F", 33, 1, null ),
173  new Among ( "\u044C\u044F", 33, 1, null )
174  };
175 
176 
177  private readonly static Among[] a_6 =
178  {
179  new Among ( "\u043E\u0441\u0442", -1, 1, null ),
180  new Among ( "\u043E\u0441\u0442\u044C", -1, 1, null )
181  };
182 
183 
184  private readonly static Among[] a_7 =
185  {
186  new Among ( "\u0435\u0439\u0448\u0435", -1, 1, null ),
187  new Among ( "\u043D", -1, 2, null ),
188  new Among ( "\u0435\u0439\u0448", -1, 1, null ),
189  new Among ( "\u044C", -1, 3, null )
190  };
191 
192 
193  private static readonly char[] g_v = { (char)33, (char)65, (char)8, (char)232 };
194 
195  private int I_p2;
196  private int I_pV;
197 
198 
199  private void copy_from(RussianStemmer other)
200  {
201  I_p2 = other.I_p2;
202  I_pV = other.I_pV;
203  copy_from(other);
204  }
205 
206 
207  private bool r_mark_regions()
208  {
209  bool root = false;
210  bool subroot = false;
211  int v_1;
212 
213  // (, line 57
214 
215  I_pV = limit;
216 
217  I_p2 = limit;
218 
219  // do, line 61
220 
221  v_1 = cursor;
222 
223  do
224  {
225  // (, line 61
226  // gopast, line 62
227  while (true)
228  {
229  do
230  {
231  if (!(in_grouping(g_v, 1072, 1103)))
232  {
233  break;
234  }
235  subroot = true;
236  if (subroot) break;
237  } while (false);
238 
239  if (subroot) break;
240 
241  if (cursor >= limit)
242  {
243  root = true;
244  break;
245  }
246  cursor++;
247  }
248 
249 
250  if (root) break;
251  root = false;
252  subroot = false;
253  // setmark pV, line 62
254  I_pV = cursor;
255  // gopast, line 62
256  while (true)
257  {
258  do
259  {
260  if (!(out_grouping(g_v, 1072, 1103)))
261  {
262  break;
263  }
264  subroot = true;
265  if (subroot) break;
266  } while (false);
267 
268  if (subroot) break;
269 
270  if (cursor >= limit)
271  {
272  root = true;
273  break;
274  }
275  cursor++;
276  }
277 
278  if (root) break;
279  root = false;
280  subroot = false;
281  // gopast, line 63
282  while (true)
283  {
284  do
285  {
286  if (!(in_grouping(g_v, 1072, 1103)))
287  {
288  break;
289  }
290  subroot = true;
291  if (subroot) break;
292  } while (false);
293 
294  if (subroot) break;
295  if (cursor >= limit)
296  {
297  root = true;
298  break;
299  }
300  cursor++;
301  }
302 
303  if (root) break;
304  root = false;
305  subroot = false;
306  // gopast, line 63
307  while (true)
308  {
309  do
310  {
311  if (!(out_grouping(g_v, 1072, 1103)))
312  {
313  break;
314  }
315  subroot = true;
316  if (subroot) break;
317  } while (false);
318 
319  if (subroot) break;
320 
321  if (cursor >= limit)
322  {
323  root = true;
324  break;
325  }
326  cursor++;
327  }
328  if (root) break;
329  // setmark p2, line 63
330  I_p2 = cursor;
331  } while (false);
332  cursor = v_1;
333  return true;
334  }
335 
336  private bool r_R2()
337  {
338  if (!(I_p2 <= cursor))
339  {
340  return false;
341  }
342  return true;
343  }
344 
345  private bool r_perfective_gerund()
346  {
347  bool subroot = false;
348  int among_var;
349  int v_1;
350  // (, line 71
351  // [, line 72
352  ket = cursor;
353  // substring, line 72
354  among_var = find_among_b(a_0, 9);
355  if (among_var == 0)
356  {
357  return false;
358  }
359  // ], line 72
360  bra = cursor;
361  switch (among_var)
362  {
363  case 0:
364  return false;
365  case 1:
366  // (, line 76
367  // or, line 76
368  do
369  {
370  v_1 = limit - cursor;
371  do
372  {
373  // literal, line 76
374  if (!(eq_s_b(1, "\u0430")))
375  {
376  break;
377  }
378  subroot = true;
379  if (subroot) break;
380  } while (false);
381 
382  if (subroot) break;
383  cursor = limit - v_1;
384  // literal, line 76
385  if (!(eq_s_b(1, "\u044F")))
386  {
387  return false;
388  }
389  } while (false);
390  // delete, line 76
391  slice_del();
392  break;
393  case 2:
394  // (, line 83
395  // delete, line 83
396  slice_del();
397  break;
398  }
399  return true;
400  }
401 
402  private bool r_adjective()
403  {
404  int among_var;
405  // (, line 87
406  // [, line 88
407  ket = cursor;
408  // substring, line 88
409  among_var = find_among_b(a_1, 26);
410  if (among_var == 0)
411  {
412  return false;
413  }
414  // ], line 88
415  bra = cursor;
416  switch (among_var)
417  {
418  case 0:
419  return false;
420  case 1:
421  // (, line 97
422  // delete, line 97
423  slice_del();
424  break;
425  }
426  return true;
427  }
428 
429  private bool r_adjectival()
430  {
431  bool root = false;
432  bool subroot = false;
433  int among_var;
434  int v_1;
435  int v_2;
436  // (, line 101
437  // call adjective, line 102
438  if (!r_adjective())
439  {
440  return false;
441  }
442  // try, line 109
443  v_1 = limit - cursor;
444  do
445  {
446  // (, line 109
447  // [, line 110
448  ket = cursor;
449  // substring, line 110
450  among_var = find_among_b(a_2, 8);
451  if (among_var == 0)
452  {
453  cursor = limit - v_1;
454  break;
455  }
456  // ], line 110
457  bra = cursor;
458  switch (among_var)
459  {
460  case 0:
461  cursor = limit - v_1;
462  goto default;
463  case 1:
464  // (, line 115
465  // or, line 115
466  do
467  {
468  v_2 = limit - cursor;
469  do
470  {
471  // literal, line 115
472  if (!(eq_s_b(1, "\u0430")))
473  {
474  break;
475  }
476  subroot = true;
477  if (subroot) break;
478  } while (false);
479  if (subroot) break;
480  cursor = limit - v_2;
481  // literal, line 115
482  if (!(eq_s_b(1, "\u044F")))
483  {
484  cursor = limit - v_1;
485  goto default;
486  }
487  } while (false);
488  // delete, line 115
489  slice_del();
490  break;
491  case 2:
492  // (, line 122
493  // delete, line 122
494  slice_del();
495  break;
496 
497  default: root = true; break;
498  }
499  if (root) break;
500  } while (false);
501  return true;
502  }
503 
504  private bool r_reflexive()
505  {
506  int among_var;
507  // (, line 128
508  // [, line 129
509  ket = cursor;
510  // substring, line 129
511  among_var = find_among_b(a_3, 2);
512  if (among_var == 0)
513  {
514  return false;
515  }
516  // ], line 129
517  bra = cursor;
518  switch (among_var)
519  {
520  case 0:
521  return false;
522  case 1:
523  // (, line 132
524  // delete, line 132
525  slice_del();
526  break;
527  }
528  return true;
529  }
530 
531  private bool r_verb()
532  {
533  bool subroot = false;
534  int among_var;
535  int v_1;
536  // (, line 136
537  // [, line 137
538  ket = cursor;
539  // substring, line 137
540  among_var = find_among_b(a_4, 46);
541  if (among_var == 0)
542  {
543  return false;
544  }
545  // ], line 137
546  bra = cursor;
547  switch (among_var)
548  {
549  case 0:
550  return false;
551  case 1:
552  // (, line 143
553  // or, line 143
554  do
555  {
556  v_1 = limit - cursor;
557  do
558  {
559  // literal, line 143
560  if (!(eq_s_b(1, "\u0430")))
561  {
562  break;
563  }
564  subroot = true;
565  if (subroot) break;
566  } while (false);
567 
568  if (subroot) break;
569 
570  cursor = limit - v_1;
571  // literal, line 143
572  if (!(eq_s_b(1, "\u044F")))
573  {
574  return false;
575  }
576  } while (false);
577  // delete, line 143
578  slice_del();
579  break;
580  case 2:
581  // (, line 151
582  // delete, line 151
583  slice_del();
584  break;
585  }
586  return true;
587  }
588 
589  private bool r_noun()
590  {
591  int among_var;
592  // (, line 159
593  // [, line 160
594  ket = cursor;
595  // substring, line 160
596  among_var = find_among_b(a_5, 36);
597  if (among_var == 0)
598  {
599  return false;
600  }
601  // ], line 160
602  bra = cursor;
603  switch (among_var)
604  {
605  case 0:
606  return false;
607  case 1:
608  // (, line 167
609  // delete, line 167
610  slice_del();
611  break;
612  }
613  return true;
614  }
615 
616  private bool r_derivational()
617  {
618  int among_var;
619  // (, line 175
620  // [, line 176
621  ket = cursor;
622  // substring, line 176
623  among_var = find_among_b(a_6, 2);
624  if (among_var == 0)
625  {
626  return false;
627  }
628  // ], line 176
629  bra = cursor;
630  // call R2, line 176
631  if (!r_R2())
632  {
633  return false;
634  }
635  switch (among_var)
636  {
637  case 0:
638  return false;
639  case 1:
640  // (, line 179
641  // delete, line 179
642  slice_del();
643  break;
644  }
645  return true;
646  }
647 
648  private bool r_tidy_up()
649  {
650  int among_var;
651  // (, line 183
652  // [, line 184
653  ket = cursor;
654  // substring, line 184
655  among_var = find_among_b(a_7, 4);
656  if (among_var == 0)
657  {
658  return false;
659  }
660  // ], line 184
661  bra = cursor;
662  switch (among_var)
663  {
664  case 0:
665  return false;
666  case 1:
667  // (, line 188
668  // delete, line 188
669  slice_del();
670  // [, line 189
671  ket = cursor;
672  // literal, line 189
673  if (!(eq_s_b(1, "\u043D")))
674  {
675  return false;
676  }
677  // ], line 189
678  bra = cursor;
679  // literal, line 189
680  if (!(eq_s_b(1, "\u043D")))
681  {
682  return false;
683  }
684  // delete, line 189
685  slice_del();
686  break;
687  case 2:
688  // (, line 192
689  // literal, line 192
690  if (!(eq_s_b(1, "\u043D")))
691  {
692  return false;
693  }
694  // delete, line 192
695  slice_del();
696  break;
697  case 3:
698  // (, line 194
699  // delete, line 194
700  slice_del();
701  break;
702  }
703  return true;
704  }
705 
710  public bool CanStem()
711  {
712  bool root = false;
713  bool subroot = false;
714  int v_1;
715  int v_2;
716  int v_3;
717  int v_4;
718  int v_5;
719  int v_6;
720  int v_7;
721  int v_8;
722  int v_9;
723  int v_10;
724  // (, line 199
725  // do, line 201
726  v_1 = cursor;
727  do
728  {
729  // call mark_regions, line 201
730  if (!r_mark_regions())
731  {
732  break;
733  }
734  } while (false);
735  cursor = v_1;
736  // backwards, line 202
737  limit_backward = cursor; cursor = limit;
738  // setlimit, line 202
739  v_2 = limit - cursor;
740  // tomark, line 202
741  if (cursor < I_pV)
742  {
743  return false;
744  }
745  cursor = I_pV;
746  v_3 = limit_backward;
747  limit_backward = cursor;
748  cursor = limit - v_2;
749  // (, line 202
750  // do, line 203
751  v_4 = limit - cursor;
752  do
753  {
754  // (, line 203
755  // or, line 204
756  do
757  {
758  v_5 = limit - cursor;
759  do
760  {
761  // call perfective_gerund, line 204
762  if (!r_perfective_gerund())
763  {
764  break;
765  }
766  subroot = true;
767  if (subroot) break;
768  } while (false);
769 
770  if (subroot) break;
771  cursor = limit - v_5;
772  // (, line 205
773  // try, line 205
774  v_6 = limit - cursor;
775  do
776  {
777  // call reflexive, line 205
778  if (!r_reflexive())
779  {
780  cursor = limit - v_6;
781  break;
782  }
783  } while (false);
784  // or, line 206
785  subroot = false;
786  do
787  {
788  v_7 = limit - cursor;
789  do
790  {
791  // call adjectival, line 206
792  if (!r_adjectival())
793  {
794  break;
795  }
796  subroot = true;
797  if (subroot) break;
798  } while (false);
799 
800  if (subroot) break;
801 
802  cursor = limit - v_7;
803  do
804  {
805  // call verb, line 206
806  if (!r_verb())
807  {
808  break;
809  }
810  subroot = true;
811  if (subroot) break;
812  } while (false);
813 
814  if (subroot) break;
815 
816  cursor = limit - v_7;
817  // call noun, line 206
818  if (!r_noun())
819  {
820  root = true;
821  break;
822  }
823  } while (false);
824 
825  if (root) break;
826  } while (false);
827 
828  if (root) break;
829  } while (false);
830  cursor = limit - v_4;
831 
832  root = false;
833  subroot = false;
834 
835  // try, line 209
836  v_8 = limit - cursor;
837  do
838  {
839  // (, line 209
840  // [, line 209
841  ket = cursor;
842  // literal, line 209
843  if (!(eq_s_b(1, "\u0438")))
844  {
845  cursor = limit - v_8;
846  break;
847  }
848  // ], line 209
849  bra = cursor;
850  // delete, line 209
851  slice_del();
852  } while (false);
853  // do, line 212
854  v_9 = limit - cursor;
855  do
856  {
857  // call derivational, line 212
858  if (!r_derivational())
859  {
860  break;
861  }
862  } while (false);
863  cursor = limit - v_9;
864  // do, line 213
865  v_10 = limit - cursor;
866  do
867  {
868  // call tidy_up, line 213
869  if (!r_tidy_up())
870  {
871  break;
872  }
873  } while (false);
874  cursor = limit - v_10;
875  limit_backward = v_3;
876  cursor = limit_backward;
877  return true;
878  }
879 
885  public string Stem(string s)
886  {
887  this.setCurrent(s.ToLowerInvariant());
888  this.CanStem();
889  return this.getCurrent();
890  }
891 
892 
893  }
894 }