natural 0.2.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/.npmignore +4 -11
  2. package/README.md +156 -41
  3. package/bayes_classifier.json +1 -0
  4. package/lib/natural/brill_pos_tagger/data/Dutch/README.txt +2 -0
  5. package/lib/natural/brill_pos_tagger/data/Dutch/brill_CONTEXTRULES.jg +285 -0
  6. package/lib/natural/brill_pos_tagger/data/Dutch/brill_LEXICON.jg +11699 -0
  7. package/lib/natural/brill_pos_tagger/data/English/README.txt +8 -0
  8. package/lib/natural/brill_pos_tagger/data/English/lexicon_from_posjs.json +297827 -0
  9. package/lib/natural/brill_pos_tagger/data/English/tr_from_brill_paper.txt +10 -0
  10. package/lib/natural/brill_pos_tagger/data/English/tr_from_posjs.txt +18 -0
  11. package/lib/natural/brill_pos_tagger/lib/Brill_POS_Tagger.js +136 -0
  12. package/lib/natural/brill_pos_tagger/lib/Predicate.js +410 -0
  13. package/lib/natural/brill_pos_tagger/lib/TF_Parser.js +717 -0
  14. package/lib/natural/brill_pos_tagger/lib/TF_Parser.pegjs +55 -0
  15. package/lib/natural/brill_pos_tagger/lib/TransformationRule.js +49 -0
  16. package/lib/natural/classifiers/bayes_classifier.js +6 -5
  17. package/lib/natural/classifiers/classifier.js +3 -2
  18. package/lib/natural/classifiers/logistic_regression_classifier.js +9 -5
  19. package/lib/natural/distance/dice_coefficient.js +22 -12
  20. package/lib/natural/index.js +6 -0
  21. package/lib/natural/ngrams/ngrams.js +4 -0
  22. package/lib/natural/stemmers/stemmer.js +31 -6
  23. package/lib/natural/tokenizers/regexp_tokenizer.js +3 -3
  24. package/{examples/inflection/noun.js → lib/natural/tokenizers/sentence_tokenizer.js} +14 -10
  25. package/lib/natural/tokenizers/tokenizer_case.js +58 -0
  26. package/lib/natural/util/bag.js +1 -0
  27. package/lib/natural/wordnet/wordnet.js +2 -2
  28. package/lib/natural/wordnet/wordnet_file.js +1 -1
  29. package/lr_classifier.json +1 -0
  30. package/package.json +6 -3
  31. package/package.json~ +66 -0
  32. package/benchmarks/index.js +0 -32
  33. package/benchmarks/metaphone.js +0 -27
  34. package/benchmarks/soundex.js +0 -27
  35. package/examples/classification/basic.js +0 -35
  36. package/examples/classification/recall.js +0 -28
  37. package/examples/classification/store.js +0 -37
  38. package/examples/inflection/count.js +0 -35
  39. package/examples/inflection/noun_attach.js +0 -33
  40. package/examples/phonetics/compare.js +0 -39
  41. package/examples/phonetics/sounds_like.js +0 -40
  42. package/examples/phonetics/tokenize_and_phoneticize.js +0 -54
  43. package/examples/stemming/stem_corpus.js +0 -29
  44. package/examples/stemming/stem_word.js +0 -26
  45. package/examples/tfidf/array_example.js +0 -34
  46. package/examples/tfidf/multiple_terms.js +0 -33
  47. package/examples/tfidf/tfidf_example.js +0 -44
  48. package/io_spec/test_data/tfidf/one +0 -1
  49. package/io_spec/test_data/tfidf/two +0 -1
  50. package/io_spec/tfidf_spec.js +0 -50
  51. package/io_spec/wordnet_spec.js +0 -81
  52. package/spec/aggressive_tokenizer_es_spec.js +0 -36
  53. package/spec/aggressive_tokenizer_fr_spec.js +0 -101
  54. package/spec/aggressive_tokenizer_nl_spec.js +0 -36
  55. package/spec/aggressive_tokenizer_pt_spec.js +0 -56
  56. package/spec/aggressive_tokenizer_spec.js +0 -56
  57. package/spec/bayes_classifier_spec.js +0 -173
  58. package/spec/classifier_spec.js +0 -175
  59. package/spec/count_inflector_fr_spec.js +0 -44
  60. package/spec/count_inflector_spec.js +0 -73
  61. package/spec/dice_coefficient_spec.js +0 -26
  62. package/spec/double_metaphone_spec.js +0 -752
  63. package/spec/jaro-winkler_spec.js +0 -53
  64. package/spec/lancaster_stemmer_spec.js +0 -73
  65. package/spec/levenshtein_spec.js +0 -66
  66. package/spec/logistic_regression_classifier_spec.js +0 -122
  67. package/spec/longest_path_tree_spec.js +0 -102
  68. package/spec/metaphone_spec.js +0 -252
  69. package/spec/ngram_spec.js +0 -130
  70. package/spec/ngram_zh_spec.js +0 -122
  71. package/spec/normalizer_ja_spec.js +0 -160
  72. package/spec/normalizer_no_spec.js +0 -111
  73. package/spec/normalizer_spec.js +0 -140
  74. package/spec/noun_inflector_fr_spec.js +0 -476
  75. package/spec/noun_inflector_ja_spec.js +0 -112
  76. package/spec/noun_inflector_spec.js +0 -270
  77. package/spec/porter_stemmer_fr_spec.js +0 -101
  78. package/spec/porter_stemmer_it_spec.js +0 -44
  79. package/spec/porter_stemmer_no_spec.js +0 -143
  80. package/spec/porter_stemmer_pt_spec.js +0 -50
  81. package/spec/porter_stemmer_ru_spec.js +0 -63
  82. package/spec/porter_stemmer_spec.js +0 -182
  83. package/spec/present_verb_inflector_spec.js +0 -128
  84. package/spec/remove_diacritics_spec.js +0 -31
  85. package/spec/sentence_analyzer_spec.js +0 -277
  86. package/spec/shortest_path_tree_spec.js +0 -132
  87. package/spec/soundex_spec.js +0 -158
  88. package/spec/spellcheck_spec.js +0 -92
  89. package/spec/stemmer_ja_spec.js +0 -66
  90. package/spec/stemmer_token_spec.js +0 -161
  91. package/spec/test_data/snowball_fr.txt +0 -20402
  92. package/spec/test_data/snowball_it.txt +0 -35482
  93. package/spec/test_data/snowball_no.txt +0 -20628
  94. package/spec/test_data/snowball_pt.txt +0 -32016
  95. package/spec/test_data/tfdif_testcorpus.txt +0 -7
  96. package/spec/test_data/tfidf_document1.txt +0 -1
  97. package/spec/test_data/tfidf_document2.txt +0 -1
  98. package/spec/test_data/tfidf_document3.txt +0 -1
  99. package/spec/test_data/tfidf_document4.txt +0 -1
  100. package/spec/test_data/tfidf_teststopwords.txt +0 -1
  101. package/spec/test_data/wordnet_mini.sql +0 -95
  102. package/spec/tfidf_spec.js +0 -323
  103. package/spec/tokenizer_ja_spec.js +0 -58
  104. package/spec/transliterator_ja_spec.js +0 -103
  105. package/spec/treebank_word_tokenizer_spec.js +0 -36
  106. package/spec/trie_spec.js +0 -206
