chipper 0.4.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +51 -0
- data/ext/extconf.rb +58 -0
- data/ext/libstemmer_c/Makefile +10 -0
- data/ext/libstemmer_c/examples/stemwords.c +209 -0
- data/ext/libstemmer_c/include/libstemmer.h +79 -0
- data/ext/libstemmer_c/libstemmer/libstemmer.c +95 -0
- data/ext/libstemmer_c/libstemmer/libstemmer_utf8.c +95 -0
- data/ext/libstemmer_c/libstemmer/modules.h +190 -0
- data/ext/libstemmer_c/libstemmer/modules_utf8.h +121 -0
- data/ext/libstemmer_c/mkinc.mak +82 -0
- data/ext/libstemmer_c/mkinc_utf8.mak +52 -0
- data/ext/libstemmer_c/runtime/api.c +66 -0
- data/ext/libstemmer_c/runtime/api.h +26 -0
- data/ext/libstemmer_c/runtime/header.h +58 -0
- data/ext/libstemmer_c/runtime/utilities.c +478 -0
- data/ext/libstemmer_c/src_c/stem_ISO_8859_1_danish.c +337 -0
- data/ext/libstemmer_c/src_c/stem_ISO_8859_1_danish.h +16 -0
- data/ext/libstemmer_c/src_c/stem_ISO_8859_1_dutch.c +624 -0
- data/ext/libstemmer_c/src_c/stem_ISO_8859_1_dutch.h +16 -0
- data/ext/libstemmer_c/src_c/stem_ISO_8859_1_english.c +1117 -0
- data/ext/libstemmer_c/src_c/stem_ISO_8859_1_english.h +16 -0
- data/ext/libstemmer_c/src_c/stem_ISO_8859_1_finnish.c +762 -0
- data/ext/libstemmer_c/src_c/stem_ISO_8859_1_finnish.h +16 -0
- data/ext/libstemmer_c/src_c/stem_ISO_8859_1_french.c +1246 -0
- data/ext/libstemmer_c/src_c/stem_ISO_8859_1_french.h +16 -0
- data/ext/libstemmer_c/src_c/stem_ISO_8859_1_german.c +521 -0
- data/ext/libstemmer_c/src_c/stem_ISO_8859_1_german.h +16 -0
- data/ext/libstemmer_c/src_c/stem_ISO_8859_1_hungarian.c +1230 -0
- data/ext/libstemmer_c/src_c/stem_ISO_8859_1_hungarian.h +16 -0
- data/ext/libstemmer_c/src_c/stem_ISO_8859_1_italian.c +1065 -0
- data/ext/libstemmer_c/src_c/stem_ISO_8859_1_italian.h +16 -0
- data/ext/libstemmer_c/src_c/stem_ISO_8859_1_norwegian.c +297 -0
- data/ext/libstemmer_c/src_c/stem_ISO_8859_1_norwegian.h +16 -0
- data/ext/libstemmer_c/src_c/stem_ISO_8859_1_porter.c +749 -0
- data/ext/libstemmer_c/src_c/stem_ISO_8859_1_porter.h +16 -0
- data/ext/libstemmer_c/src_c/stem_ISO_8859_1_portuguese.c +1017 -0
- data/ext/libstemmer_c/src_c/stem_ISO_8859_1_portuguese.h +16 -0
- data/ext/libstemmer_c/src_c/stem_ISO_8859_1_spanish.c +1093 -0
- data/ext/libstemmer_c/src_c/stem_ISO_8859_1_spanish.h +16 -0
- data/ext/libstemmer_c/src_c/stem_ISO_8859_1_swedish.c +307 -0
- data/ext/libstemmer_c/src_c/stem_ISO_8859_1_swedish.h +16 -0
- data/ext/libstemmer_c/src_c/stem_ISO_8859_2_romanian.c +998 -0
- data/ext/libstemmer_c/src_c/stem_ISO_8859_2_romanian.h +16 -0
- data/ext/libstemmer_c/src_c/stem_KOI8_R_russian.c +700 -0
- data/ext/libstemmer_c/src_c/stem_KOI8_R_russian.h +16 -0
- data/ext/libstemmer_c/src_c/stem_UTF_8_danish.c +339 -0
- data/ext/libstemmer_c/src_c/stem_UTF_8_danish.h +16 -0
- data/ext/libstemmer_c/src_c/stem_UTF_8_dutch.c +634 -0
- data/ext/libstemmer_c/src_c/stem_UTF_8_dutch.h +16 -0
- data/ext/libstemmer_c/src_c/stem_UTF_8_english.c +1125 -0
- data/ext/libstemmer_c/src_c/stem_UTF_8_english.h +16 -0
- data/ext/libstemmer_c/src_c/stem_UTF_8_finnish.c +768 -0
- data/ext/libstemmer_c/src_c/stem_UTF_8_finnish.h +16 -0
- data/ext/libstemmer_c/src_c/stem_UTF_8_french.c +1256 -0
- data/ext/libstemmer_c/src_c/stem_UTF_8_french.h +16 -0
- data/ext/libstemmer_c/src_c/stem_UTF_8_german.c +527 -0
- data/ext/libstemmer_c/src_c/stem_UTF_8_german.h +16 -0
- data/ext/libstemmer_c/src_c/stem_UTF_8_hungarian.c +1234 -0
- data/ext/libstemmer_c/src_c/stem_UTF_8_hungarian.h +16 -0
- data/ext/libstemmer_c/src_c/stem_UTF_8_italian.c +1073 -0
- data/ext/libstemmer_c/src_c/stem_UTF_8_italian.h +16 -0
- data/ext/libstemmer_c/src_c/stem_UTF_8_norwegian.c +299 -0
- data/ext/libstemmer_c/src_c/stem_UTF_8_norwegian.h +16 -0
- data/ext/libstemmer_c/src_c/stem_UTF_8_porter.c +755 -0
- data/ext/libstemmer_c/src_c/stem_UTF_8_porter.h +16 -0
- data/ext/libstemmer_c/src_c/stem_UTF_8_portuguese.c +1023 -0
- data/ext/libstemmer_c/src_c/stem_UTF_8_portuguese.h +16 -0
- data/ext/libstemmer_c/src_c/stem_UTF_8_romanian.c +1004 -0
- data/ext/libstemmer_c/src_c/stem_UTF_8_romanian.h +16 -0
- data/ext/libstemmer_c/src_c/stem_UTF_8_russian.c +694 -0
- data/ext/libstemmer_c/src_c/stem_UTF_8_russian.h +16 -0
- data/ext/libstemmer_c/src_c/stem_UTF_8_spanish.c +1097 -0
- data/ext/libstemmer_c/src_c/stem_UTF_8_spanish.h +16 -0
- data/ext/libstemmer_c/src_c/stem_UTF_8_swedish.c +309 -0
- data/ext/libstemmer_c/src_c/stem_UTF_8_swedish.h +16 -0
- data/ext/libstemmer_c/src_c/stem_UTF_8_turkish.c +2205 -0
- data/ext/libstemmer_c/src_c/stem_UTF_8_turkish.h +16 -0
- data/ext/re2/bitstate.cc +378 -0
- data/ext/re2/compile.cc +1138 -0
- data/ext/re2/dfa.cc +2086 -0
- data/ext/re2/filtered_re2.cc +100 -0
- data/ext/re2/filtered_re2.h +99 -0
- data/ext/re2/hash.cc +231 -0
- data/ext/re2/mimics_pcre.cc +185 -0
- data/ext/re2/nfa.cc +709 -0
- data/ext/re2/onepass.cc +614 -0
- data/ext/re2/parse.cc +2202 -0
- data/ext/re2/perl_groups.cc +119 -0
- data/ext/re2/prefilter.cc +671 -0
- data/ext/re2/prefilter.h +105 -0
- data/ext/re2/prefilter_tree.cc +398 -0
- data/ext/re2/prefilter_tree.h +130 -0
- data/ext/re2/prog.cc +341 -0
- data/ext/re2/prog.h +376 -0
- data/ext/re2/re2.cc +1180 -0
- data/ext/re2/re2.h +837 -0
- data/ext/re2/regexp.cc +920 -0
- data/ext/re2/regexp.h +632 -0
- data/ext/re2/rune.cc +258 -0
- data/ext/re2/set.cc +113 -0
- data/ext/re2/set.h +55 -0
- data/ext/re2/simplify.cc +393 -0
- data/ext/re2/stringpiece.cc +87 -0
- data/ext/re2/stringpiece.h +182 -0
- data/ext/re2/tostring.cc +341 -0
- data/ext/re2/unicode_casefold.cc +469 -0
- data/ext/re2/unicode_casefold.h +75 -0
- data/ext/re2/unicode_groups.cc +4851 -0
- data/ext/re2/unicode_groups.h +64 -0
- data/ext/re2/valgrind.cc +24 -0
- data/ext/re2/variadic_function.h +346 -0
- data/ext/re2/walker-inl.h +244 -0
- data/ext/src/chipper.cc +626 -0
- data/ext/src/version.h +1 -0
- data/ext/stemmer.rb +40 -0
- data/ext/util/arena.h +103 -0
- data/ext/util/atomicops.h +79 -0
- data/ext/util/benchmark.h +41 -0
- data/ext/util/flags.h +27 -0
- data/ext/util/logging.h +78 -0
- data/ext/util/mutex.h +190 -0
- data/ext/util/pcre.h +679 -0
- data/ext/util/random.h +29 -0
- data/ext/util/sparse_array.h +451 -0
- data/ext/util/sparse_set.h +177 -0
- data/ext/util/test.h +57 -0
- data/ext/util/thread.h +26 -0
- data/ext/util/utf.h +43 -0
- data/ext/util/util.h +127 -0
- data/ext/util/valgrind.h +4517 -0
- data/test/helper.rb +5 -0
- data/test/test_entities.rb +57 -0
- data/test/test_tokens.rb +118 -0
- metadata +199 -0
data/README.rdoc
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
= Twitter Text Extraction
|
2
|
+
|
3
|
+
A fast screen name, hashtag, url extraction and tokenizer for tweets.
|
4
|
+
|
5
|
+
|
6
|
+
== API
|
7
|
+
|
8
|
+
Chipper
|
9
|
+
#users => [Array]
|
10
|
+
#hashtags => [Array]
|
11
|
+
#urls => [Array]
|
12
|
+
#tokens => [Array]
|
13
|
+
|
14
|
+
#skip_users
|
15
|
+
#skip_hashtags
|
16
|
+
#skip_tokens
|
17
|
+
#skip_token_pattern
|
18
|
+
|
19
|
+
== Usage
|
20
|
+
|
21
|
+
require 'chipper'
|
22
|
+
|
23
|
+
Chipper.skip_users(%w(youtube msn))
|
24
|
+
Chipper.skip_hashtags(%w(abc24 cnn))
|
25
|
+
Chipper.skip_tokens(%w(story tv why that get from your))
|
26
|
+
Chipper.skip_token_pattern '^vimeo$'
|
27
|
+
|
28
|
+
tweet = "hi @youtube, could we get #cnn videos so i can #watch it on my @apple tv http://t.co/HM7XoimM"
|
29
|
+
Chipper.users(tweet) #=> ["@apple"]
|
30
|
+
Chipper.hashtags(tweet) #=> ["#watch"]
|
31
|
+
Chipper.urls(tweet) #=> ["http://t.co/HM7XoimM"]
|
32
|
+
|
33
|
+
# n-gram tokenizer, returns a list of tokens partitioned by stop words, punctuation, urls and hashtags.
|
34
|
+
Chipper.tokens(tweet) #=> [["could"], ["get"], ["videos"], ["can"]]
|
35
|
+
|
36
|
+
# single method that does all of the above and returns a hash.
|
37
|
+
Chipper.entities(tweet)
|
38
|
+
|
39
|
+
== Gotchas
|
40
|
+
|
41
|
+
* skips tokens shorter than 3 characters
|
42
|
+
* only handles t.co urls
|
43
|
+
|
44
|
+
== Updating version
|
45
|
+
|
46
|
+
* update ext/src/version.h
|
47
|
+
* rake gemspec
|
48
|
+
|
49
|
+
== License
|
50
|
+
|
51
|
+
{Creative Commons Attribution - CC BY}[http://creativecommons.org/licenses/by/3.0]
|
data/ext/extconf.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'mkmf'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
puts 'compiling libstemmer_c'
|
7
|
+
logs = IO.popen(File.join(File.dirname(__FILE__), 'stemmer.rb') + ' 2>&1') {|io| io.read }
|
8
|
+
|
9
|
+
File.open('mkmf.log', 'w') {|fh| fh.write(logs)}
|
10
|
+
|
11
|
+
raise "unable to compile libstemmer_c" if $?.exitstatus != 0
|
12
|
+
|
13
|
+
EXTCONFIG = Object.const_get(defined?(RbConfig) ? :RbConfig : :Config)::CONFIG
|
14
|
+
EXTCONFIG['CC'] = 'g++'
|
15
|
+
EXTCONFIG['CPP'] = 'g++'
|
16
|
+
|
17
|
+
version = %x{g++ --version | head -n1}.strip.sub(%r{^.* ([\d\.]+)$}, '\1')
|
18
|
+
maj, min = version.split('.').values_at(0, 1).map(&:to_i)
|
19
|
+
|
20
|
+
$CFLAGS = '-pthread -Wno-sign-compare '
|
21
|
+
$CFLAGS += (maj >= 4 && min > 5 || maj > 4) ? '-Ofast ' : '-O3 '
|
22
|
+
$CFLAGS += '-I/usr/include -I/opt/local/include -I/usr/local/include'
|
23
|
+
|
24
|
+
snowball = File.join(File.dirname(__FILE__), 'libstemmer_c')
|
25
|
+
$CFLAGS += " -I#{File.expand_path(File.join(snowball, 'include'))} "
|
26
|
+
$libs = 'libstemmer_c/libstemmer.o'
|
27
|
+
|
28
|
+
def apt_install_hint pkg
|
29
|
+
"sudo apt-get install #{pkg}"
|
30
|
+
end
|
31
|
+
|
32
|
+
def library_installed? name, hint
|
33
|
+
if find_library(name, 'main', *%w(/usr/lib /usr/local/lib /opt/lib /opt/local/lib /sw/lib))
|
34
|
+
true
|
35
|
+
else
|
36
|
+
$stderr.puts <<-ERROR
|
37
|
+
|
38
|
+
Unable to find required library: #{name}.
|
39
|
+
On debian systems, it can be installed as,
|
40
|
+
|
41
|
+
#{hint}
|
42
|
+
|
43
|
+
ERROR
|
44
|
+
false
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# ugly mkmf hack: manually assign source and object directories.
|
49
|
+
$srcs = Dir["{re2/*.cc,src/*.cc}"]
|
50
|
+
$objs = $srcs.map {|name| File.join(File.dirname(name), File.basename(name, ".cc") + ".o")}
|
51
|
+
|
52
|
+
class File
|
53
|
+
def self.basename name
|
54
|
+
name
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
create_makefile 'chipper'
|
@@ -0,0 +1,10 @@
|
|
1
|
+
include mkinc.mak
|
2
|
+
CC=g++
|
3
|
+
CFLAGS=-Iinclude -fPIC -O3
|
4
|
+
all: libstemmer.o stemwords
|
5
|
+
libstemmer.o: $(snowball_sources:.c=.o)
|
6
|
+
$(AR) -cru $@ $^
|
7
|
+
stemwords: examples/stemwords.o libstemmer.o
|
8
|
+
$(CC) -o $@ $^
|
9
|
+
clean:
|
10
|
+
rm -f stemwords *.o src_c/*.o runtime/*.o libstemmer/*.o
|
@@ -0,0 +1,209 @@
|
|
1
|
+
/* This is a simple program which uses libstemmer to provide a command
|
2
|
+
* line interface for stemming using any of the algorithms provided.
|
3
|
+
*/
|
4
|
+
|
5
|
+
#include <stdio.h>
|
6
|
+
#include <stdlib.h> /* for malloc, free */
|
7
|
+
#include <string.h> /* for memmove */
|
8
|
+
#include <ctype.h> /* for isupper, tolower */
|
9
|
+
|
10
|
+
#include "libstemmer.h"
|
11
|
+
|
12
|
+
const char * progname;
|
13
|
+
static int pretty = 1;
|
14
|
+
|
15
|
+
static void
|
16
|
+
stem_file(struct sb_stemmer * stemmer, FILE * f_in, FILE * f_out)
|
17
|
+
{
|
18
|
+
#define INC 10
|
19
|
+
int lim = INC;
|
20
|
+
sb_symbol * b = (sb_symbol *) malloc(lim * sizeof(sb_symbol));
|
21
|
+
|
22
|
+
while(1) {
|
23
|
+
int ch = getc(f_in);
|
24
|
+
if (ch == EOF) {
|
25
|
+
free(b); return;
|
26
|
+
}
|
27
|
+
{
|
28
|
+
int i = 0;
|
29
|
+
int inlen = 0;
|
30
|
+
while(1) {
|
31
|
+
if (ch == '\n' || ch == EOF) break;
|
32
|
+
if (i == lim) {
|
33
|
+
sb_symbol * newb;
|
34
|
+
newb = (sb_symbol *)
|
35
|
+
realloc(b, (lim + INC) * sizeof(sb_symbol));
|
36
|
+
if (newb == 0) goto error;
|
37
|
+
b = newb;
|
38
|
+
lim = lim + INC;
|
39
|
+
}
|
40
|
+
/* Update count of utf-8 characters. */
|
41
|
+
if (ch < 0x80 || ch > 0xBF) inlen += 1;
|
42
|
+
/* force lower case: */
|
43
|
+
if (isupper(ch)) ch = tolower(ch);
|
44
|
+
|
45
|
+
b[i] = ch;
|
46
|
+
i++;
|
47
|
+
ch = getc(f_in);
|
48
|
+
}
|
49
|
+
|
50
|
+
{
|
51
|
+
const sb_symbol * stemmed = sb_stemmer_stem(stemmer, b, i);
|
52
|
+
if (stemmed == NULL)
|
53
|
+
{
|
54
|
+
fprintf(stderr, "Out of memory");
|
55
|
+
exit(1);
|
56
|
+
}
|
57
|
+
else
|
58
|
+
{
|
59
|
+
if (pretty == 1) {
|
60
|
+
fwrite(b, i, 1, f_out);
|
61
|
+
fputs(" -> ", f_out);
|
62
|
+
} else if (pretty == 2) {
|
63
|
+
fwrite(b, i, 1, f_out);
|
64
|
+
if (sb_stemmer_length(stemmer) > 0) {
|
65
|
+
int j;
|
66
|
+
if (inlen < 30) {
|
67
|
+
for (j = 30 - inlen; j > 0; j--)
|
68
|
+
fputs(" ", f_out);
|
69
|
+
} else {
|
70
|
+
fputs("\n", f_out);
|
71
|
+
for (j = 30; j > 0; j--)
|
72
|
+
fputs(" ", f_out);
|
73
|
+
}
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
77
|
+
fputs((char *)stemmed, f_out);
|
78
|
+
putc('\n', f_out);
|
79
|
+
}
|
80
|
+
}
|
81
|
+
}
|
82
|
+
}
|
83
|
+
error:
|
84
|
+
if (b != 0) free(b);
|
85
|
+
return;
|
86
|
+
}
|
87
|
+
|
88
|
+
/** Display the command line syntax, and then exit.
|
89
|
+
* @param n The value to exit with.
|
90
|
+
*/
|
91
|
+
static void
|
92
|
+
usage(int n)
|
93
|
+
{
|
94
|
+
printf("usage: %s [-l <language>] [-i <input file>] [-o <output file>] [-c <character encoding>] [-p[2]] [-h]\n"
|
95
|
+
"\n"
|
96
|
+
"The input file consists of a list of words to be stemmed, one per\n"
|
97
|
+
"line. Words should be in lower case, but (for English) A-Z letters\n"
|
98
|
+
"are mapped to their a-z equivalents anyway. If omitted, stdin is\n"
|
99
|
+
"used.\n"
|
100
|
+
"\n"
|
101
|
+
"If -c is given, the argument is the character encoding of the input\n"
|
102
|
+
"and output files. If it is omitted, the UTF-8 encoding is used.\n"
|
103
|
+
"\n"
|
104
|
+
"If -p is given the output file consists of each word of the input\n"
|
105
|
+
"file followed by \"->\" followed by its stemmed equivalent.\n"
|
106
|
+
"If -p2 is given the output file is a two column layout containing\n"
|
107
|
+
"the input words in the first column and the stemmed eqivalents in\n"
|
108
|
+
"the second column.\n"
|
109
|
+
"Otherwise, the output file consists of the stemmed words, one per\n"
|
110
|
+
"line.\n"
|
111
|
+
"\n"
|
112
|
+
"-h displays this help\n",
|
113
|
+
progname);
|
114
|
+
exit(n);
|
115
|
+
}
|
116
|
+
|
117
|
+
int
|
118
|
+
main(int argc, char * argv[])
|
119
|
+
{
|
120
|
+
char * in = 0;
|
121
|
+
char * out = 0;
|
122
|
+
FILE * f_in;
|
123
|
+
FILE * f_out;
|
124
|
+
struct sb_stemmer * stemmer;
|
125
|
+
|
126
|
+
char * language = "english";
|
127
|
+
char * charenc = NULL;
|
128
|
+
|
129
|
+
char * s;
|
130
|
+
int i = 1;
|
131
|
+
pretty = 0;
|
132
|
+
|
133
|
+
progname = argv[0];
|
134
|
+
|
135
|
+
while(i < argc) {
|
136
|
+
s = argv[i++];
|
137
|
+
if (s[0] == '-') {
|
138
|
+
if (strcmp(s, "-o") == 0) {
|
139
|
+
if (i >= argc) {
|
140
|
+
fprintf(stderr, "%s requires an argument\n", s);
|
141
|
+
exit(1);
|
142
|
+
}
|
143
|
+
out = argv[i++];
|
144
|
+
} else if (strcmp(s, "-i") == 0) {
|
145
|
+
if (i >= argc) {
|
146
|
+
fprintf(stderr, "%s requires an argument\n", s);
|
147
|
+
exit(1);
|
148
|
+
}
|
149
|
+
in = argv[i++];
|
150
|
+
} else if (strcmp(s, "-l") == 0) {
|
151
|
+
if (i >= argc) {
|
152
|
+
fprintf(stderr, "%s requires an argument\n", s);
|
153
|
+
exit(1);
|
154
|
+
}
|
155
|
+
language = argv[i++];
|
156
|
+
} else if (strcmp(s, "-c") == 0) {
|
157
|
+
if (i >= argc) {
|
158
|
+
fprintf(stderr, "%s requires an argument\n", s);
|
159
|
+
exit(1);
|
160
|
+
}
|
161
|
+
charenc = argv[i++];
|
162
|
+
} else if (strcmp(s, "-p2") == 0) {
|
163
|
+
pretty = 2;
|
164
|
+
} else if (strcmp(s, "-p") == 0) {
|
165
|
+
pretty = 1;
|
166
|
+
} else if (strcmp(s, "-h") == 0) {
|
167
|
+
usage(0);
|
168
|
+
} else {
|
169
|
+
fprintf(stderr, "option %s unknown\n", s);
|
170
|
+
usage(1);
|
171
|
+
}
|
172
|
+
} else {
|
173
|
+
fprintf(stderr, "unexpected parameter %s\n", s);
|
174
|
+
usage(1);
|
175
|
+
}
|
176
|
+
}
|
177
|
+
|
178
|
+
/* prepare the files */
|
179
|
+
f_in = (in == 0) ? stdin : fopen(in, "r");
|
180
|
+
if (f_in == 0) {
|
181
|
+
fprintf(stderr, "file %s not found\n", in);
|
182
|
+
exit(1);
|
183
|
+
}
|
184
|
+
f_out = (out == 0) ? stdout : fopen(out, "w");
|
185
|
+
if (f_out == 0) {
|
186
|
+
fprintf(stderr, "file %s cannot be opened\n", out);
|
187
|
+
exit(1);
|
188
|
+
}
|
189
|
+
|
190
|
+
/* do the stemming process: */
|
191
|
+
stemmer = sb_stemmer_new(language, charenc);
|
192
|
+
if (stemmer == 0) {
|
193
|
+
if (charenc == NULL) {
|
194
|
+
fprintf(stderr, "language `%s' not available for stemming\n", language);
|
195
|
+
exit(1);
|
196
|
+
} else {
|
197
|
+
fprintf(stderr, "language `%s' not available for stemming in encoding `%s'\n", language, charenc);
|
198
|
+
exit(1);
|
199
|
+
}
|
200
|
+
}
|
201
|
+
stem_file(stemmer, f_in, f_out);
|
202
|
+
sb_stemmer_delete(stemmer);
|
203
|
+
|
204
|
+
if (in != 0) (void) fclose(f_in);
|
205
|
+
if (out != 0) (void) fclose(f_out);
|
206
|
+
|
207
|
+
return 0;
|
208
|
+
}
|
209
|
+
|
@@ -0,0 +1,79 @@
|
|
1
|
+
|
2
|
+
/* Make header file work when included from C++ */
|
3
|
+
#ifdef __cplusplus
|
4
|
+
extern "C" {
|
5
|
+
#endif
|
6
|
+
|
7
|
+
struct sb_stemmer;
|
8
|
+
typedef unsigned char sb_symbol;
|
9
|
+
|
10
|
+
/* FIXME - should be able to get a version number for each stemming
|
11
|
+
* algorithm (which will be incremented each time the output changes). */
|
12
|
+
|
13
|
+
/** Returns an array of the names of the available stemming algorithms.
|
14
|
+
* Note that these are the canonical names - aliases (ie, other names for
|
15
|
+
* the same algorithm) will not be included in the list.
|
16
|
+
* The list is terminated with a null pointer.
|
17
|
+
*
|
18
|
+
* The list must not be modified in any way.
|
19
|
+
*/
|
20
|
+
const char ** sb_stemmer_list(void);
|
21
|
+
|
22
|
+
/** Create a new stemmer object, using the specified algorithm, for the
|
23
|
+
* specified character encoding.
|
24
|
+
*
|
25
|
+
* All algorithms will usually be available in UTF-8, but may also be
|
26
|
+
* available in other character encodings.
|
27
|
+
*
|
28
|
+
* @param algorithm The algorithm name. This is either the english
|
29
|
+
* name of the algorithm, or the 2 or 3 letter ISO 639 codes for the
|
30
|
+
* language. Note that case is significant in this parameter - the
|
31
|
+
* value should be supplied in lower case.
|
32
|
+
*
|
33
|
+
* @param charenc The character encoding. NULL may be passed as
|
34
|
+
* this value, in which case UTF-8 encoding will be assumed. Otherwise,
|
35
|
+
* the argument may be one of "UTF_8", "ISO_8859_1" (ie, Latin 1),
|
36
|
+
* "CP850" (ie, MS-DOS Latin 1) or "KOI8_R" (Russian). Note that
|
37
|
+
* case is significant in this parameter.
|
38
|
+
*
|
39
|
+
* @return NULL if the specified algorithm is not recognised, or the
|
40
|
+
* algorithm is not available for the requested encoding. Otherwise,
|
41
|
+
* returns a pointer to a newly created stemmer for the requested algorithm.
|
42
|
+
* The returned pointer must be deleted by calling sb_stemmer_delete().
|
43
|
+
*
|
44
|
+
* @note NULL will also be returned if an out of memory error occurs.
|
45
|
+
*/
|
46
|
+
struct sb_stemmer * sb_stemmer_new(const char * algorithm, const char * charenc);
|
47
|
+
|
48
|
+
/** Delete a stemmer object.
|
49
|
+
*
|
50
|
+
* This frees all resources allocated for the stemmer. After calling
|
51
|
+
* this function, the supplied stemmer may no longer be used in any way.
|
52
|
+
*
|
53
|
+
* It is safe to pass a null pointer to this function - this will have
|
54
|
+
* no effect.
|
55
|
+
*/
|
56
|
+
void sb_stemmer_delete(struct sb_stemmer * stemmer);
|
57
|
+
|
58
|
+
/** Stem a word.
|
59
|
+
*
|
60
|
+
* The return value is owned by the stemmer - it must not be freed or
|
61
|
+
* modified, and it will become invalid when the stemmer is called again,
|
62
|
+
* or if the stemmer is freed.
|
63
|
+
*
|
64
|
+
* The length of the return value can be obtained using sb_stemmer_length().
|
65
|
+
*
|
66
|
+
* If an out-of-memory error occurs, this will return NULL.
|
67
|
+
*/
|
68
|
+
const sb_symbol * sb_stemmer_stem(struct sb_stemmer * stemmer,
|
69
|
+
const sb_symbol * word, int size);
|
70
|
+
|
71
|
+
/** Get the length of the result of the last stemmed word.
|
72
|
+
* This should not be called before sb_stemmer_stem() has been called.
|
73
|
+
*/
|
74
|
+
int sb_stemmer_length(struct sb_stemmer * stemmer);
|
75
|
+
|
76
|
+
#ifdef __cplusplus
|
77
|
+
}
|
78
|
+
#endif
|
79
|
+
|
@@ -0,0 +1,95 @@
|
|
1
|
+
|
2
|
+
#include <stdlib.h>
|
3
|
+
#include <string.h>
|
4
|
+
#include "../include/libstemmer.h"
|
5
|
+
#include "../runtime/api.h"
|
6
|
+
#include "modules.h"
|
7
|
+
|
8
|
+
struct sb_stemmer {
|
9
|
+
struct SN_env * (*create)(void);
|
10
|
+
void (*close)(struct SN_env *);
|
11
|
+
int (*stem)(struct SN_env *);
|
12
|
+
|
13
|
+
struct SN_env * env;
|
14
|
+
};
|
15
|
+
|
16
|
+
extern const char **
|
17
|
+
sb_stemmer_list(void)
|
18
|
+
{
|
19
|
+
return algorithm_names;
|
20
|
+
}
|
21
|
+
|
22
|
+
static stemmer_encoding_t
|
23
|
+
sb_getenc(const char * charenc)
|
24
|
+
{
|
25
|
+
struct stemmer_encoding * encoding;
|
26
|
+
if (charenc == NULL) return ENC_UTF_8;
|
27
|
+
for (encoding = encodings; encoding->name != 0; encoding++) {
|
28
|
+
if (strcmp(encoding->name, charenc) == 0) break;
|
29
|
+
}
|
30
|
+
if (encoding->name == NULL) return ENC_UNKNOWN;
|
31
|
+
return encoding->enc;
|
32
|
+
}
|
33
|
+
|
34
|
+
extern struct sb_stemmer *
|
35
|
+
sb_stemmer_new(const char * algorithm, const char * charenc)
|
36
|
+
{
|
37
|
+
stemmer_encoding_t enc;
|
38
|
+
struct stemmer_modules * module;
|
39
|
+
struct sb_stemmer * stemmer;
|
40
|
+
|
41
|
+
enc = sb_getenc(charenc);
|
42
|
+
if (enc == ENC_UNKNOWN) return NULL;
|
43
|
+
|
44
|
+
for (module = modules; module->name != 0; module++) {
|
45
|
+
if (strcmp(module->name, algorithm) == 0 && module->enc == enc) break;
|
46
|
+
}
|
47
|
+
if (module->name == NULL) return NULL;
|
48
|
+
|
49
|
+
stemmer = (struct sb_stemmer *) malloc(sizeof(struct sb_stemmer));
|
50
|
+
if (stemmer == NULL) return NULL;
|
51
|
+
|
52
|
+
stemmer->create = module->create;
|
53
|
+
stemmer->close = module->close;
|
54
|
+
stemmer->stem = module->stem;
|
55
|
+
|
56
|
+
stemmer->env = stemmer->create();
|
57
|
+
if (stemmer->env == NULL)
|
58
|
+
{
|
59
|
+
sb_stemmer_delete(stemmer);
|
60
|
+
return NULL;
|
61
|
+
}
|
62
|
+
|
63
|
+
return stemmer;
|
64
|
+
}
|
65
|
+
|
66
|
+
void
|
67
|
+
sb_stemmer_delete(struct sb_stemmer * stemmer)
|
68
|
+
{
|
69
|
+
if (stemmer == 0) return;
|
70
|
+
if (stemmer->close == 0) return;
|
71
|
+
stemmer->close(stemmer->env);
|
72
|
+
stemmer->close = 0;
|
73
|
+
free(stemmer);
|
74
|
+
}
|
75
|
+
|
76
|
+
const sb_symbol *
|
77
|
+
sb_stemmer_stem(struct sb_stemmer * stemmer, const sb_symbol * word, int size)
|
78
|
+
{
|
79
|
+
int ret;
|
80
|
+
if (SN_set_current(stemmer->env, size, (const symbol *)(word)))
|
81
|
+
{
|
82
|
+
stemmer->env->l = 0;
|
83
|
+
return NULL;
|
84
|
+
}
|
85
|
+
ret = stemmer->stem(stemmer->env);
|
86
|
+
if (ret < 0) return NULL;
|
87
|
+
stemmer->env->p[stemmer->env->l] = 0;
|
88
|
+
return (const sb_symbol *)(stemmer->env->p);
|
89
|
+
}
|
90
|
+
|
91
|
+
int
|
92
|
+
sb_stemmer_length(struct sb_stemmer * stemmer)
|
93
|
+
{
|
94
|
+
return stemmer->env->l;
|
95
|
+
}
|
@@ -0,0 +1,95 @@
|
|
1
|
+
|
2
|
+
#include <stdlib.h>
|
3
|
+
#include <string.h>
|
4
|
+
#include "../include/libstemmer.h"
|
5
|
+
#include "../runtime/api.h"
|
6
|
+
#include "modules_utf8.h"
|
7
|
+
|
8
|
+
struct sb_stemmer {
|
9
|
+
struct SN_env * (*create)(void);
|
10
|
+
void (*close)(struct SN_env *);
|
11
|
+
int (*stem)(struct SN_env *);
|
12
|
+
|
13
|
+
struct SN_env * env;
|
14
|
+
};
|
15
|
+
|
16
|
+
extern const char **
|
17
|
+
sb_stemmer_list(void)
|
18
|
+
{
|
19
|
+
return algorithm_names;
|
20
|
+
}
|
21
|
+
|
22
|
+
static stemmer_encoding_t
|
23
|
+
sb_getenc(const char * charenc)
|
24
|
+
{
|
25
|
+
struct stemmer_encoding * encoding;
|
26
|
+
if (charenc == NULL) return ENC_UTF_8;
|
27
|
+
for (encoding = encodings; encoding->name != 0; encoding++) {
|
28
|
+
if (strcmp(encoding->name, charenc) == 0) break;
|
29
|
+
}
|
30
|
+
if (encoding->name == NULL) return ENC_UNKNOWN;
|
31
|
+
return encoding->enc;
|
32
|
+
}
|
33
|
+
|
34
|
+
extern struct sb_stemmer *
|
35
|
+
sb_stemmer_new(const char * algorithm, const char * charenc)
|
36
|
+
{
|
37
|
+
stemmer_encoding_t enc;
|
38
|
+
struct stemmer_modules * module;
|
39
|
+
struct sb_stemmer * stemmer;
|
40
|
+
|
41
|
+
enc = sb_getenc(charenc);
|
42
|
+
if (enc == ENC_UNKNOWN) return NULL;
|
43
|
+
|
44
|
+
for (module = modules; module->name != 0; module++) {
|
45
|
+
if (strcmp(module->name, algorithm) == 0 && module->enc == enc) break;
|
46
|
+
}
|
47
|
+
if (module->name == NULL) return NULL;
|
48
|
+
|
49
|
+
stemmer = (struct sb_stemmer *) malloc(sizeof(struct sb_stemmer));
|
50
|
+
if (stemmer == NULL) return NULL;
|
51
|
+
|
52
|
+
stemmer->create = module->create;
|
53
|
+
stemmer->close = module->close;
|
54
|
+
stemmer->stem = module->stem;
|
55
|
+
|
56
|
+
stemmer->env = stemmer->create();
|
57
|
+
if (stemmer->env == NULL)
|
58
|
+
{
|
59
|
+
sb_stemmer_delete(stemmer);
|
60
|
+
return NULL;
|
61
|
+
}
|
62
|
+
|
63
|
+
return stemmer;
|
64
|
+
}
|
65
|
+
|
66
|
+
void
|
67
|
+
sb_stemmer_delete(struct sb_stemmer * stemmer)
|
68
|
+
{
|
69
|
+
if (stemmer == 0) return;
|
70
|
+
if (stemmer->close == 0) return;
|
71
|
+
stemmer->close(stemmer->env);
|
72
|
+
stemmer->close = 0;
|
73
|
+
free(stemmer);
|
74
|
+
}
|
75
|
+
|
76
|
+
const sb_symbol *
|
77
|
+
sb_stemmer_stem(struct sb_stemmer * stemmer, const sb_symbol * word, int size)
|
78
|
+
{
|
79
|
+
int ret;
|
80
|
+
if (SN_set_current(stemmer->env, size, (const symbol *)(word)))
|
81
|
+
{
|
82
|
+
stemmer->env->l = 0;
|
83
|
+
return NULL;
|
84
|
+
}
|
85
|
+
ret = stemmer->stem(stemmer->env);
|
86
|
+
if (ret < 0) return NULL;
|
87
|
+
stemmer->env->p[stemmer->env->l] = 0;
|
88
|
+
return (const sb_symbol *)(stemmer->env->p);
|
89
|
+
}
|
90
|
+
|
91
|
+
int
|
92
|
+
sb_stemmer_length(struct sb_stemmer * stemmer)
|
93
|
+
{
|
94
|
+
return stemmer->env->l;
|
95
|
+
}
|