natural 0.1.28 → 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 (117) hide show
  1. package/.editorconfig +7 -0
  2. package/.npmignore +4 -11
  3. package/README.md +190 -50
  4. package/bayes_classifier.json +1 -0
  5. package/lib/natural/analyzers/sentence_analyzer.js +8 -5
  6. package/lib/natural/brill_pos_tagger/data/Dutch/README.txt +2 -0
  7. package/lib/natural/brill_pos_tagger/data/Dutch/brill_CONTEXTRULES.jg +285 -0
  8. package/lib/natural/brill_pos_tagger/data/Dutch/brill_LEXICON.jg +11699 -0
  9. package/lib/natural/brill_pos_tagger/data/English/README.txt +8 -0
  10. package/lib/natural/brill_pos_tagger/data/English/lexicon_from_posjs.json +297827 -0
  11. package/lib/natural/brill_pos_tagger/data/English/tr_from_brill_paper.txt +10 -0
  12. package/lib/natural/brill_pos_tagger/data/English/tr_from_posjs.txt +18 -0
  13. package/lib/natural/brill_pos_tagger/lib/Brill_POS_Tagger.js +136 -0
  14. package/lib/natural/brill_pos_tagger/lib/Predicate.js +410 -0
  15. package/lib/natural/brill_pos_tagger/lib/TF_Parser.js +717 -0
  16. package/lib/natural/brill_pos_tagger/lib/TF_Parser.pegjs +55 -0
  17. package/lib/natural/brill_pos_tagger/lib/TransformationRule.js +49 -0
  18. package/lib/natural/classifiers/bayes_classifier.js +6 -5
  19. package/lib/natural/classifiers/classifier.js +3 -2
  20. package/lib/natural/classifiers/logistic_regression_classifier.js +9 -5
  21. package/lib/natural/distance/dice_coefficient.js +22 -12
  22. package/lib/natural/distance/jaro-winkler_distance.js +13 -8
  23. package/lib/natural/index.js +6 -0
  24. package/lib/natural/inflectors/present_verb_inflector.js +1 -0
  25. package/lib/natural/ngrams/ngrams.js +6 -0
  26. package/lib/natural/normalizers/normalizer_ja.js +26 -8
  27. package/lib/natural/phonetics/double_metaphone.js +9 -4
  28. package/lib/natural/phonetics/metaphone.js +4 -0
  29. package/lib/natural/phonetics/soundex.js +11 -7
  30. package/lib/natural/spellcheck/spellcheck.js +80 -0
  31. package/lib/natural/stemmers/porter_stemmer.js +90 -62
  32. package/lib/natural/stemmers/porter_stemmer_fr.js +8 -3
  33. package/lib/natural/stemmers/porter_stemmer_pt.js +302 -0
  34. package/lib/natural/stemmers/stemmer.js +31 -6
  35. package/lib/natural/stemmers/stemmer_pt.js +65 -0
  36. package/lib/natural/stemmers/token.js +163 -0
  37. package/lib/natural/tfidf/tfidf.js +49 -18
  38. package/lib/natural/tokenizers/regexp_tokenizer.js +3 -3
  39. package/{examples/inflection/noun.js → lib/natural/tokenizers/sentence_tokenizer.js} +14 -10
  40. package/lib/natural/tokenizers/tokenizer_case.js +58 -0
  41. package/lib/natural/util/bag.js +1 -0
  42. package/lib/natural/util/stopwords_pt.js +136 -0
  43. package/lib/natural/wordnet/wordnet.js +2 -2
  44. package/lib/natural/wordnet/wordnet_file.js +1 -1
  45. package/lr_classifier.json +1 -0
  46. package/package.json +7 -4
  47. package/package.json~ +66 -0
  48. package/benchmarks/index.js +0 -32
  49. package/benchmarks/metaphone.js +0 -27
  50. package/benchmarks/soundex.js +0 -27
  51. package/examples/classification/basic.js +0 -35
  52. package/examples/classification/recall.js +0 -28
  53. package/examples/classification/store.js +0 -37
  54. package/examples/inflection/count.js +0 -35
  55. package/examples/inflection/noun_attach.js +0 -33
  56. package/examples/phonetics/compare.js +0 -39
  57. package/examples/phonetics/sounds_like.js +0 -40
  58. package/examples/phonetics/tokenize_and_phoneticize.js +0 -54
  59. package/examples/stemming/stem_corpus.js +0 -29
  60. package/examples/stemming/stem_word.js +0 -26
  61. package/examples/tfidf/array_example.js +0 -34
  62. package/examples/tfidf/multiple_terms.js +0 -33
  63. package/examples/tfidf/tfidf_example.js +0 -44
  64. package/io_spec/test_data/tfidf/one +0 -1
  65. package/io_spec/test_data/tfidf/two +0 -1
  66. package/io_spec/tfidf_spec.js +0 -50
  67. package/io_spec/wordnet_spec.js +0 -81
  68. package/spec/aggressive_tokenizer_es_spec.js +0 -36
  69. package/spec/aggressive_tokenizer_fr_spec.js +0 -101
  70. package/spec/aggressive_tokenizer_nl_spec.js +0 -36
  71. package/spec/aggressive_tokenizer_pt_spec.js +0 -56
  72. package/spec/aggressive_tokenizer_spec.js +0 -56
  73. package/spec/bayes_classifier_spec.js +0 -173
  74. package/spec/classifier_spec.js +0 -91
  75. package/spec/count_inflector_fr_spec.js +0 -44
  76. package/spec/count_inflector_spec.js +0 -73
  77. package/spec/dice_coefficient_spec.js +0 -26
  78. package/spec/double_metaphone_spec.js +0 -743
  79. package/spec/jaro-winkler_spec.js +0 -53
  80. package/spec/lancaster_stemmer_spec.js +0 -73
  81. package/spec/levenshtein_spec.js +0 -66
  82. package/spec/logistic_regression_classifier_spec.js +0 -122
  83. package/spec/longest_path_tree_spec.js +0 -102
  84. package/spec/metaphone_spec.js +0 -247
  85. package/spec/ngram_spec.js +0 -130
  86. package/spec/ngram_zh_spec.js +0 -122
  87. package/spec/normalizer_ja_spec.js +0 -154
  88. package/spec/normalizer_no_spec.js +0 -111
  89. package/spec/normalizer_spec.js +0 -118
  90. package/spec/noun_inflector_fr_spec.js +0 -476
  91. package/spec/noun_inflector_ja_spec.js +0 -112
  92. package/spec/noun_inflector_spec.js +0 -270
  93. package/spec/porter_stemmer_fr_spec.js +0 -101
  94. package/spec/porter_stemmer_it_spec.js +0 -44
  95. package/spec/porter_stemmer_no_spec.js +0 -143
  96. package/spec/porter_stemmer_ru_spec.js +0 -63
  97. package/spec/porter_stemmer_spec.js +0 -137
  98. package/spec/present_verb_inflector_spec.js +0 -125
  99. package/spec/sentence_analyzer_spec.js +0 -29
  100. package/spec/shortest_path_tree_spec.js +0 -132
  101. package/spec/soundex_spec.js +0 -154
  102. package/spec/stemmer_ja_spec.js +0 -66
  103. package/spec/test_data/snowball_fr.txt +0 -20402
  104. package/spec/test_data/snowball_it.txt +0 -35482
  105. package/spec/test_data/snowball_no.txt +0 -20628
  106. package/spec/test_data/tfdif_testcorpus.txt +0 -7
  107. package/spec/test_data/tfidf_document1.txt +0 -1
  108. package/spec/test_data/tfidf_document2.txt +0 -1
  109. package/spec/test_data/tfidf_document3.txt +0 -1
  110. package/spec/test_data/tfidf_document4.txt +0 -1
  111. package/spec/test_data/tfidf_teststopwords.txt +0 -1
  112. package/spec/test_data/wordnet_mini.sql +0 -95
  113. package/spec/tfidf_spec.js +0 -198
  114. package/spec/tokenizer_ja_spec.js +0 -58
  115. package/spec/transliterator_ja_spec.js +0 -103
  116. package/spec/treebank_word_tokenizer_spec.js +0 -36
  117. package/spec/trie_spec.js +0 -206
