~ubuntu-branches/debian/sid/golang-github-blevesearch-bleve/sid

« back to all changes in this revision

Viewing changes to analysis/lang/ckb/sorani_stemmer_filter.go

  • Committer: Package Import Robot
  • Author(s): Michael Lustfield
  • Date: 2017-03-30 16:06:03 UTC
  • Revision ID: package-import@ubuntu.com-20170330160603-0oogmb960l7918jx
Tags: upstream-0.5.0+git20170324.202.4702785f
Import upstream version 0.5.0+git20170324.202.4702785f

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//  Copyright (c) 2014 Couchbase, Inc.
 
2
//
 
3
// Licensed under the Apache License, Version 2.0 (the "License");
 
4
// you may not use this file except in compliance with the License.
 
5
// You may obtain a copy of the License at
 
6
//
 
7
//              http://www.apache.org/licenses/LICENSE-2.0
 
8
//
 
9
// Unless required by applicable law or agreed to in writing, software
 
10
// distributed under the License is distributed on an "AS IS" BASIS,
 
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
12
// See the License for the specific language governing permissions and
 
13
// limitations under the License.
 
14
 
 
15
package ckb
 
16
 
 
17
import (
 
18
        "bytes"
 
19
        "unicode/utf8"
 
20
 
 
21
        "github.com/blevesearch/bleve/analysis"
 
22
        "github.com/blevesearch/bleve/registry"
 
23
)
 
24
 
 
25
const StemmerName = "stemmer_ckb"
 
26
 
 
27
type SoraniStemmerFilter struct {
 
28
}
 
29
 
 
30
func NewSoraniStemmerFilter() *SoraniStemmerFilter {
 
31
        return &SoraniStemmerFilter{}
 
32
}
 
33
 
 
34
func (s *SoraniStemmerFilter) Filter(input analysis.TokenStream) analysis.TokenStream {
 
35
        for _, token := range input {
 
36
                // if not protected keyword, stem it
 
37
                if !token.KeyWord {
 
38
                        stemmed := stem(token.Term)
 
39
                        token.Term = stemmed
 
40
                }
 
41
        }
 
42
        return input
 
43
}
 
44
 
 
45
func stem(input []byte) []byte {
 
46
        inputLen := utf8.RuneCount(input)
 
47
 
 
48
        // postposition
 
49
        if inputLen > 5 && bytes.HasSuffix(input, []byte("دا")) {
 
50
                input = truncateRunes(input, 2)
 
51
                inputLen = utf8.RuneCount(input)
 
52
        } else if inputLen > 4 && bytes.HasSuffix(input, []byte("نا")) {
 
53
                input = truncateRunes(input, 1)
 
54
                inputLen = utf8.RuneCount(input)
 
55
        } else if inputLen > 6 && bytes.HasSuffix(input, []byte("ەوە")) {
 
56
                input = truncateRunes(input, 3)
 
57
                inputLen = utf8.RuneCount(input)
 
58
        }
 
59
 
 
60
        // possessive pronoun
 
61
        if inputLen > 6 &&
 
62
                (bytes.HasSuffix(input, []byte("مان")) ||
 
63
                        bytes.HasSuffix(input, []byte("یان")) ||
 
64
                        bytes.HasSuffix(input, []byte("تان"))) {
 
65
                input = truncateRunes(input, 3)
 
66
                inputLen = utf8.RuneCount(input)
 
67
        }
 
68
 
 
69
        // indefinite singular ezafe
 
70
        if inputLen > 6 && bytes.HasSuffix(input, []byte("ێکی")) {
 
71
                return truncateRunes(input, 3)
 
72
        } else if inputLen > 7 && bytes.HasSuffix(input, []byte("یەکی")) {
 
73
                return truncateRunes(input, 4)
 
74
        }
 
75
 
 
76
        if inputLen > 5 && bytes.HasSuffix(input, []byte("ێک")) {
 
77
                // indefinite singular
 
78
                return truncateRunes(input, 2)
 
79
        } else if inputLen > 6 && bytes.HasSuffix(input, []byte("یەک")) {
 
80
                // indefinite singular
 
81
                return truncateRunes(input, 3)
 
82
        } else if inputLen > 6 && bytes.HasSuffix(input, []byte("ەکە")) {
 
83
                // definite singular
 
84
                return truncateRunes(input, 3)
 
85
        } else if inputLen > 5 && bytes.HasSuffix(input, []byte("کە")) {
 
86
                // definite singular
 
87
                return truncateRunes(input, 2)
 
88
        } else if inputLen > 7 && bytes.HasSuffix(input, []byte("ەکان")) {
 
89
                // definite plural
 
90
                return truncateRunes(input, 4)
 
91
        } else if inputLen > 6 && bytes.HasSuffix(input, []byte("کان")) {
 
92
                // definite plural
 
93
                return truncateRunes(input, 3)
 
94
        } else if inputLen > 7 && bytes.HasSuffix(input, []byte("یانی")) {
 
95
                // indefinite plural ezafe
 
96
                return truncateRunes(input, 4)
 
97
        } else if inputLen > 6 && bytes.HasSuffix(input, []byte("انی")) {
 
98
                // indefinite plural ezafe
 
99
                return truncateRunes(input, 3)
 
100
        } else if inputLen > 6 && bytes.HasSuffix(input, []byte("یان")) {
 
101
                // indefinite plural
 
102
                return truncateRunes(input, 3)
 
103
        } else if inputLen > 5 && bytes.HasSuffix(input, []byte("ان")) {
 
104
                // indefinite plural
 
105
                return truncateRunes(input, 2)
 
106
        } else if inputLen > 7 && bytes.HasSuffix(input, []byte("یانە")) {
 
107
                // demonstrative plural
 
108
                return truncateRunes(input, 4)
 
109
        } else if inputLen > 6 && bytes.HasSuffix(input, []byte("انە")) {
 
110
                // demonstrative plural
 
111
                return truncateRunes(input, 3)
 
112
        } else if inputLen > 5 && (bytes.HasSuffix(input, []byte("ایە")) || bytes.HasSuffix(input, []byte("ەیە"))) {
 
113
                // demonstrative singular
 
114
                return truncateRunes(input, 2)
 
115
        } else if inputLen > 4 && bytes.HasSuffix(input, []byte("ە")) {
 
116
                // demonstrative singular
 
117
                return truncateRunes(input, 1)
 
118
        } else if inputLen > 4 && bytes.HasSuffix(input, []byte("ی")) {
 
119
                // absolute singular ezafe
 
120
                return truncateRunes(input, 1)
 
121
        }
 
122
        return input
 
123
}
 
124
 
 
125
func truncateRunes(input []byte, num int) []byte {
 
126
        runes := bytes.Runes(input)
 
127
        runes = runes[:len(runes)-num]
 
128
        out := buildTermFromRunes(runes)
 
129
        return out
 
130
}
 
131
 
 
132
func buildTermFromRunes(runes []rune) []byte {
 
133
        rv := make([]byte, 0, len(runes)*4)
 
134
        for _, r := range runes {
 
135
                runeBytes := make([]byte, utf8.RuneLen(r))
 
136
                utf8.EncodeRune(runeBytes, r)
 
137
                rv = append(rv, runeBytes...)
 
138
        }
 
139
        return rv
 
140
}
 
141
 
 
142
func StemmerFilterConstructor(config map[string]interface{}, cache *registry.Cache) (analysis.TokenFilter, error) {
 
143
        return NewSoraniStemmerFilter(), nil
 
144
}
 
145
 
 
146
func init() {
 
147
        registry.RegisterTokenFilter(StemmerName, StemmerFilterConstructor)
 
148
}