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.
- package/.npmignore +4 -11
- package/README.md +156 -41
- package/bayes_classifier.json +1 -0
- package/lib/natural/brill_pos_tagger/data/Dutch/README.txt +2 -0
- package/lib/natural/brill_pos_tagger/data/Dutch/brill_CONTEXTRULES.jg +285 -0
- package/lib/natural/brill_pos_tagger/data/Dutch/brill_LEXICON.jg +11699 -0
- package/lib/natural/brill_pos_tagger/data/English/README.txt +8 -0
- package/lib/natural/brill_pos_tagger/data/English/lexicon_from_posjs.json +297827 -0
- package/lib/natural/brill_pos_tagger/data/English/tr_from_brill_paper.txt +10 -0
- package/lib/natural/brill_pos_tagger/data/English/tr_from_posjs.txt +18 -0
- package/lib/natural/brill_pos_tagger/lib/Brill_POS_Tagger.js +136 -0
- package/lib/natural/brill_pos_tagger/lib/Predicate.js +410 -0
- package/lib/natural/brill_pos_tagger/lib/TF_Parser.js +717 -0
- package/lib/natural/brill_pos_tagger/lib/TF_Parser.pegjs +55 -0
- package/lib/natural/brill_pos_tagger/lib/TransformationRule.js +49 -0
- package/lib/natural/classifiers/bayes_classifier.js +6 -5
- package/lib/natural/classifiers/classifier.js +3 -2
- package/lib/natural/classifiers/logistic_regression_classifier.js +9 -5
- package/lib/natural/distance/dice_coefficient.js +22 -12
- package/lib/natural/index.js +6 -0
- package/lib/natural/ngrams/ngrams.js +4 -0
- package/lib/natural/stemmers/stemmer.js +31 -6
- package/lib/natural/tokenizers/regexp_tokenizer.js +3 -3
- package/{examples/inflection/noun.js → lib/natural/tokenizers/sentence_tokenizer.js} +14 -10
- package/lib/natural/tokenizers/tokenizer_case.js +58 -0
- package/lib/natural/util/bag.js +1 -0
- package/lib/natural/wordnet/wordnet.js +2 -2
- package/lib/natural/wordnet/wordnet_file.js +1 -1
- package/lr_classifier.json +1 -0
- package/package.json +6 -3
- package/package.json~ +66 -0
- package/benchmarks/index.js +0 -32
- package/benchmarks/metaphone.js +0 -27
- package/benchmarks/soundex.js +0 -27
- package/examples/classification/basic.js +0 -35
- package/examples/classification/recall.js +0 -28
- package/examples/classification/store.js +0 -37
- package/examples/inflection/count.js +0 -35
- package/examples/inflection/noun_attach.js +0 -33
- package/examples/phonetics/compare.js +0 -39
- package/examples/phonetics/sounds_like.js +0 -40
- package/examples/phonetics/tokenize_and_phoneticize.js +0 -54
- package/examples/stemming/stem_corpus.js +0 -29
- package/examples/stemming/stem_word.js +0 -26
- package/examples/tfidf/array_example.js +0 -34
- package/examples/tfidf/multiple_terms.js +0 -33
- package/examples/tfidf/tfidf_example.js +0 -44
- package/io_spec/test_data/tfidf/one +0 -1
- package/io_spec/test_data/tfidf/two +0 -1
- package/io_spec/tfidf_spec.js +0 -50
- package/io_spec/wordnet_spec.js +0 -81
- package/spec/aggressive_tokenizer_es_spec.js +0 -36
- package/spec/aggressive_tokenizer_fr_spec.js +0 -101
- package/spec/aggressive_tokenizer_nl_spec.js +0 -36
- package/spec/aggressive_tokenizer_pt_spec.js +0 -56
- package/spec/aggressive_tokenizer_spec.js +0 -56
- package/spec/bayes_classifier_spec.js +0 -173
- package/spec/classifier_spec.js +0 -175
- package/spec/count_inflector_fr_spec.js +0 -44
- package/spec/count_inflector_spec.js +0 -73
- package/spec/dice_coefficient_spec.js +0 -26
- package/spec/double_metaphone_spec.js +0 -752
- package/spec/jaro-winkler_spec.js +0 -53
- package/spec/lancaster_stemmer_spec.js +0 -73
- package/spec/levenshtein_spec.js +0 -66
- package/spec/logistic_regression_classifier_spec.js +0 -122
- package/spec/longest_path_tree_spec.js +0 -102
- package/spec/metaphone_spec.js +0 -252
- package/spec/ngram_spec.js +0 -130
- package/spec/ngram_zh_spec.js +0 -122
- package/spec/normalizer_ja_spec.js +0 -160
- package/spec/normalizer_no_spec.js +0 -111
- package/spec/normalizer_spec.js +0 -140
- package/spec/noun_inflector_fr_spec.js +0 -476
- package/spec/noun_inflector_ja_spec.js +0 -112
- package/spec/noun_inflector_spec.js +0 -270
- package/spec/porter_stemmer_fr_spec.js +0 -101
- package/spec/porter_stemmer_it_spec.js +0 -44
- package/spec/porter_stemmer_no_spec.js +0 -143
- package/spec/porter_stemmer_pt_spec.js +0 -50
- package/spec/porter_stemmer_ru_spec.js +0 -63
- package/spec/porter_stemmer_spec.js +0 -182
- package/spec/present_verb_inflector_spec.js +0 -128
- package/spec/remove_diacritics_spec.js +0 -31
- package/spec/sentence_analyzer_spec.js +0 -277
- package/spec/shortest_path_tree_spec.js +0 -132
- package/spec/soundex_spec.js +0 -158
- package/spec/spellcheck_spec.js +0 -92
- package/spec/stemmer_ja_spec.js +0 -66
- package/spec/stemmer_token_spec.js +0 -161
- package/spec/test_data/snowball_fr.txt +0 -20402
- package/spec/test_data/snowball_it.txt +0 -35482
- package/spec/test_data/snowball_no.txt +0 -20628
- package/spec/test_data/snowball_pt.txt +0 -32016
- package/spec/test_data/tfdif_testcorpus.txt +0 -7
- package/spec/test_data/tfidf_document1.txt +0 -1
- package/spec/test_data/tfidf_document2.txt +0 -1
- package/spec/test_data/tfidf_document3.txt +0 -1
- package/spec/test_data/tfidf_document4.txt +0 -1
- package/spec/test_data/tfidf_teststopwords.txt +0 -1
- package/spec/test_data/wordnet_mini.sql +0 -95
- package/spec/tfidf_spec.js +0 -323
- package/spec/tokenizer_ja_spec.js +0 -58
- package/spec/transliterator_ja_spec.js +0 -103
- package/spec/treebank_word_tokenizer_spec.js +0 -36
- package/spec/trie_spec.js +0 -206
|
@@ -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;
|