package/.editorconfig ADDED
@@ -0,0 +1,7 @@
1
+ root = true
2
+
3
+ [*]
4
+ end_of_line = lf
5
+ insert_final_newline = true
6
+ indent_style = space
7
+ indent_size = 2
package/.npmignore CHANGED
@@ -1,11 +1,4 @@
1
- *~
2
- \#*
3
- *.kpf
4
- *classifier.json
5
- node_modules
6
- io_spec/test_data/wordnet/download/*
7
- *.noun
8
- *.verb
9
- *.adj
10
- *.adv
11
- npm-debug.log
1
+ benchmarks
2
+ spec
3
+ examples
4
+ io_spec
package/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  natural
2
2
  =======
3
3
 
4
+ [![NPM version](https://img.shields.io/npm/v/natural.svg)](https://www.npmjs.com/package/natural)
4
5
  [![Build Status](https://travis-ci.org/NaturalNode/natural.png?branch=master)](https://travis-ci.org/NaturalNode/natural)
5
6
 
6
7
  "Natural" is a general natural language facility for nodejs. Tokenizing,
@@ -18,8 +19,30 @@ will be in order. Thanks to Polyakov Vladimir, Russian stemming has been added!,
18
19
 
19
20
  Aside from this README, the only documentation is [this DZone article](http://www.dzone.com/links/r/using_natural_a_nlp_module_for_nodejs.html) and [here on my blog](http://www.chrisumbel.com/article/node_js_natural_language_porter_stemmer_lancaster_bayes_naive_metaphone_soundex), which is a bit older.
20
21
 
21
- Installation
22
- ------------
22
+ ### TABLE OF CONTENTS
23
+
24
+ * [Installation](#installation)
25
+ * [Tokenizers](#tokenizers)
26
+ * [String Distance](#string-distance)
27
+ * [Stemmers](#stemmers)
28
+ * [Classifiers](#classifiers)
29
+ * [Phonetics](#phonetics)
30
+ * [Inflectors](#inflectors)
31
+ * [N-Grams](#n-grams)
32
+ * [tf-idf](#tf-idf)
33
+ * [Tries](#tries)
34
+ * [EdgeWeightedDigraph](#edgeweighteddigraph)
35
+ * [ShortestPathTree](#shortestpathtree)
36
+ * [LongestPathTree](#longestpathtree)
37
+ * [WordNet](#wordnet)
38
+ * [Spellcheck](#spellcheck)
39
+ * [POS Tagger](#pos-tagger)
40
+ * [Acknowledgements/references](#acknowledgements-and-references)
41
+ * [Development](#development)
42
+ * [License](#license)
43
+
44
+
45
+ ## Installation
23
46
 
24
47
  If you're just looking to use natural without your own node application,
25
48
  you can install via NPM like so:
@@ -29,8 +52,7 @@ you can install via NPM like so:
29
52
  If you're interested in contributing to natural, or just hacking on it, then by all
30
53
  means fork away!
31
54
 
32
- Tokenizers
33
- ----------
55
+ ## Tokenizers
34
56
 
35
57
  Word, Regexp, and [Treebank tokenizers](http://www.cis.upenn.edu/~treebank/tokenization.html) are provided for breaking text up into
36
58
  arrays of tokens:
@@ -58,8 +80,8 @@ console.log(tokenizer.tokenize("my dog hasn't any fleas."));
58
80
  // [ 'my', 'dog', 'hasn', '\'', 't', 'any', 'fleas', '.' ]
59
81
  ```
60
82
 
61
- String Distance
62
- ----------------------
83
+ ## String Distance
84
+
63
85
  Natural provides an implementation of the [Jaro–Winkler](http://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance) string distance measuring algorithm.
64
86
  This will return a number between 0 and 1 which tells how closely the strings match (0 = not at all, 1 = exact match):
65
87
 
@@ -122,8 +144,7 @@ Output:
122
144
  0
123
145
  ```
124
146
 
125
- Stemmers
126
- --------
147
+ ## Stemmers
127
148
 
128
149
  Currently stemming is supported via the [Porter](http://tartarus.org/martin/PorterStemmer/index.html) and [Lancaster](http://www.comp.lancs.ac.uk/computing/research/stemming/) (Paice/Husk) algorithms.
129
150
 
@@ -167,8 +188,7 @@ console.log("i am waking up to the sounds of chainsaws".tokenizeAndStem());
167
188
  console.log("chainsaws".stem());
168
189
  ```
169
190
 
170
- Classifiers
171
- ----------------------
191
+ ## Classifiers
172
192
 
173
193
  Two classifiers are currently supported, [Naive Bayes](http://en.wikipedia.org/wiki/Naive_Bayes_classifier) and [logistic regression](http://en.wikipedia.org/wiki/Logistic_regression).
174
194
  The following examples use the BayesClassifier class, but the
@@ -184,7 +204,7 @@ tokenize and stem the text.
184
204
 
185
205
  ```javascript
186
206
  classifier.addDocument('i am long qqqq', 'buy');
187
- classifier.addDocument('buy the q''s', 'buy');
207
+ classifier.addDocument('buy the q\'s', 'buy');
188
208
  classifier.addDocument('short gold', 'sell');
189
209
  classifier.addDocument('sell gold', 'sell');
190
210
 
@@ -208,8 +228,8 @@ You have access to the set of matched classes and the associated value from the
208
228
  Outputs:
209
229
 
210
230
  ```javascript
211
- [ { label: 'sell', value: 0.39999999999999997 },
212
- { label: 'buy', value: 0.19999999999999998 } ]
231
+ [ { label: 'buy', value: 0.39999999999999997 },
232
+ { label: 'sell', value: 0.19999999999999998 } ]
213
233
  ```
214
234
 
215
235
  From this:
@@ -234,7 +254,8 @@ The training process can be monitored by subscribing to the event `trainedWithDo
234
254
  * total: 23 // There are 23 total documents being trained against
235
255
  * index: 12 // The index/number of the document that's just been trained against
236
256
  * doc: {...} // The document that has just been indexed
237
- */ }
257
+ * }
258
+ */
238
259
  });
