• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ljacqu / wordeval / 14573369468

21 Apr 2025 12:20PM UTC coverage: 58.038% (+2.9%) from 55.116%
14573369468

push

github

ljacqu
Create Hunspell aff parser (work in progress)

310 of 613 branches covered (50.57%)

96 of 98 new or added lines in 10 files covered. (97.96%)

834 of 1437 relevant lines covered (58.04%)

3.35 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.3
/src/main/java/ch/jalu/wordeval/dictionary/hunspell/parser/AffixesParser.java
1
package ch.jalu.wordeval.dictionary.hunspell.parser;
2

3
import ch.jalu.wordeval.dictionary.hunspell.AffixFlagType;
4
import ch.jalu.wordeval.dictionary.hunspell.AffixType;
5
import org.springframework.stereotype.Component;
6

7
import java.util.regex.Matcher;
8
import java.util.regex.Pattern;
9
import java.util.stream.Stream;
10

11
/**
12
 * Hunspell .aff parser.
13
 */
14
@Component
15
public class AffixesParser {
3✔
16

17
    // TODO: twofold suffix stripping is a thing  (e.g. `SFX X 0 able/Y .`)
18
    // https://www.systutorials.com/docs/linux/man/4-hunspell/
19

20
    // e.g. SFX V N 2
21
    private static final Pattern HEADER_PATTERN = Pattern.compile("^(PFX|SFX)\\s+(\\S)\\s+([YN])\\s+(\\d+)$");
3✔
22
    // e.g. SFX V   e  ive  e
23
    private static final Pattern RULE_PATTERN = Pattern.compile("^(PFX|SFX)\\s+\\S\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)(.*?)?$");
4✔
24

25
    public ParsedAffixes parseAffFile(Stream<String> lines) {
26
        ParsedAffixes result = new ParsedAffixes();
4✔
27

28
        lines.forEach(line -> {
4✔
29
            line = line.trim();
3✔
30
            if (line.isEmpty() || line.startsWith("#")) {
7✔
31
                return;
1✔
32
            }
33

34
            Matcher headerMatcher = HEADER_PATTERN.matcher(line);
4✔
35
            Matcher ruleMatcher = RULE_PATTERN.matcher(line);
4✔
36

37
            if (headerMatcher.matches()) {
3✔
38
                ParsedRule rule = new ParsedRule();
4✔
39
                rule.type = AffixType.fromString(headerMatcher.group(1));
6✔
40
                rule.flag = headerMatcher.group(2);
5✔
41
                rule.crossProduct = headerMatcher.group(3).equalsIgnoreCase("Y");
7✔
42
                result.addRule(rule);
3✔
43
            } else if (ruleMatcher.matches()) {
4✔
44
                String strip = ruleMatcher.group(2).equals("0") ? "" : ruleMatcher.group(2);
12✔
45
                String append = ruleMatcher.group(3).equals("0") ? "" : ruleMatcher.group(3);
10!
46
                String condition = ruleMatcher.group(4);
4✔
47
                result.addEntryToCurrentRule(new ParsedRule.RuleEntry(strip, append, condition));
8✔
48
            } else if (line.startsWith("REP ")) {
5!
49
                // ignore
50
            } else if (line.startsWith("FLAG ")) {
4!
51
                result.setFlagType(AffixFlagType.fromAffixFileString(line.substring("FLAG ".length())));
8✔
52
            } else {
53
                // todo: logging
NEW
54
                System.out.println("Unknown line: " + line);
×
55
            }
56
        });
1✔
57

58
        return result;
2✔
59
    }
60
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc