nuspell 5.1.6
Nuspell spellchecking library
Loading...
Searching...
No Matches
checker.hxx
1/* Copyright 2016-2024 Dimitrij Mijoski
2 *
3 * This file is part of Nuspell.
4 *
5 * Nuspell is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * Nuspell is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with Nuspell. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifndef NUSPELL_CHECKER_HXX
20#define NUSPELL_CHECKER_HXX
21
22#include "aff_data.hxx"
23
24namespace nuspell {
25NUSPELL_BEGIN_INLINE_NAMESPACE
26
27enum Affixing_Mode {
28 FULL_WORD,
29 AT_COMPOUND_BEGIN,
30 AT_COMPOUND_END,
31 AT_COMPOUND_MIDDLE
32};
33
34struct Affixing_Result_Base {
35 Word_List::const_pointer root_word = {};
36
37 operator Word_List::const_pointer() const { return root_word; }
38 auto& operator*() const { return *root_word; }
39 auto operator->() const { return root_word; }
40};
41
42template <class T1 = void, class T2 = void>
43struct Affixing_Result : Affixing_Result_Base {
44 const T1* a = {};
45 const T2* b = {};
46
47 Affixing_Result() = default;
48 Affixing_Result(Word_List::const_reference r, const T1& a, const T2& b)
49 : Affixing_Result_Base{&r}, a{&a}, b{&b}
50 {
51 }
52};
53template <class T1>
54struct Affixing_Result<T1, void> : Affixing_Result_Base {
55 const T1* a = {};
56
57 Affixing_Result() = default;
58 Affixing_Result(Word_List::const_reference r, const T1& a)
59 : Affixing_Result_Base{&r}, a{&a}
60 {
61 }
62};
63
64template <>
65struct Affixing_Result<void, void> : Affixing_Result_Base {
66 Affixing_Result() = default;
67 Affixing_Result(Word_List::const_reference r) : Affixing_Result_Base{&r}
68 {
69 }
70};
71
72struct Compounding_Result {
73 Word_List::const_pointer word_entry = {};
74 unsigned char num_words_modifier = {};
75 signed char num_syllable_modifier = {};
76 bool affixed_and_modified = {};
77 operator Word_List::const_pointer() const { return word_entry; }
78 auto& operator*() const { return *word_entry; }
79 auto operator->() const { return word_entry; }
80};
81
82struct Checker : public Aff_Data {
83 enum Forceucase : bool {
84 FORBID_BAD_FORCEUCASE = false,
85 ALLOW_BAD_FORCEUCASE = true
86 };
87
88 enum Hidden_Homonym : bool {
89 ACCEPT_HIDDEN_HOMONYM = false,
90 SKIP_HIDDEN_HOMONYM = true
91 };
92
93 auto spell_priv(std::string& s) const -> bool;
94 auto spell_break(std::string& s, size_t depth = 0) const -> bool;
95 auto spell_casing(std::string& s) const -> const Flag_Set*;
96 auto spell_casing_upper(std::string& s) const -> const Flag_Set*;
97 auto spell_casing_title(std::string& s) const -> const Flag_Set*;
98 auto spell_sharps(std::string& base, size_t n_pos = 0, size_t n = 0,
99 size_t rep = 0) const -> const Flag_Set*;
100
101 auto check_word(std::string& s, Forceucase allow_bad_forceucase = {},
102 Hidden_Homonym skip_hidden_homonym = {}) const
103 -> const Flag_Set*;
104 auto check_simple_word(std::string& word,
105 Hidden_Homonym skip_hidden_homonym = {}) const
106 -> const Flag_Set*;
107
108 template <Affixing_Mode m>
109 auto affix_NOT_valid(const Prefix& a) const;
110 template <Affixing_Mode m>
111 auto affix_NOT_valid(const Suffix& a) const;
112 template <Affixing_Mode m, class AffixT>
113 auto outer_affix_NOT_valid(const AffixT& a) const;
114 template <class AffixT>
115 auto is_circumfix(const AffixT& a) const;
116 template <Affixing_Mode m>
117 auto is_valid_inside_compound(const Flag_Set& flags) const;
118
119 template <Affixing_Mode m = FULL_WORD>
120 auto strip_prefix_only(std::string& s,
121 Hidden_Homonym skip_hidden_homonym = {}) const
122 -> Affixing_Result<Prefix>;
123
124 template <Affixing_Mode m = FULL_WORD>
125 auto strip_suffix_only(std::string& s,
126 Hidden_Homonym skip_hidden_homonym = {}) const
127 -> Affixing_Result<Suffix>;
128
129 template <Affixing_Mode m = FULL_WORD>
130 auto
131 strip_prefix_then_suffix(std::string& s,
132 Hidden_Homonym skip_hidden_homonym = {}) const
133 -> Affixing_Result<Suffix, Prefix>;
134
135 template <Affixing_Mode m>
136 auto strip_pfx_then_sfx_2(const Prefix& pe, std::string& s,
137 Hidden_Homonym skip_hidden_homonym) const
138 -> Affixing_Result<Suffix, Prefix>;
139
140 template <Affixing_Mode m = FULL_WORD>
141 auto
142 strip_suffix_then_prefix(std::string& s,
143 Hidden_Homonym skip_hidden_homonym = {}) const
144 -> Affixing_Result<Prefix, Suffix>;
145
146 template <Affixing_Mode m>
147 auto strip_sfx_then_pfx_2(const Suffix& se, std::string& s,
148 Hidden_Homonym skip_hidden_homonym) const
149 -> Affixing_Result<Prefix, Suffix>;
150
151 template <Affixing_Mode m = FULL_WORD>
152 auto strip_prefix_then_suffix_commutative(
153 std::string& word, Hidden_Homonym skip_hidden_homonym = {}) const
154 -> Affixing_Result<Suffix, Prefix>;
155
156 template <Affixing_Mode m = FULL_WORD>
157 auto strip_pfx_then_sfx_comm_2(const Prefix& pe, std::string& word,
158 Hidden_Homonym skip_hidden_homonym) const
159 -> Affixing_Result<Suffix, Prefix>;
160
161 template <Affixing_Mode m = FULL_WORD>
162 auto
163 strip_suffix_then_suffix(std::string& s,
164 Hidden_Homonym skip_hidden_homonym = {}) const
165 -> Affixing_Result<Suffix, Suffix>;
166
167 template <Affixing_Mode m>
168 auto strip_sfx_then_sfx_2(const Suffix& se1, std::string& s,
169 Hidden_Homonym skip_hidden_homonym) const
170 -> Affixing_Result<Suffix, Suffix>;
171
172 template <Affixing_Mode m = FULL_WORD>
173 auto
174 strip_prefix_then_prefix(std::string& s,
175 Hidden_Homonym skip_hidden_homonym = {}) const
176 -> Affixing_Result<Prefix, Prefix>;
177
178 template <Affixing_Mode m>
179 auto strip_pfx_then_pfx_2(const Prefix& pe1, std::string& s,
180 Hidden_Homonym skip_hidden_homonym) const
181 -> Affixing_Result<Prefix, Prefix>;
182
183 template <Affixing_Mode m = FULL_WORD>
184 auto strip_prefix_then_2_suffixes(
185 std::string& s, Hidden_Homonym skip_hidden_homonym = {}) const
186 -> Affixing_Result<>;
187
188 template <Affixing_Mode m>
189 auto strip_pfx_2_sfx_3(const Prefix& pe1, const Suffix& se1,
190 std::string& s,
191 Hidden_Homonym skip_hidden_homonym) const
192 -> Affixing_Result<>;
193
194 template <Affixing_Mode m = FULL_WORD>
195 auto strip_suffix_prefix_suffix(
196 std::string& s, Hidden_Homonym skip_hidden_homonym = {}) const
197 -> Affixing_Result<>;
198
199 template <Affixing_Mode m>
200 auto strip_s_p_s_3(const Suffix& se1, const Prefix& pe1,
201 std::string& word,
202 Hidden_Homonym skip_hidden_homonym) const
203 -> Affixing_Result<>;
204
205 template <Affixing_Mode m = FULL_WORD>
206 auto strip_2_suffixes_then_prefix(
207 std::string& s, Hidden_Homonym skip_hidden_homonym = {}) const
208 -> Affixing_Result<>;
209
210 template <Affixing_Mode m>
211 auto strip_2_sfx_pfx_3(const Suffix& se1, const Suffix& se2,
212 std::string& word,
213 Hidden_Homonym skip_hidden_homonym) const
214 -> Affixing_Result<>;
215
216 template <Affixing_Mode m = FULL_WORD>
217 auto strip_suffix_then_2_prefixes(
218 std::string& s, Hidden_Homonym skip_hidden_homonym = {}) const
219 -> Affixing_Result<>;
220
221 template <Affixing_Mode m>
222 auto strip_sfx_2_pfx_3(const Suffix& se1, const Prefix& pe1,
223 std::string& s,
224 Hidden_Homonym skip_hidden_homonym) const
225 -> Affixing_Result<>;
226
227 template <Affixing_Mode m = FULL_WORD>
228 auto strip_prefix_suffix_prefix(
229 std::string& word, Hidden_Homonym skip_hidden_homonym = {}) const
230 -> Affixing_Result<>;
231
232 template <Affixing_Mode m>
233 auto strip_p_s_p_3(const Prefix& pe1, const Suffix& se1,
234 std::string& word,
235 Hidden_Homonym skip_hidden_homonym) const
236 -> Affixing_Result<>;
237
238 template <Affixing_Mode m = FULL_WORD>
239 auto strip_2_prefixes_then_suffix(
240 std::string& word, Hidden_Homonym skip_hidden_homonym = {}) const
241 -> Affixing_Result<>;
242
243 template <Affixing_Mode m>
244 auto strip_2_pfx_sfx_3(const Prefix& pe1, const Prefix& pe2,
245 std::string& word,
246 Hidden_Homonym skip_hidden_homonym) const
247 -> Affixing_Result<>;
248
249 auto check_compound(std::string& word,
250 Forceucase allow_bad_forceucase) const
251 -> Compounding_Result;
252
253 template <Affixing_Mode m = AT_COMPOUND_BEGIN>
254 auto check_compound(std::string& word, size_t start_pos,
255 size_t num_part, std::string& part,
256 Forceucase allow_bad_forceucase) const
257 -> Compounding_Result;
258
259 template <Affixing_Mode m = AT_COMPOUND_BEGIN>
260 auto check_compound_classic(std::string& word, size_t start_pos,
261 size_t i, size_t num_part,
262 std::string& part,
263 Forceucase allow_bad_forceucase) const
264 -> Compounding_Result;
265
266 template <Affixing_Mode m = AT_COMPOUND_BEGIN>
267 auto check_compound_with_pattern_replacements(
268 std::string& word, size_t start_pos, size_t i, size_t num_part,
269 std::string& part, Forceucase allow_bad_forceucase) const
270 -> Compounding_Result;
271
272 template <Affixing_Mode m>
273 auto check_word_in_compound(std::string& s) const -> Compounding_Result;
274
275 auto calc_num_words_modifier(const Prefix& pfx) const -> unsigned char;
276
277 template <Affixing_Mode m>
278 auto calc_syllable_modifier(Word_List::const_reference we) const
279 -> signed char;
280
281 template <Affixing_Mode m>
282 auto calc_syllable_modifier(Word_List::const_reference we,
283 const Suffix& sfx) const -> signed char;
284
285 auto count_syllables(std::string_view word) const -> size_t;
286
287 auto check_compound_with_rules(std::string& word,
288 std::vector<const Flag_Set*>& words_data,
289 size_t start_pos, std::string& part,
290 Forceucase allow_bad_forceucase) const
291
292 -> Compounding_Result;
293 auto is_rep_similar(std::string& word) const -> bool;
294};
295
296template <Affixing_Mode m>
297auto Checker::affix_NOT_valid(const Prefix& e) const
298{
299 if (m == FULL_WORD && e.cont_flags.contains(compound_onlyin_flag))
300 return true;
301 if (m == AT_COMPOUND_END &&
302 !e.cont_flags.contains(compound_permit_flag))
303 return true;
304 if (m != FULL_WORD && e.cont_flags.contains(compound_forbid_flag))
305 return true;
306 return false;
307}
308template <Affixing_Mode m>
309auto Checker::affix_NOT_valid(const Suffix& e) const
310{
311 if (m == FULL_WORD && e.cont_flags.contains(compound_onlyin_flag))
312 return true;
313 if (m == AT_COMPOUND_BEGIN &&
314 !e.cont_flags.contains(compound_permit_flag))
315 return true;
316 if (m != FULL_WORD && e.cont_flags.contains(compound_forbid_flag))
317 return true;
318 return false;
319}
320template <Affixing_Mode m, class AffixT>
321auto Checker::outer_affix_NOT_valid(const AffixT& e) const
322{
323 if (affix_NOT_valid<m>(e))
324 return true;
325 if (e.cont_flags.contains(need_affix_flag))
326 return true;
327 return false;
328}
329template <class AffixT>
330auto Checker::is_circumfix(const AffixT& a) const
331{
332 return a.cont_flags.contains(circumfix_flag);
333}
334
335template <class AffixInner, class AffixOuter>
336auto cross_valid_inner_outer(const AffixInner& inner, const AffixOuter& outer)
337{
338 return inner.cont_flags.contains(outer.flag);
339}
340
341template <class Affix>
342auto cross_valid_inner_outer(const Flag_Set& word_flags, const Affix& afx)
343{
344 return word_flags.contains(afx.flag);
345}
346
347NUSPELL_END_INLINE_NAMESPACE
348} // namespace nuspell
349#endif // NUSPELL_CHECKER_HXX
Library main namespace.
Definition aff_data.cxx:33