@@ -0,0 +1,10 @@
1
+ TO IN NEXT-TAG AT
2
+ VBN VBD PREV-WORD-IS-CAP YES
3
+ VBD VBN PREV-1-OR-2-OR-3-TAG HVD
4
+ VB NN PREV-1-OR-2-TAG AT
5
+ NN VB PREV-TAG TO
6
+ TO IN NEXT-WORD-IS-CAP YES
7
+ NN VB PREV-TAG MD
8
+ PPS PPO NEXT-TAG .
9
+ VBN VBD PREV-TAG PPS
10
+ NP NN CURRENT-WORD-IS-CAP NO
@@ -0,0 +1,18 @@
1
+ VBD NN PREV-TAG DT
2
+ VBP NN PREV-TAG DT
3
+ VB NN PREV-TAG DT
4
+ NN CD CURRENT-WORD-IS-NUMBER YES
5
+ NNP CD CURRENT-WORD-IS-NUMBER YES
6
+ NNS CD CURRENT-WORD-IS-NUMBER YES
7
+ NNPS CD CURRENT-WORD-IS-NUMBER YES
8
+ NN URL CURRENT-WORD-IS-URL YES
9
+ NNS URL CURRENT-WORD-IS-URL YES
10
+ NNP URL CURRENT-WORD-IS-URL YES
11
+ NNPS URL CURRENT-WORD-IS-URL YES
12
+ NN VBN CURRENT-WORD-ENDS-WITH ed
13
+ * RB CURRENT-WORD-ENDS-WITH ly
14
+ NN JJ CURRENT-WORD-ENDS-WITH al
15
+ NNS JJ CURRENT-WORD-ENDS-WITH al
16
+ NN VB PREV-WORD-IS would
17
+ NN NNS CURRENT-WORD-ENDS-WITH s
18
+ NN VBG CURRENT-WORD-ENDS-WITH ing
@@ -0,0 +1,136 @@
1
+ /*
2
+ Brill's POS Tagger
3
+ Copyright (C) 2015 Hugo W.L. ter Doest
4
+
5
+ This program is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU 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
+ This program 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 General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License
16
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+ var log4js = require('log4js');
20
+ var logger = log4js.getLogger();
21
+
22
+ var fs = require("fs");
23
+
24
+ var TF_Parser = require('./TF_Parser');
25
+
26
+ logger.setLevel('WARN');
27
+
28
+ // Tags a sentence, sentence is an array of words
29
+ // Returns an array of tagged words; a tagged words is an array consisting of
30
+ // the word itself followed by its lexical category
31
+ Brill_POS_Tagger.prototype.tag = function(sentence) {
32
+ var tagged_sentence = new Array(sentence.length);
33
+
34
+ // Initialise result
35
+ for (var i = 0, size = sentence.length; i < size; i++) {
36
+ var ss = this.lexicon[sentence[i]];
37
+ if (!ss) {
38
+ ss = this.lexicon[sentence[i].toLowerCase()];
39
+ }
40
+ tagged_sentence[i] = [];
41
+ tagged_sentence[i][0] = sentence[i];
42
+ if (!ss) { // If not found assign default_category
43
+ tagged_sentence[i][1] = this.default_category;
44
+ }
45
+ else {
46
+ tagged_sentence[i][1] = ss[0];
47
+ }
48
+ }
49
+ // Apply transformation rules
50
+ for (var i = 0, size = sentence.length; i < size; i++) {
51
+ this.transformation_rules.forEach(function(rule) {
52
+ rule.apply(tagged_sentence, i);
53
+ });
54
+ }
55
+ return(tagged_sentence);
56
+ };
57
+
58
+ Brill_POS_Tagger.prototype.parse_lexicon = function(data) {
59
+ var that = this;
60
+ // Split into an array of non-empty lines
61
+ var arrayOfLines = data.match(/[^\r\n]+/g);
62
+ this.lexicon = {};
63
+ arrayOfLines.forEach(function(line) {
64
+ // Split line by whitespace
65
+ var elements = line.trim().split(/\s+/);
66
+ if (elements.length > 0) {
67
+ that.lexicon[elements[0]] = elements.slice(1);
68
+ }
69
+ });
70
+ };
71
+
72
+ Brill_POS_Tagger.prototype.read_lexicon = function(lexicon_file,callback) {
73
+ var that = this;
74
+
75
+ // Read lexicon
76
+ fs.readFile(lexicon_file, 'utf8', function (error, data) {
77
+ if (error) {
78
+ logger.error(error);
79
+ callback(error);
80
+ }
81
+ else {
82
+ if (data[0] === "{") {
83
+ // Lexicon is in JSON format
84
+ that.lexicon = JSON.parse(data);
85
+ callback();
86
+ }
87
+ else {
88
+ // Lexicon is plain text
89
+ that.parse_lexicon(data);
90
+ callback();
91
+ }
92
+ logger.debug('Brill_POS_Tagger.read_lexicon: number of lexicon entries read: ' + Object.keys(that.lexicon).length);
93
+ }
94
+ });
95
+ };
96
+
97
+ Brill_POS_Tagger.prototype.read_transformation_rules = function(rules_file, callback) {
98
+ var that = this;
99
+
100
+ // Read transformation rules
101
+ fs.readFile(rules_file, 'utf8', function (err, data) {
102
+ if (err) {
103
+ logger.error(error);
104
+ callback(err);
105
+ }
106
+ else {
107
+ that.transformation_rules = TF_Parser.parse(data);
108
+ logger.debug(that.transformation_rules);
109
+ logger.debug('Brill_POS_Tagger.read_transformation_rules: number of transformation rules read: ' + that.transformation_rules.length);
110
+ callback();
111
+ }
112
+ });
113
+ };
114
+
115
+ function Brill_POS_Tagger(lexicon_file, rules_file, default_category, callback) {
116
+ var that = this;
117
+
118
+ this.default_category = default_category;
119
+ this.read_lexicon(lexicon_file, function(error) {
120
+ if (error) {
121
+ callback(error);
122
+ }
123
+ else {
124
+ that.read_transformation_rules(rules_file, function(error) {
125
+ if (error) {
126
+ callback(error);
127
+ }
128
+ else {
129
+ callback();
130
+ }
131
+ });
132
+ }
133
+ });
134
+ }
135
+
136
+ module.exports = Brill_POS_Tagger;
@@ -0,0 +1,410 @@
1
+ /*
2
+ Predicates for the Brill tagger
3
+ Copyright (C) 2015 Hugo W.L. ter Doest
4
+
5
+ This program is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU 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
+ This program 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 General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License
16
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+ var log4js = require('log4js');
20
+ var logger = log4js.getLogger();
21
+ logger.setLevel('WARN');
22
+
23
+ var predicates = {
24
+ // Predicates as used in the English rules in data/English/tr_from_posjs.txt
25
+ "NEXT-TAG": next_tag_is,
26
+ "NEXT-WORD-IS-CAP": next_word_is_cap,
27
+ "PREV-1-OR-2-OR-3-TAG": prev_1_or_2_or_3_tag,
28
+ "PREV-1-OR-2-TAG": prev_1_or_2_tag,
29
+ "NEXT-WORD-IS-TAG": next_tag_is,
30
+ "PREV-TAG": prev_tag_is,
31
+ "CURRENT-WORD-IS-TAG": current_word_is_tag,
32
+ "PREV-WORD-IS-CAP": prev_word_is_cap,
33
+ "CURRENT-WORD-IS-CAP": current_word_is_cap,
34
+ "CURRENT-WORD-IS-NUMBER": current_word_is_number,
35
+ "CURRENT-WORD-IS-URL": current_word_is_url,
36
+ "CURRENT-WORD-ENDS-WITH": current_word_ends_with,
37
+ "PREV-WORD-IS": prev_word_is,
38
+ // Predicates as used in the Dutch rules in data/Dutch/brill_CONTEXTRULES.jg
39
+ "PREVTAG": prev_tag_is,
40
+ "NEXT1OR2TAG": next_1_or_2_tag_is,
41
+ "NEXTTAG": next_tag_is,
42
+ "PREV1OR2TAG": prev_1_or_2_tag,
43
+ "WDAND2TAGAFT": current_word_and_2_tag_after_are,
44
+ "NEXT1OR2OR3TAG": next_1_or_2_or_3_tag,
45
+ "CURWD": current_word_is,
46
+ "SURROUNDTAG": surrounded_by_tags,
47
+ "PREV1OR2OR3TAG": prev_1_or_2_or_3_tag,
48
+ "WDNEXTTAG": current_word_and_next_tag_are,
49
+ "PREV1OR2WD": prev_1_or_2_word_is,
50
+ "NEXTWD": next_word_is,
51
+ "PREVWD": prev_word_is,
52
+ "NEXT2TAG": next_2_tag_is,
53
+ "WDAND2TAGBFR": current_word_and_2_tag_before_are,
54
+ "WDAND2AFT": current_word_and_2_after_are,
55
+ "WDPREVTAG": current_word_and_prev_tag_are,
56
+ "RBIGRAM": right_bigram_is,
57
+ "LBIGRAM": left_bigram_is,
58
+ "NEXTBIGRAM": next_bigram_is,
59
+ "PREVBIGRAM": prev_bigram_is,
60
+ "PREV2TAG": prev_2_tag_is,
61
+ "NEXT1OR2WD": next_1_or_2_word_is
62
+ };
63
+
64
+ // ==================================
65
+ // Predicates that start with words
66
+ // ==================================
67
+ function next_word_is_cap(tagged_sentence, i, parameter) {
68
+ if (i < tagged_sentence.length - 1) {
69
+ var next_word = tagged_sentence[i+1][0];
70
+ return(next_word[0] === next_word[0].toUpperCase());
71
+ }
72
+ else {
73
+ return(false);
74
+ }
75
+ }
76
+
77
+ function next_word_is(tagged_sentence, i, parameter) {
78
+ if (i < tagged_sentence.length - 1) {
79
+ return(tagged_sentence[i+1][0] === parameter);
80
+ }
81
+ }
82
+
83
+ function prev_word_is_cap(tagged_sentence, i, parameter) {
84
+ var prev_word = null;
85
+ if (i > 0) {
86
+ prev_word = tagged_sentence[i-1][0];
87
+ return(prev_word[0] === prev_word[0].toUpperCase());
88
+ }
89
+ return(false);
90
+ }
91
+
92
+ function current_word_is_cap(tagged_sentence, i, parameter) {
93
+ var current_word = tagged_sentence[i][0];
94
+ return(current_word[0] === current_word[0].toUpperCase());
95
+ }
96
+
97
+ function current_word_is(tagged_sentence, i, parameter) {
98
+ return(tagged_sentence[i][0] === parameter);
99
+ }
100
+
101
+ function isNumeric(num) {
102
+ return (!isNaN(num));
103
+ }
104
+
105
+ function current_word_is_number(tagged_sentence, i, parameter) {
106
+ var is_number = isNumeric(tagged_sentence[i][0]);
107
+ // Attempt to parse it as a float
108
+ if (!is_number) {
109
+ is_number = parseFloat(tagged_sentence[i][0]);
110
+ }
111
+ return((parameter === "YES") ? is_number : !is_number);
112
+ }
113
+
114
+ // Checks if the current word is a url
115
+ // Adapted from the original Javascript Brill tagger
116
+ function current_word_is_url(tagged_sentence, i, parameter) {
117
+ var is_url = false;
118
+ if (tagged_sentence[i][0].indexOf(".") > -1) {
119
+ // url if there are two contiguous alpha characters
120
+ if (/[a-zA-Z]{2}/.test(tagged_sentence[i][0])) {
121
+ is_url = true;
122
+ }
123
+ }
124
+ return((parameter === "YES") ? is_url : !is_url);
125
+ };
126
+
127
+ function current_word_and_2_tag_after_are(tagged_sentence, i, parameter1, parameter2) {
128
+ if (i < tagged_sentence.length - 2) {
129
+ if (tagged_sentence[i+2][1] === parameter2) {
130
+ return(tagged_sentence[i][0] === parameter1);
131
+ }
132
+ else {
133
+ return(false);
134
+ }
135
+ }
136
+ else {
137
+ return(false);
138
+ }
139
+ }
140
+
141
+ function current_word_and_next_tag_are(tagged_sentence, i, parameter1, parameter2) {
142
+ var next_tag = false;
143
+ // check current word
144
+ var current_word = (tagged_sentence[i][0] === parameter1);
145
+ // check next tag
146
+ if (i < tagged_sentence.length - 1) {
147
+ next_tag = (tagged_sentence[i+1][1] === parameter2);
148
+ }
149
+ return(current_word && next_tag);
150
+ }
151
+
152
+ function current_word_and_prev_tag_are(tagged_sentence, i, parameter1, parameter2) {
153
+ var prev_tag = false;
154
+ // check current word
155
+ var current_word = (tagged_sentence[i][0] === parameter2);
156
+ // check prev tag
157
+ if (i > 0) {
158
+ prev_tag = (tagged_sentence[i-1][1] === parameter1);
159
+ }
160
+ return(current_word && prev_tag);
161
+ }
162
+
163
+ function current_word_and_2_tag_before_are(tagged_sentence, i, parameter1, parameter2) {
164
+ var two_tags_before = false;
165
+ // check current word
166
+ var current_word = (tagged_sentence[i][0] === parameter2);
167
+ if (i > 1) {
168
+ // check two tags before
169
+ two_tags_before = (tagged_sentence[i-2][1] === parameter1);
170
+ }
171
+ return(current_word && two_tags_before);
172
+ }
173
+
174
+ function current_word_and_2_after_are(tagged_sentence, i, parameter1, parameter2) {
175
+ var two_words_after = false;
176
+ // check current word
177
+ var current_word = (tagged_sentence[i][0] === parameter1);
178
+ if (i < tagged_sentence - 2) {
179
+ two_words_after = (tagged_sentence[i+2][0] === parameter2);
180
+ }
181
+ return(current_word && two_words_after);
182
+ }
183
+
184
+ function prev_word_is(tagged_sentence, i, parameter) {
185
+ if (i > 0) {
186
+ return(tagged_sentence[i-1][0].toLowerCase() === parameter.toLowerCase());
187
+ }
188
+ else {
189
+ return(false);
190
+ }
191
+ };
192
+
193
+ function prev_1_or_2_word_is(tagged_sentence, i, parameter) {
194
+ var prev_1 = false;
195
+ var prev_2 = false;
196
+ if (i > 0) {
197
+ prev_1 = (tagged_sentence[i-1][0].toLowerCase() === parameter.toLowerCase());
198
+ }
199
+ if (i > 1) {
200
+ prev_2 = (tagged_sentence[i-2][0].toLowerCase() === parameter.toLowerCase());
201
+ }
202
+ return(prev_1 || prev_2);
203
+ };
204
+
205
+ // Indicates whether or not this string ends with the specified string.
206
+ // Adapted from the original Javascript Brill tagger
207
+ function current_word_ends_with(tagged_sentence, i, parameter) {
208
+ var word = tagged_sentence[i][0];
209
+ if (!parameter || (parameter.length > word.length)) {
210
+ return false;
211
+ }
212
+ return(word.indexOf(parameter) === (word.length - parameter.length));
213
+ }
214
+
215
+ function right_bigram_is(tagged_sentence, i, parameter1, parameter2) {
216
+ var word_1 = (tagged_sentence[i][0] === parameter1);
217
+ var word_2 = false;
218
+ if (i < tagged_sentence.length - 1) {
219
+ word_2 = (tagged_sentence[i+1][0] === parameter2);
220
+ }
221
+ return(word_1 && word_2);
222
+ }
223
+
224
+ function left_bigram_is(tagged_sentence, i, parameter1, parameter2) {
225
+ var word_1 = false;
226
+ var word_2 = (tagged_sentence[i][0] === parameter2);
227
+ if (i > 0) {
228
+ word_1 = (tagged_sentence[i-1][0] === parameter1);
229
+ }
230
+ return(word_1 && word_2);
231
+ }
232
+
233
+ function next_bigram_is(tagged_sentence, i, parameter1, parameter2) {
234
+ var word_1 = false;
235
+ var word_2 = false;
236
+ if (i < tagged_sentence.length - 1) {
237
+ word_1 = (tagged_sentence[i+1][0] === parameter1);
238
+ }
239
+ if (i < tagged_sentence.length - 2) {
240
+ word_2 = (tagged_sentence[i+2][0] === parameter2);
241
+ }
242
+ return(word_1 && word_2);
243
+ }
244
+
245
+ function prev_bigram_is(tagged_sentence, i, parameter1, parameter2) {
246
+ var word_1 = false;
247
+ var word_2 = false;
248
+ if (i > 1) {
249
+ word_1 = (tagged_sentence[i-2][0] === parameter1);
250
+ }
251
+ if (i > 0) {
252
+ word_2 = (tagged_sentence[i-1][0] === parameter2);
253
+ }
254
+ return(word_1 && word_2);
255
+ }
256
+
257
+ function next_1_or_2_word_is(tagged_sentence, i, parameter1, parameter2) {
258
+ next_1 = false;
259
+ next_2 = false;
260
+ if (i < tagged_sentence.length - 1) {
261
+ next_1 = (tagged_sentence[i+1][0] === parameter1);
262
+ }
263
+ if (i < tagged_sentence.length - 2) {
264
+ next_2 = (tagged_sentence[i+2][0] === parameter2);
265
+ }
266
+ return(next_1 || next_2);
267
+ }
268
+
269
+ // ==================================
270
+ // Predicates about tags
271
+ // ==================================
272
+ function next_tag_is(tagged_sentence, i, parameter) {
273
+ if (i < tagged_sentence.length - 1) {
274
+ return(tagged_sentence[i+1][1] === parameter);
275
+ }
276
+ else {
277
+ return(false);
278
+ }
279
+ }
280
+
281
+ function next_2_tag_is(tagged_sentence, i, parameter) {
282
+ if (i < tagged_sentence.length - 2) {
283
+ return(tagged_sentence[i+2][1] === parameter);
284
+ }
285
+ else {
286
+ return(false);
287
+ }
288
+ }
289
+
290
+ function next_1_or_2_tag_is(tagged_sentence, i, parameter) {
291
+ var next_1 = false;
292
+ var next_2 = false;
293
+ if (i < tagged_sentence.length - 1) {
294
+ next_1 = (tagged_sentence[i+1][1] === parameter);
295
+ }
296
+ if (i < tagged_sentence.length - 2) {
297
+ next_2 = (tagged_sentence[i+2][1] === parameter);
298
+ }
299
+ return(next_1 || next_2);
300
+ }
301
+
302
+ function next_1_or_2_or_3_tag(tagged_sentence, i, parameter) {
303
+ var next_1 = false;
304
+ var next_2 = false;
305
+ var next_3 = false;
306
+ if (i < tagged_sentence.length - 1) {
307
+ next_1 = (tagged_sentence[i+1][1] === parameter);
308
+ }
309
+ if (i < tagged_sentence.length - 2) {
310
+ next_2 = (tagged_sentence[i+2][1] === parameter);
311
+ }
312
+ if (i < tagged_sentence.length - 3) {
313
+ next_3 = (tagged_sentence[i+3][1] === parameter);
314
+ }
315
+ return(next_1 || next_2 || next_3);
316
+ }
317
+
318
+ function surrounded_by_tags(tagged_sentence, i, parameter1, parameter2) {
319
+ if (i < tagged_sentence.length - 1) {
320
+ // check next tag
321
+ if (tagged_sentence[i+1][1] === parameter2) {
322
+ // check previous tag
323
+ if (i > 0) {
324
+ return(tagged_sentence[i-1][1] === parameter1)
325
+ }
326
+ else {
327
+ return(false);
328
+ }
329
+ }
330
+ else {
331
+ return(false);
332
+ }
333
+ }
334
+ else {
335
+ return(false);
336
+ }
337
+ }
338
+
339
+ function prev_1_or_2_or_3_tag(tagged_sentence, i, parameter) {
340
+ var prev_1 = null;
341
+ if (i > 0) {
342
+ prev_1 = tagged_sentence[i-1][1];
343
+ }
344
+ var prev_2 = null;
345
+ if (i > 1) {
346
+ prev_2 = tagged_sentence[i-2][1];
347
+ }
348
+ var prev_3 = null;
349
+ if (i > 2) {
350
+ prev_3 = tagged_sentence[i-2][1];
351
+ }
352
+ return((prev_1 === parameter) || (prev_2 === parameter) || (prev_3 === parameter));
353
+ }
354
+
355
+ function prev_1_or_2_tag(tagged_sentence, i, parameter) {
356
+ var prev_1 = null;
357
+ if (i > 0) {
358
+ prev_1 = tagged_sentence[i-1][1];
359
+ }
360
+ var prev_2 = null;
361
+ if (i > 1) {
362
+ prev_2 = tagged_sentence[i-2][1];
363
+ }
364
+ return((prev_1 === parameter) || (prev_2 === parameter));
365
+ }
366
+
367
+ function prev_tag_is(tagged_sentence, i, parameter) {
368
+ var prev = false;
369
+ if (i > 0) {
370
+ prev = (tagged_sentence[i-1][1] === parameter);
371
+ }
372
+ return(prev);
373
+ }
374
+
375
+ function current_word_is_tag(tagged_sentence, i, parameter) {
376
+ return(tagged_sentence[i][0] === parameter);
377
+ }
378
+
379
+ function prev_2_tag_is(tagged_sentence, i, parameter) {
380
+ var prev_2 = false;
381
+ if (i > 1) {
382
+ prev_2 = (tagged_sentence[i-2][1] === parameter);
383
+ }
384
+ return(prev_2);
385
+ }
386
+
387
+ function default_transformation_rule (tagged_sentence, i, parameter) {
388
+ return(false);
389
+ }
390
+
391
+ function Predicate(name, parameter1, parameter2) {
392
+ this.name = name;
393
+ this.parameter1 = parameter1;
394
+ if (parameter2) {
395
+ this.parameter2 = parameter2;
396
+ }
397
+ this.function = predicates[name];
398
+ if (!this.function) {
399
+ this.predicate = default_transformation_rule;
400
+ logger.warn('Predicate constructor: predicate not found: ' + name + '; using default');
401
+ }
402
+ logger.debug(this.name);
403
+ logger.debug(this.function);
404
+ }
405
+
406
+ Predicate.prototype.evaluate = function(tagged_sentence, position) {
407
+ return(this.function(tagged_sentence, position, this.parameter1, this.parameter2));
408
+ };
409
+
410
+ module.exports = Predicate;