239
260
 
240
261
  A classifier can also be persisted and recalled so you can reuse a training
@@ -268,8 +289,7 @@ var restoredClassifier = natural.BayesClassifier.restore(JSON.parse(raw));
268
289
  console.log(restoredClassifier.classify('i should sell that'));
269
290
  ```
270
291
 
271
- Phonetics
272
- ---------
292
+ ## Phonetics
273
293
 
274
294
  Phonetic matching (sounds-like) matching can be done with the [SoundEx](http://en.wikipedia.org/wiki/Soundex),
275
295
  [Metaphone](http://en.wikipedia.org/wiki/Metaphone) or [DoubleMetaphone](http://en.wikipedia.org/wiki/Metaphone#Double_Metaphone) algorithms
@@ -356,8 +376,7 @@ if(wordA.soundsLike(wordB))
356
376
  console.log('phonetics'.phonetics());
357
377
  ```
358
378
 
359
- Inflectors
360
- ----------
379
+ ## Inflectors
361
380
 
362
381
  ### Nouns
363
382
 
@@ -442,8 +461,7 @@ console.log('walks'.pluralizePresentVerb());
442
461
  ```
443
462
 
444
463
 
445
- N-Grams
446
- -------
464
+ ## N-Grams
447
465
 
448
466
  n-grams can be obtained for either arrays or strings (which will be tokenized
449
467
  for you):
@@ -534,8 +552,7 @@ console.log(NGramsZH.ngrams(['一', '个', '中', '文', '测',
534
552
  '试'], 4));
535
553
  ```
