1 package org.apache.lucene.analysis.el;
3 import org.apache.lucene.analysis.CharArraySet;
4 import org.apache.lucene.util.Version;
6 import java.util.Arrays;
9 * Licensed to the Apache Software Foundation (ASF) under one or more
10 * contributor license agreements. See the NOTICE file distributed with
11 * this work for additional information regarding copyright ownership.
12 * The ASF licenses this file to You under the Apache License, Version 2.0
13 * (the "License"); you may not use this file except in compliance with
14 * the License. You may obtain a copy of the License at
16 * http://www.apache.org/licenses/LICENSE-2.0
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
26 * A stemmer for Greek words, according to: <i>Development of a Stemmer for the
27 * Greek Language.</i> Georgios Ntais
29 * NOTE: Input is expected to be casefolded for Greek (including folding of final
30 * sigma to sigma), and with diacritics removed. This can be achieved with
31 * either {@link GreekLowerCaseFilter} or ICUFoldingFilter.
32 * @lucene.experimental
34 public class GreekStemmer {
35 public int stem(char s[], int len) {
36 if (len < 4) // too short
39 final int origLen = len;
40 // "short rules": if it hits one of these, it skips the "long list"
66 return rule22(s, len);
69 private int rule0(char s[], int len) {
70 if (len > 9 && (endsWith(s, len, "καθεστωτοσ")
71 || endsWith(s, len, "καθεστωτων")))
74 if (len > 8 && (endsWith(s, len, "γεγονοτοσ")
75 || endsWith(s, len, "γεγονοτων")))
78 if (len > 8 && endsWith(s, len, "καθεστωτα"))
81 if (len > 7 && (endsWith(s, len, "τατογιου")
82 || endsWith(s, len, "τατογιων")))
85 if (len > 7 && endsWith(s, len, "γεγονοτα"))
88 if (len > 7 && endsWith(s, len, "καθεστωσ"))
91 if (len > 6 && (endsWith(s, len, "σκαγιου"))
92 || endsWith(s, len, "σκαγιων")
93 || endsWith(s, len, "ολογιου")
94 || endsWith(s, len, "ολογιων")
95 || endsWith(s, len, "κρεατοσ")
96 || endsWith(s, len, "κρεατων")
97 || endsWith(s, len, "περατοσ")
98 || endsWith(s, len, "περατων")
99 || endsWith(s, len, "τερατοσ")
100 || endsWith(s, len, "τερατων"))
103 if (len > 6 && endsWith(s, len, "τατογια"))
106 if (len > 6 && endsWith(s, len, "γεγονοσ"))
109 if (len > 5 && (endsWith(s, len, "φαγιου")
110 || endsWith(s, len, "φαγιων")
111 || endsWith(s, len, "σογιου")
112 || endsWith(s, len, "σογιων")))
115 if (len > 5 && (endsWith(s, len, "σκαγια")
116 || endsWith(s, len, "ολογια")
117 || endsWith(s, len, "κρεατα")
118 || endsWith(s, len, "περατα")
119 || endsWith(s, len, "τερατα")))
122 if (len > 4 && (endsWith(s, len, "φαγια")
123 || endsWith(s, len, "σογια")
124 || endsWith(s, len, "φωτοσ")
125 || endsWith(s, len, "φωτων")))
128 if (len > 4 && (endsWith(s, len, "κρεασ")
129 || endsWith(s, len, "περασ")
130 || endsWith(s, len, "τερασ")))
133 if (len > 3 && endsWith(s, len, "φωτα"))
136 if (len > 2 && endsWith(s, len, "φωσ"))
142 private int rule1(char s[], int len) {
143 if (len > 4 && (endsWith(s, len, "αδεσ") || endsWith(s, len, "αδων"))) {
145 if (!(endsWith(s, len, "οκ") ||
146 endsWith(s, len, "μαμ") ||
147 endsWith(s, len, "μαν") ||
148 endsWith(s, len, "μπαμπ") ||
149 endsWith(s, len, "πατερ") ||
150 endsWith(s, len, "γιαγι") ||
151 endsWith(s, len, "νταντ") ||
152 endsWith(s, len, "κυρ") ||
153 endsWith(s, len, "θει") ||
154 endsWith(s, len, "πεθερ")))
155 len += 2; // add back -αδ
160 private int rule2(char s[], int len) {
161 if (len > 4 && (endsWith(s, len, "εδεσ") || endsWith(s, len, "εδων"))) {
163 if (endsWith(s, len, "οπ") ||
164 endsWith(s, len, "ιπ") ||
165 endsWith(s, len, "εμπ") ||
166 endsWith(s, len, "υπ") ||
167 endsWith(s, len, "γηπ") ||
168 endsWith(s, len, "δαπ") ||
169 endsWith(s, len, "κρασπ") ||
170 endsWith(s, len, "μιλ"))
171 len += 2; // add back -εδ
176 private int rule3(char s[], int len) {
177 if (len > 5 && (endsWith(s, len, "ουδεσ") || endsWith(s, len, "ουδων"))) {
179 if (endsWith(s, len, "αρκ") ||
180 endsWith(s, len, "καλιακ") ||
181 endsWith(s, len, "πεταλ") ||
182 endsWith(s, len, "λιχ") ||
183 endsWith(s, len, "πλεξ") ||
184 endsWith(s, len, "σκ") ||
185 endsWith(s, len, "σ") ||
186 endsWith(s, len, "φλ") ||
187 endsWith(s, len, "φρ") ||
188 endsWith(s, len, "βελ") ||
189 endsWith(s, len, "λουλ") ||
190 endsWith(s, len, "χν") ||
191 endsWith(s, len, "σπ") ||
192 endsWith(s, len, "τραγ") ||
193 endsWith(s, len, "φε"))
194 len += 3; // add back -ουδ
199 private static final CharArraySet exc4 = new CharArraySet(Version.LUCENE_31,
200 Arrays.asList("θ", "δ", "ελ", "γαλ", "ν", "π", "ιδ", "παρ"),
203 private int rule4(char s[], int len) {
204 if (len > 3 && (endsWith(s, len, "εωσ") || endsWith(s, len, "εων"))) {
206 if (exc4.contains(s, 0, len))
207 len++; // add back -ε
212 private int rule5(char s[], int len) {
213 if (len > 2 && endsWith(s, len, "ια")) {
215 if (endsWithVowel(s, len))
216 len++; // add back -ι
217 } else if (len > 3 && (endsWith(s, len, "ιου") || endsWith(s, len, "ιων"))) {
219 if (endsWithVowel(s, len))
220 len++; // add back -ι
225 private static final CharArraySet exc6 = new CharArraySet(Version.LUCENE_31,
226 Arrays.asList("αλ", "αδ", "ενδ", "αμαν", "αμμοχαλ", "ηθ", "ανηθ",
227 "αντιδ", "φυσ", "βρωμ", "γερ", "εξωδ", "καλπ", "καλλιν", "καταδ",
228 "μουλ", "μπαν", "μπαγιατ", "μπολ", "μποσ", "νιτ", "ξικ", "συνομηλ",
229 "πετσ", "πιτσ", "πικαντ", "πλιατσ", "ποστελν", "πρωτοδ", "σερτ",
230 "συναδ", "τσαμ", "υποδ", "φιλον", "φυλοδ", "χασ"),
233 private int rule6(char s[], int len) {
234 boolean removed = false;
235 if (len > 3 && (endsWith(s, len, "ικα") || endsWith(s, len, "ικο"))) {
238 } else if (len > 4 && (endsWith(s, len, "ικου") || endsWith(s, len, "ικων"))) {
244 if (endsWithVowel(s, len) || exc6.contains(s, 0, len))
245 len += 2; // add back -ικ
250 private static final CharArraySet exc7 = new CharArraySet(Version.LUCENE_31,
251 Arrays.asList("αναπ", "αποθ", "αποκ", "αποστ", "βουβ", "ξεθ", "ουλ",
252 "πεθ", "πικρ", "ποτ", "σιχ", "χ"),
255 private int rule7(char s[], int len) {
256 if (len == 5 && endsWith(s, len, "αγαμε"))
259 if (len > 7 && endsWith(s, len, "ηθηκαμε"))
261 else if (len > 6 && endsWith(s, len, "ουσαμε"))
263 else if (len > 5 && (endsWith(s, len, "αγαμε") ||
264 endsWith(s, len, "ησαμε") ||
265 endsWith(s, len, "ηκαμε")))
268 if (len > 3 && endsWith(s, len, "αμε")) {
270 if (exc7.contains(s, 0, len))
271 len += 2; // add back -αμ
277 private static final CharArraySet exc8a = new CharArraySet(Version.LUCENE_31,
278 Arrays.asList("τρ", "τσ"),
281 private static final CharArraySet exc8b = new CharArraySet(Version.LUCENE_31,
282 Arrays.asList("βετερ", "βουλκ", "βραχμ", "γ", "δραδουμ", "θ", "καλπουζ",
283 "καστελ", "κορμορ", "λαοπλ", "μωαμεθ", "μ", "μουσουλμ", "ν", "ουλ",
284 "π", "πελεκ", "πλ", "πολισ", "πορτολ", "σαρακατσ", "σουλτ",
285 "τσαρλατ", "ορφ", "τσιγγ", "τσοπ", "φωτοστεφ", "χ", "ψυχοπλ", "αγ",
286 "ορφ", "γαλ", "γερ", "δεκ", "διπλ", "αμερικαν", "ουρ", "πιθ",
287 "πουριτ", "σ", "ζωντ", "ικ", "καστ", "κοπ", "λιχ", "λουθηρ", "μαιντ",
288 "μελ", "σιγ", "σπ", "στεγ", "τραγ", "τσαγ", "φ", "ερ", "αδαπ",
289 "αθιγγ", "αμηχ", "ανικ", "ανοργ", "απηγ", "απιθ", "ατσιγγ", "βασ",
290 "βασκ", "βαθυγαλ", "βιομηχ", "βραχυκ", "διατ", "διαφ", "ενοργ",
291 "θυσ", "καπνοβιομηχ", "καταγαλ", "κλιβ", "κοιλαρφ", "λιβ",
292 "μεγλοβιομηχ", "μικροβιομηχ", "νταβ", "ξηροκλιβ", "ολιγοδαμ",
293 "ολογαλ", "πενταρφ", "περηφ", "περιτρ", "πλατ", "πολυδαπ", "πολυμηχ",
294 "στεφ", "ταβ", "τετ", "υπερηφ", "υποκοπ", "χαμηλοδαπ", "ψηλοταβ"),
297 private int rule8(char s[], int len) {
298 boolean removed = false;
300 if (len > 8 && endsWith(s, len, "ιουντανε")) {
303 } else if (len > 7 && endsWith(s, len, "ιοντανε") ||
304 endsWith(s, len, "ουντανε") ||
305 endsWith(s, len, "ηθηκανε")) {
308 } else if (len > 6 && endsWith(s, len, "ιοτανε") ||
309 endsWith(s, len, "οντανε") ||
310 endsWith(s, len, "ουσανε")) {
313 } else if (len > 5 && endsWith(s, len, "αγανε") ||
314 endsWith(s, len, "ησανε") ||
315 endsWith(s, len, "οτανε") ||
316 endsWith(s, len, "ηκανε")) {
321 if (removed && exc8a.contains(s, 0, len)) {
322 // add -αγαν (we removed > 4 chars so its safe)
330 if (len > 3 && endsWith(s, len, "ανε")) {
332 if (endsWithVowelNoY(s, len) || exc8b.contains(s, 0, len)) {
333 len += 2; // add back -αν
340 private static final CharArraySet exc9 = new CharArraySet(Version.LUCENE_31,
341 Arrays.asList("αβαρ", "βεν", "εναρ", "αβρ", "αδ", "αθ", "αν", "απλ",
342 "βαρον", "ντρ", "σκ", "κοπ", "μπορ", "νιφ", "παγ", "παρακαλ", "σερπ",
343 "σκελ", "συρφ", "τοκ", "υ", "δ", "εμ", "θαρρ", "θ"),
346 private int rule9(char s[], int len) {
347 if (len > 5 && endsWith(s, len, "ησετε"))
350 if (len > 3 && endsWith(s, len, "ετε")) {
352 if (exc9.contains(s, 0, len) ||
353 endsWithVowelNoY(s, len) ||
354 endsWith(s, len, "οδ") ||
355 endsWith(s, len, "αιρ") ||
356 endsWith(s, len, "φορ") ||
357 endsWith(s, len, "ταθ") ||
358 endsWith(s, len, "διαθ") ||
359 endsWith(s, len, "σχ") ||
360 endsWith(s, len, "ενδ") ||
361 endsWith(s, len, "ευρ") ||
362 endsWith(s, len, "τιθ") ||
363 endsWith(s, len, "υπερθ") ||
364 endsWith(s, len, "ραθ") ||
365 endsWith(s, len, "ενθ") ||
366 endsWith(s, len, "ροθ") ||
367 endsWith(s, len, "σθ") ||
368 endsWith(s, len, "πυρ") ||
369 endsWith(s, len, "αιν") ||
370 endsWith(s, len, "συνδ") ||
371 endsWith(s, len, "συν") ||
372 endsWith(s, len, "συνθ") ||
373 endsWith(s, len, "χωρ") ||
374 endsWith(s, len, "πον") ||
375 endsWith(s, len, "βρ") ||
376 endsWith(s, len, "καθ") ||
377 endsWith(s, len, "ευθ") ||
378 endsWith(s, len, "εκθ") ||
379 endsWith(s, len, "νετ") ||
380 endsWith(s, len, "ρον") ||
381 endsWith(s, len, "αρκ") ||
382 endsWith(s, len, "βαρ") ||
383 endsWith(s, len, "βολ") ||
384 endsWith(s, len, "ωφελ")) {
385 len += 2; // add back -ετ
392 private int rule10(char s[], int len) {
393 if (len > 5 && (endsWith(s, len, "οντασ") || endsWith(s, len, "ωντασ"))) {
395 if (len == 3 && endsWith(s, len, "αρχ")) {
396 len += 3; // add back *ντ
399 if (endsWith(s, len, "κρε")) {
400 len += 3; // add back *ντ
408 private int rule11(char s[], int len) {
409 if (len > 6 && endsWith(s, len, "ομαστε")) {
411 if (len == 2 && endsWith(s, len, "ον")) {
412 len += 5; // add back -ομαστ
414 } else if (len > 7 && endsWith(s, len, "ιομαστε")) {
416 if (len == 2 && endsWith(s, len, "ον")) {
428 private static final CharArraySet exc12a = new CharArraySet(Version.LUCENE_31,
429 Arrays.asList("π", "απ", "συμπ", "ασυμπ", "ακαταπ", "αμεταμφ"),
432 private static final CharArraySet exc12b = new CharArraySet(Version.LUCENE_31,
433 Arrays.asList("αλ", "αρ", "εκτελ", "ζ", "μ", "ξ", "παρακαλ", "αρ", "προ", "νισ"),
436 private int rule12(char s[], int len) {
437 if (len > 5 && endsWith(s, len, "ιεστε")) {
439 if (exc12a.contains(s, 0, len))
440 len += 4; // add back -ιεστ
443 if (len > 4 && endsWith(s, len, "εστε")) {
445 if (exc12b.contains(s, 0, len))
446 len += 3; // add back -εστ
452 private static final CharArraySet exc13 = new CharArraySet(Version.LUCENE_31,
453 Arrays.asList("διαθ", "θ", "παρακαταθ", "προσθ", "συνθ"),
456 private int rule13(char s[], int len) {
457 if (len > 6 && endsWith(s, len, "ηθηκεσ")) {
459 } else if (len > 5 && (endsWith(s, len, "ηθηκα") || endsWith(s, len, "ηθηκε"))) {
463 boolean removed = false;
465 if (len > 4 && endsWith(s, len, "ηκεσ")) {
468 } else if (len > 3 && (endsWith(s, len, "ηκα") || endsWith(s, len, "ηκε"))) {
473 if (removed && (exc13.contains(s, 0, len)
474 || endsWith(s, len, "σκωλ")
475 || endsWith(s, len, "σκουλ")
476 || endsWith(s, len, "ναρθ")
477 || endsWith(s, len, "σφ")
478 || endsWith(s, len, "οθ")
479 || endsWith(s, len, "πιθ"))) {
480 len += 2; // add back the -ηκ
486 private static final CharArraySet exc14 = new CharArraySet(Version.LUCENE_31,
487 Arrays.asList("φαρμακ", "χαδ", "αγκ", "αναρρ", "βρομ", "εκλιπ", "λαμπιδ",
488 "λεχ", "μ", "πατ", "ρ", "λ", "μεδ", "μεσαζ", "υποτειν", "αμ", "αιθ",
489 "ανηκ", "δεσποζ", "ενδιαφερ", "δε", "δευτερευ", "καθαρευ", "πλε",
493 private int rule14(char s[], int len) {
494 boolean removed = false;
496 if (len > 5 && endsWith(s, len, "ουσεσ")) {
499 } else if (len > 4 && (endsWith(s, len, "ουσα") || endsWith(s, len, "ουσε"))) {
504 if (removed && (exc14.contains(s, 0, len)
505 || endsWithVowel(s, len)
506 || endsWith(s, len, "ποδαρ")
507 || endsWith(s, len, "βλεπ")
508 || endsWith(s, len, "πανταχ")
509 || endsWith(s, len, "φρυδ")
510 || endsWith(s, len, "μαντιλ")
511 || endsWith(s, len, "μαλλ")
512 || endsWith(s, len, "κυματ")
513 || endsWith(s, len, "λαχ")
514 || endsWith(s, len, "ληγ")
515 || endsWith(s, len, "φαγ")
516 || endsWith(s, len, "ομ")
517 || endsWith(s, len, "πρωτ"))) {
518 len += 3; // add back -ουσ
524 private static final CharArraySet exc15a = new CharArraySet(Version.LUCENE_31,
525 Arrays.asList("αβαστ", "πολυφ", "αδηφ", "παμφ", "ρ", "ασπ", "αφ", "αμαλ",
526 "αμαλλι", "ανυστ", "απερ", "ασπαρ", "αχαρ", "δερβεν", "δροσοπ",
527 "ξεφ", "νεοπ", "νομοτ", "ολοπ", "ομοτ", "προστ", "προσωποπ", "συμπ",
528 "συντ", "τ", "υποτ", "χαρ", "αειπ", "αιμοστ", "ανυπ", "αποτ",
529 "αρτιπ", "διατ", "εν", "επιτ", "κροκαλοπ", "σιδηροπ", "λ", "ναυ",
530 "ουλαμ", "ουρ", "π", "τρ", "μ"),
533 private static final CharArraySet exc15b = new CharArraySet(Version.LUCENE_31,
534 Arrays.asList("ψοφ", "ναυλοχ"),
537 private int rule15(char s[], int len) {
538 boolean removed = false;
539 if (len > 4 && endsWith(s, len, "αγεσ")) {
542 } else if (len > 3 && (endsWith(s, len, "αγα") || endsWith(s, len, "αγε"))) {
548 final boolean cond1 = exc15a.contains(s, 0, len)
549 || endsWith(s, len, "οφ")
550 || endsWith(s, len, "πελ")
551 || endsWith(s, len, "χορτ")
552 || endsWith(s, len, "λλ")
553 || endsWith(s, len, "σφ")
554 || endsWith(s, len, "ρπ")
555 || endsWith(s, len, "φρ")
556 || endsWith(s, len, "πρ")
557 || endsWith(s, len, "λοχ")
558 || endsWith(s, len, "σμην");
560 final boolean cond2 = exc15b.contains(s, 0, len)
561 || endsWith(s, len, "κολλ");
564 len += 2; // add back -αγ
570 private static final CharArraySet exc16 = new CharArraySet(Version.LUCENE_31,
571 Arrays.asList("ν", "χερσον", "δωδεκαν", "ερημον", "μεγαλον", "επταν"),
574 private int rule16(char s[], int len) {
575 boolean removed = false;
576 if (len > 4 && endsWith(s, len, "ησου")) {
579 } else if (len > 3 && (endsWith(s, len, "ησε") || endsWith(s, len, "ησα"))) {
584 if (removed && exc16.contains(s, 0, len))
585 len += 2; // add back -ησ
590 private static final CharArraySet exc17 = new CharArraySet(Version.LUCENE_31,
591 Arrays.asList("ασβ", "σβ", "αχρ", "χρ", "απλ", "αειμν", "δυσχρ", "ευχρ", "κοινοχρ", "παλιμψ"),
594 private int rule17(char s[], int len) {
595 if (len > 4 && endsWith(s, len, "ηστε")) {
597 if (exc17.contains(s, 0, len))
598 len += 3; // add back the -ηστ
604 private static final CharArraySet exc18 = new CharArraySet(Version.LUCENE_31,
605 Arrays.asList("ν", "ρ", "σπι", "στραβομουτσ", "κακομουτσ", "εξων"),
608 private int rule18(char s[], int len) {
609 boolean removed = false;
611 if (len > 6 && (endsWith(s, len, "ησουνε") || endsWith(s, len, "ηθουνε"))) {
614 } else if (len > 4 && endsWith(s, len, "ουνε")) {
619 if (removed && exc18.contains(s, 0, len)) {
628 private static final CharArraySet exc19 = new CharArraySet(Version.LUCENE_31,
629 Arrays.asList("παρασουσ", "φ", "χ", "ωριοπλ", "αζ", "αλλοσουσ", "ασουσ"),
632 private int rule19(char s[], int len) {
633 boolean removed = false;
635 if (len > 6 && (endsWith(s, len, "ησουμε") || endsWith(s, len, "ηθουμε"))) {
638 } else if (len > 4 && endsWith(s, len, "ουμε")) {
643 if (removed && exc19.contains(s, 0, len)) {
652 private int rule20(char s[], int len) {
653 if (len > 5 && (endsWith(s, len, "ματων") || endsWith(s, len, "ματοσ")))
655 else if (len > 4 && endsWith(s, len, "ματα"))
660 private int rule21(char s[], int len) {
661 if (len > 9 && endsWith(s, len, "ιοντουσαν"))
664 if (len > 8 && (endsWith(s, len, "ιομασταν") ||
665 endsWith(s, len, "ιοσασταν") ||
666 endsWith(s, len, "ιουμαστε") ||
667 endsWith(s, len, "οντουσαν")))
670 if (len > 7 && (endsWith(s, len, "ιεμαστε") ||
671 endsWith(s, len, "ιεσαστε") ||
672 endsWith(s, len, "ιομουνα") ||
673 endsWith(s, len, "ιοσαστε") ||
674 endsWith(s, len, "ιοσουνα") ||
675 endsWith(s, len, "ιουνται") ||
676 endsWith(s, len, "ιουνταν") ||
677 endsWith(s, len, "ηθηκατε") ||
678 endsWith(s, len, "ομασταν") ||
679 endsWith(s, len, "οσασταν") ||
680 endsWith(s, len, "ουμαστε")))
683 if (len > 6 && (endsWith(s, len, "ιομουν") ||
684 endsWith(s, len, "ιονταν") ||
685 endsWith(s, len, "ιοσουν") ||
686 endsWith(s, len, "ηθειτε") ||
687 endsWith(s, len, "ηθηκαν") ||
688 endsWith(s, len, "ομουνα") ||
689 endsWith(s, len, "οσαστε") ||
690 endsWith(s, len, "οσουνα") ||
691 endsWith(s, len, "ουνται") ||
692 endsWith(s, len, "ουνταν") ||
693 endsWith(s, len, "ουσατε")))
696 if (len > 5 && (endsWith(s, len, "αγατε") ||
697 endsWith(s, len, "ιεμαι") ||
698 endsWith(s, len, "ιεται") ||
699 endsWith(s, len, "ιεσαι") ||
700 endsWith(s, len, "ιοταν") ||
701 endsWith(s, len, "ιουμα") ||
702 endsWith(s, len, "ηθεισ") ||
703 endsWith(s, len, "ηθουν") ||
704 endsWith(s, len, "ηκατε") ||
705 endsWith(s, len, "ησατε") ||
706 endsWith(s, len, "ησουν") ||
707 endsWith(s, len, "ομουν") ||
708 endsWith(s, len, "ονται") ||
709 endsWith(s, len, "ονταν") ||
710 endsWith(s, len, "οσουν") ||
711 endsWith(s, len, "ουμαι") ||
712 endsWith(s, len, "ουσαν")))
715 if (len > 4 && (endsWith(s, len, "αγαν") ||
716 endsWith(s, len, "αμαι") ||
717 endsWith(s, len, "ασαι") ||
718 endsWith(s, len, "αται") ||
719 endsWith(s, len, "ειτε") ||
720 endsWith(s, len, "εσαι") ||
721 endsWith(s, len, "εται") ||
722 endsWith(s, len, "ηδεσ") ||
723 endsWith(s, len, "ηδων") ||
724 endsWith(s, len, "ηθει") ||
725 endsWith(s, len, "ηκαν") ||
726 endsWith(s, len, "ησαν") ||
727 endsWith(s, len, "ησει") ||
728 endsWith(s, len, "ησεσ") ||
729 endsWith(s, len, "ομαι") ||
730 endsWith(s, len, "οταν")))
733 if (len > 3 && (endsWith(s, len, "αει") ||
734 endsWith(s, len, "εισ") ||
735 endsWith(s, len, "ηθω") ||
736 endsWith(s, len, "ησω") ||
737 endsWith(s, len, "ουν") ||
738 endsWith(s, len, "ουσ")))
741 if (len > 2 && (endsWith(s, len, "αν") ||
742 endsWith(s, len, "ασ") ||
743 endsWith(s, len, "αω") ||
744 endsWith(s, len, "ει") ||
745 endsWith(s, len, "εσ") ||
746 endsWith(s, len, "ησ") ||
747 endsWith(s, len, "οι") ||
748 endsWith(s, len, "οσ") ||
749 endsWith(s, len, "ου") ||
750 endsWith(s, len, "υσ") ||
751 endsWith(s, len, "ων")))
754 if (len > 1 && endsWithVowel(s, len))
760 private int rule22(char s[], int len) {
761 if (endsWith(s, len, "εστερ") ||
762 endsWith(s, len, "εστατ"))
765 if (endsWith(s, len, "οτερ") ||
766 endsWith(s, len, "οτατ") ||
767 endsWith(s, len, "υτερ") ||
768 endsWith(s, len, "υτατ") ||
769 endsWith(s, len, "ωτερ") ||
770 endsWith(s, len, "ωτατ"))
776 private boolean endsWith(char s[], int len, String suffix) {
777 final int suffixLen = suffix.length();
780 for (int i = suffixLen - 1; i >= 0; i--)
781 if (s[len -(suffixLen - i)] != suffix.charAt(i))
787 private boolean endsWithVowel(char s[], int len) {
804 private boolean endsWithVowelNoY(char s[], int len) {