536
554
 
537
- tf-idf
538
- -----
555
+ ## tf-idf
539
556
 
540
557
  [Term Frequency–Inverse Document Frequency (tf-idf)](http://en.wikipedia.org/wiki/Tf%E2%80%93idf) is implemented to determine how important a word (or words) is to a
541
558
  document relative to a corpus. The following example will add four documents to
@@ -597,7 +614,7 @@ tfidf.addFileSync('data_files/two.txt');
597
614
 
598
615
  Multiple terms can be measured as well, with their weights being added into
599
616
  a single measure value. The following example determines that the last document
600
- is the most relevent to the words "node" and "ruby".
617
+ is the most relevant to the words "node" and "ruby".
601
618
 
602
619
  ```javascript
603
620
  var natural = require('natural'),
@@ -650,7 +667,7 @@ tfidf.listTerms(0 /*document index*/).forEach(function(item) {
650
667
  });
651
668
  ```
652
669
 
653
- A TfIdf instance can also be serialized and deserialzed for save and recall.
670
+ A TfIdf instance can also be serialized and deserialized for save and recall.
654
671
 
655
672
  ```javascript
656
673
  var tfidf = new TfIdf();
@@ -663,12 +680,11 @@ var s = JSON.stringify(tfidf);
663
680
  var tfidf = new TfIdf(JSON.parse(s));
664
681
  ```
665
682
 
666
- Tries
667
- -----
683
+ ## Tries
668
684
 
669
685
  Tries are a very efficient data structure used for prefix-based searches.
670
- Natural comes packaged with a basic Trie implementation wich can support match collection along a path,
671
- existance search and prefix search.
686
+ Natural comes packaged with a basic Trie implementation which can support match collection along a path,
687
+ existence search and prefix search.
672
688
 
673
689
  ### Building The Trie
674
690
 
@@ -741,9 +757,9 @@ ciTrie.contains("TEsT"); // true
741
757
  ```
742
758
  In the case of the searches which return strings, all strings returned will be in lower case if you are in case-_in_sensitive mode.
743
759
 
744
- EdgeWeightedDigraph
745
- -------------------
746
- EdgeWeightedDigraph represents a digraph, you can add an edge, get the number vertexs, edges, get all edges and use toString to print the Digraph.
760
+ ## EdgeWeightedDigraph
761
+
762
+ EdgeWeightedDigraph represents a digraph, you can add an edge, get the number vertexes, edges, get all edges and use toString to print the Digraph.
747
763
 
748
764
  initialize a digraph:
749
765
 
@@ -759,7 +775,7 @@ digraph.add(6,4,0.93);
759
775
  ```
760
776
  the api used is: add(from, to, weight).
761
777
 
762
- get the number of vertexs:
778
+ get the number of vertexes:
763
779
 
764
780
  ```javascript
765
781
  console.log(digraph.v());
@@ -775,8 +791,7 @@ you will get 5.
775
791
 
776
792
 
777
793
 
778
- ShortestPathTree
779
- ----------------
794
+ ## ShortestPathTree
780
795
 
781
796
  ShortestPathTree represents a data type for solving the single-source shortest paths problem in
782
797
  edge-weighted directed acyclic graphs (DAGs).
@@ -815,7 +830,7 @@ false
815
830
  ```
816
831
 
817
832
  ### pathTo(vertex)
818
- this will retuan a shortest path:
833
+ this will return a shortest path:
819
834
 
820
835
  ```javascript
821
836
  console.log(spt.pathTo(4));
@@ -827,8 +842,7 @@ output will be:
827
842
  [5, 4]
828
843
  ```
829
844
 
830
- LongestPathTree
831
- ----------------
845
+ ## LongestPathTree
832
846
 
833
847
  LongestPathTree represents a data type for solving the single-source shortest paths problem in
834
848
  edge-weighted directed acyclic graphs (DAGs).
@@ -867,7 +881,7 @@ false
867
881
  ```
868
882
 
869
883
  ### pathTo(vertex)
870
- this will retuan a shortest path:
884
+ this will return a shortest path:
871
885
 
872
886
  ```javascript
873
887
  console.log(spt.pathTo(4));
@@ -879,21 +893,18 @@ output will be:
879
893
  [5, 1, 3, 6, 4]
880
894
  ```
881
895
 
882
- WordNet
883
- -------
896
+ ## WordNet
884
897
 
885
898
  One of the newest and most experimental features in natural is WordNet integration. Here's an
886
899
  example of using natural to look up definitions of the word node. To use the WordNet module,
887
- first install the WordNet database files using the [WNdb module](https://github.com/moos/WNdb):
900
+ first install the WordNet database files using [wordnet-db](https://github.com/moos/wordnet-db):
888
901
 
889
- npm install WNdb
890
-
891
- (For node < v0.6, please use 'npm install WNdb@3.0.0')
902
+ npm install wordnet-db
892
903
 
893
904
  Keep in mind that the WordNet integration is to be considered experimental at this point,
894
- and not production-ready. The API is also subject to change.
905
+ and not production-ready. The API is also subject to change. For an implementation with vastly increased performance, as well as a command-line interface, see [wordpos](https://github.com/moos/wordpos).
895
906
 
896
- Here's an example of looking up definitions for the word, "node".
907
+ Here's an example of looking up definitions for the word "node".
897
908
 
898
909
  ```javascript
899
910
  var wordnet = new natural.WordNet();
@@ -935,8 +946,138 @@ As of v0.1.11, WordNet data files are no longer automatically downloaded.
935
946
 
936
947
  Princeton University "About WordNet." WordNet. Princeton University. 2010. <http://wordnet.princeton.edu>
937
948
 
938
- Development
939
- -----------
949
+ ## Spellcheck
950
+
951
+ A probabilistic spellchecker based on http://norvig.com/spell-correct.html
952
+
953
+ This is best constructed with an array of tokens from a corpus, but a simple list of words from a dictionary will work.
954
+
955
+ ```javascript
956
+ var corpus = ['something', 'soothing'];
957
+ var spellcheck = new Spellcheck(corpus);
958
+ ```
959
+
960
+ It uses the trie datastructure for fast boolean lookup of a word
961
+
962
+ ```javascript
963
+ spellcheck.isCorrect('cat'); // false
964
+ ```
965
+
966
+ It suggests corrections (sorted by probability in descending order) that are up to a maximum edit distance away from the input word. According to Norvig, a max distance of 1 will cover 80% to 95% of spelling mistakes. After a distance of 2, it becomes very slow.
967
+
968
+ ```javascript
969
+ spellcheck.getCorrections('soemthing', 1); // ['something']
970
+ spellcheck.getCorrections('soemthing', 2); // ['something', 'soothing']
971
+ ```
972
+
973
+ ## POS Tagger
974
+
975
+ This is a part-of-speech tagger based on Eric Brill's transformational
976
+ algorithm. Transformation rules are specified in external files.
977
+
978
+ ### Usage
979
+ ```javascript
980
+ var Tagger = require("./lib/natural").BrillPOSTagger;
981
+
982
+ var base_folder = "some_path/lib/natural/brill_pos_tagger";
983
+ var rules_file = base_folder + "/data/tr_from_posjs.txt";
984
+ var lexicon_file = base_folder + "/data/lexicon_from_posjs.json";
985
+ var default_category = 'N';
986
+
987
+ var tagger = new Tagger(lexicon_file, rules_file, default_category, function(error) {
988
+ if (error) {
989
+ console.log(error);
990
+ }
991
+ else {
992
+ var sentence = ["I", "see", "the", "man", "with", "the", "telescope"];
993
+ console.log(JSON.stringify(tagger.tag(sentence)));
994
+ }
995
+ });
996
+ ```
997
+
998
+ ### Lexicon
999
+ The lexicon is either a JSON file that has the following structure:
1000
+ ```javascript
1001
+ {
1002
+ "word1": ["cat1"],
1003
+ "word2": ["cat2", "cat3"],
1004
+ ...
1005
+ }
1006
+ ```
1007
+ or a text file:
1008
+ ```
1009
+ word1 cat1 cat2
1010
+ word2 cat3
1011
+ ...
1012
+ ```
1013
+ Words may have multiple categories in the lexicon file. The tagger uses only
1014
+ the first category specified.
1015
+
1016
+ ### Specifying transformation rules
1017
+ Transformation rules are specified as follows:
1018
+ ```
1019
+ OLD_CAT NEW_CAT PREDICATE PARAMETER
1020
+ ```
1021
+ This means that if the category of the current position is OLD_CAT and the predicate is true, the category is replaced by NEW_CAT. The predicate
1022
+ may use the parameter in different ways: sometimes the parameter is used for
1023
+ specifying the outcome of the predicate:
1024
+ ```
1025
+ NN CD CURRENT-WORD-IS-NUMBER YES
1026
+ ```
1027
+ This means that if the outcome of predicate CURRENT-WORD-IS-NUMBER is YES, the
1028
+ category is replaced by <code>CD</code>.
1029
+ The parameter can also be used to check the category of a word in the sentence:
1030
+ ```
1031
+ VBD NN PREV-TAG DT
1032
+ ```
1033
+ Here the category of the previous word must be <code>DT</code> for the rule to be applied.
1034
+
1035
+ ### Algorithm
1036
+ The tagger applies transformation rules that may change the category of words. The input sentence must be split into words which are assigned with categories. The tagged sentence is then processed from left to right. At each step all rules are applied once; rules are applied in the order in which they are specified. Algorithm:
1037
+ ```javascript
1038
+ function(sentence) {
1039
+ var tagged_sentence = new Array(sentence.length);
1040
+
1041
+ // snip
1042
+
1043
+ // Apply transformation rules
1044
+ for (var i = 0, size = sentence.length; i < size; i++) {
1045
+ this.transformation_rules.forEach(function(rule) {
1046
+ rule.apply(tagged_sentence, i);
1047
+ });
1048
+ }
1049
+ return(tagged_sentence);
1050
+ }
1051
+ ```
1052
+
1053
+ ### Adding a predicate
1054
+ Predicates are defined in module <code>lib/Predicate.js</code>. In that file
1055
+ a function must be created that serves as predicate. A predicate accepts a
1056
+ tagged sentence, the current position in the sentence that should be tagged, and
1057
+ the
1058
+ outcome(s) of the predicate. An example of a predicate that checks the category of the current word:
1059
+ ```javascript
1060
+ function current_word_is_tag(tagged_sentence, i, parameter) {
1061
+ return(tagged_sentence[i][0] === parameter);
1062
+ }
1063
+ ```
1064
+ Some predicates accept two parameters. Next step is to map a keyword to this predicate so that it can be used in the transformation rules. The mapping is also defined in <code>lib/Predicate.js</code>:
1065
+ ```javascript
1066
+ var predicates = {
1067
+ "CURRENT-WORD-IS-TAG": current_word_is_tag,
1068
+ "PREV-WORD-IS-CAP": prev_word_is_cap
1069
+ }
1070
+ ```
1071
+
1072
+ ### Acknowledgements and References
1073
+ * Part of speech tagger by Percy Wegmann, https://code.google.com/p/jspos/
1074
+ * Node.js version of jspos: https://github.com/neopunisher/pos-js
1075
+ * A simple rule-based part of speech tagger, Eric Brill, Published in: Proceeding ANLC '92 Proceedings of the third conference on Applied natural language processing, Pages 152-155. http://dl.acm.org/citation.cfm?id=974526
1076
+
1077
+
1078
+
1079
+ ## Development
1080
+
940
1081
  When developing, please:
941
1082
 
942
1083
  + Write unit tests
@@ -947,8 +1088,7 @@ The current configuration of the unit tests requires the following environment v
947
1088
  export NODE_PATH=.
948
1089
 
949
1090
 
950
- License
951
- -------
1091
+ ## License
952
1092
 
953
1093
  Copyright (c) 2011, 2012 Chris Umbel, Rob Ellis, Russell Mull
954
1094
 
@@ -0,0 +1 @@
1
+ {"classifier":{"classFeatures":{"computing":{"0":2,"1":2,"2":2,"3":3,"4":2,"5":2},"literature":{"2":2,"6":4,"7":2,"8":2}},"classTotals":{"computing":4,"literature":4},"totalExamples":7,"smoothing":1},"docs":[{"label":"computing","text":["fix","box"]},{"label":"computing","text":["write","code"]},{"label":"computing","text":["nasti","script","code"]},{"label":"literature","text":["write","book"]},{"label":"literature","text":["read","book"]},{"label":"literature","text":["studi","book"]}],"features":{"fix":1,"box":1,"write":2,"code":2,"nasti":1,"script":1,"book":3,"read":1,"studi":1},"stemmer":{},"lastAdded":6,"events":{"domain":null,"_events":{},"_maxListeners":10}}
@@ -135,13 +135,16 @@ Sentences.prototype.toString = function() {
135
135
  // This is quick and incomplete.
136
136
  Sentences.prototype.type = function(callback) {
137
137
  var callback = callback || false;
138
-
138
+
139
+ // Check for implicit you before popping a tag.
140
+ var implicitYou = this.implicitYou();
141
+
139
142
  // FIXME - punct seems useless
140
143
  var lastElement = this.posObj.punct();
141
144
  lastElement = (lastElement.length != 0) ? lastElement.pop() : this.posObj.tags.pop();
142
-
145
+
143
146
  if (lastElement.pos !== ".") {
144
- if (this.implicitYou()) {
147
+ if (implicitYou) {
145
148
  this.senType = "COMMAND";
146
149
  } else if (_(["WDT","WP","WP$","WRB"]).contains(this.posObj.tags[0].pos)) {
147
150
  // Sentences that start with: who, what where when why and how, then they are questions
@@ -158,8 +161,8 @@ Sentences.prototype.type = function(callback) {
158
161
  } else {
159
162
  switch(lastElement.token) {
160
163
  case "?": this.senType = "INTERROGATIVE"; break;
161
- case "!": this.senType = (this.implicitYou()) ? "COMMAND":"EXCLAMATORY"; break;
162
- case ".": this.senType = (this.implicitYou()) ? "COMMAND":"DECLARATIVE"; break;
164
+ case "!": this.senType = (implicitYou) ? "COMMAND":"EXCLAMATORY"; break;
165
+ case ".": this.senType = (implicitYou) ? "COMMAND":"DECLARATIVE"; break;
163
166
  }
164
167
  }
165
168
 
@@ -0,0 +1,2 @@
1
+ Transformation rules and lexicon are from
2
+ https://mlnl.net/jg/software/bnl/