rley 0.7.03 → 0.7.08
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +362 -62
- data/.travis.yml +6 -7
- data/CHANGELOG.md +20 -1
- data/LICENSE.txt +1 -1
- data/README.md +6 -7
- data/Rakefile +2 -0
- data/appveyor.yml +2 -4
- data/examples/NLP/benchmark_pico_en.rb +2 -0
- data/examples/NLP/engtagger.rb +193 -188
- data/examples/NLP/nano_eng/nano_en_demo.rb +2 -0
- data/examples/NLP/nano_eng/nano_grammar.rb +7 -5
- data/examples/NLP/pico_en_demo.rb +2 -0
- data/examples/data_formats/JSON/cli_options.rb +3 -1
- data/examples/data_formats/JSON/json_ast_builder.rb +14 -9
- data/examples/data_formats/JSON/json_ast_nodes.rb +14 -21
- data/examples/data_formats/JSON/json_demo.rb +2 -0
- data/examples/data_formats/JSON/json_grammar.rb +4 -2
- data/examples/data_formats/JSON/json_lexer.rb +10 -8
- data/examples/data_formats/JSON/json_minifier.rb +3 -1
- data/examples/general/calc_iter1/calc_ast_builder.rb +15 -10
- data/examples/general/calc_iter1/calc_ast_nodes.rb +25 -37
- data/examples/general/calc_iter1/calc_demo.rb +2 -0
- data/examples/general/calc_iter1/calc_grammar.rb +4 -2
- data/examples/general/calc_iter1/calc_lexer.rb +8 -4
- data/examples/general/calc_iter1/spec/calculator_spec.rb +7 -5
- data/examples/general/calc_iter2/calc_ast_builder.rb +7 -3
- data/examples/general/calc_iter2/calc_ast_nodes.rb +29 -43
- data/examples/general/calc_iter2/calc_demo.rb +2 -0
- data/examples/general/calc_iter2/calc_grammar.rb +5 -3
- data/examples/general/calc_iter2/calc_lexer.rb +13 -10
- data/examples/general/calc_iter2/spec/calculator_spec.rb +28 -26
- data/examples/general/left.rb +4 -2
- data/examples/general/right.rb +4 -2
- data/lib/rley.rb +2 -0
- data/lib/rley/base/base_parser.rb +2 -0
- data/lib/rley/base/dotted_item.rb +38 -41
- data/lib/rley/base/grm_items_builder.rb +2 -0
- data/lib/rley/constants.rb +5 -3
- data/lib/rley/engine.rb +22 -24
- data/lib/rley/formatter/asciitree.rb +6 -4
- data/lib/rley/formatter/base_formatter.rb +2 -0
- data/lib/rley/formatter/bracket_notation.rb +3 -8
- data/lib/rley/formatter/debug.rb +8 -6
- data/lib/rley/formatter/json.rb +4 -2
- data/lib/rley/gfg/call_edge.rb +3 -1
- data/lib/rley/gfg/edge.rb +7 -5
- data/lib/rley/gfg/end_vertex.rb +4 -6
- data/lib/rley/gfg/epsilon_edge.rb +3 -5
- data/lib/rley/gfg/grm_flow_graph.rb +31 -25
- data/lib/rley/gfg/item_vertex.rb +12 -22
- data/lib/rley/gfg/non_terminal_vertex.rb +6 -4
- data/lib/rley/gfg/return_edge.rb +2 -0
- data/lib/rley/gfg/scan_edge.rb +3 -1
- data/lib/rley/gfg/shortcut_edge.rb +4 -2
- data/lib/rley/gfg/start_vertex.rb +6 -8
- data/lib/rley/gfg/vertex.rb +47 -41
- data/lib/rley/lexical/token.rb +3 -1
- data/lib/rley/lexical/token_range.rb +8 -6
- data/lib/rley/parse_forest_visitor.rb +7 -5
- data/lib/rley/parse_rep/ast_base_builder.rb +11 -11
- data/lib/rley/parse_rep/cst_builder.rb +7 -4
- data/lib/rley/parse_rep/parse_forest_builder.rb +36 -25
- data/lib/rley/parse_rep/parse_forest_factory.rb +5 -3
- data/lib/rley/parse_rep/parse_rep_creator.rb +18 -13
- data/lib/rley/parse_rep/parse_tree_builder.rb +15 -15
- data/lib/rley/parse_rep/parse_tree_factory.rb +27 -25
- data/lib/rley/parse_tree_visitor.rb +3 -1
- data/lib/rley/parser/error_reason.rb +9 -8
- data/lib/rley/parser/gfg_chart.rb +54 -22
- data/lib/rley/parser/gfg_earley_parser.rb +3 -1
- data/lib/rley/parser/gfg_parsing.rb +51 -31
- data/lib/rley/parser/parse_entry.rb +29 -33
- data/lib/rley/parser/parse_entry_set.rb +32 -27
- data/lib/rley/parser/parse_entry_tracker.rb +6 -4
- data/lib/rley/parser/parse_state.rb +18 -21
- data/lib/rley/parser/parse_state_tracker.rb +6 -4
- data/lib/rley/parser/parse_tracer.rb +15 -13
- data/lib/rley/parser/parse_walker_factory.rb +28 -29
- data/lib/rley/parser/state_set.rb +11 -10
- data/lib/rley/ptree/non_terminal_node.rb +10 -6
- data/lib/rley/ptree/parse_tree.rb +6 -4
- data/lib/rley/ptree/parse_tree_node.rb +7 -5
- data/lib/rley/ptree/terminal_node.rb +9 -7
- data/lib/rley/rley_error.rb +12 -10
- data/lib/rley/sppf/alternative_node.rb +8 -6
- data/lib/rley/sppf/composite_node.rb +9 -7
- data/lib/rley/sppf/epsilon_node.rb +5 -3
- data/lib/rley/sppf/leaf_node.rb +5 -3
- data/lib/rley/sppf/non_terminal_node.rb +2 -0
- data/lib/rley/sppf/parse_forest.rb +19 -17
- data/lib/rley/sppf/sppf_node.rb +9 -8
- data/lib/rley/sppf/token_node.rb +5 -3
- data/lib/rley/syntax/grammar.rb +7 -5
- data/lib/rley/syntax/grammar_builder.rb +11 -9
- data/lib/rley/syntax/grm_symbol.rb +8 -6
- data/lib/rley/syntax/literal.rb +2 -0
- data/lib/rley/syntax/non_terminal.rb +11 -15
- data/lib/rley/syntax/production.rb +13 -11
- data/lib/rley/syntax/symbol_seq.rb +10 -10
- data/lib/rley/syntax/terminal.rb +6 -5
- data/lib/rley/syntax/verbatim_symbol.rb +5 -3
- data/lib/support/base_tokenizer.rb +23 -20
- data/spec/rley/base/dotted_item_spec.rb +4 -2
- data/spec/rley/base/grm_items_builder_spec.rb +2 -0
- data/spec/rley/engine_spec.rb +47 -9
- data/spec/rley/formatter/asciitree_spec.rb +11 -9
- data/spec/rley/formatter/bracket_notation_spec.rb +16 -14
- data/spec/rley/formatter/debug_spec.rb +4 -2
- data/spec/rley/formatter/json_spec.rb +5 -3
- data/spec/rley/gfg/call_edge_spec.rb +2 -0
- data/spec/rley/gfg/edge_spec.rb +2 -0
- data/spec/rley/gfg/end_vertex_spec.rb +7 -5
- data/spec/rley/gfg/epsilon_edge_spec.rb +2 -0
- data/spec/rley/gfg/grm_flow_graph_spec.rb +2 -0
- data/spec/rley/gfg/item_vertex_spec.rb +12 -10
- data/spec/rley/gfg/non_terminal_vertex_spec.rb +5 -3
- data/spec/rley/gfg/return_edge_spec.rb +2 -0
- data/spec/rley/gfg/scan_edge_spec.rb +2 -0
- data/spec/rley/gfg/shortcut_edge_spec.rb +3 -1
- data/spec/rley/gfg/start_vertex_spec.rb +7 -5
- data/spec/rley/gfg/vertex_spec.rb +5 -3
- data/spec/rley/lexical/token_range_spec.rb +18 -16
- data/spec/rley/lexical/token_spec.rb +4 -2
- data/spec/rley/parse_forest_visitor_spec.rb +167 -163
- data/spec/rley/parse_rep/ambiguous_parse_spec.rb +46 -44
- data/spec/rley/parse_rep/ast_builder_spec.rb +8 -6
- data/spec/rley/parse_rep/cst_builder_spec.rb +7 -5
- data/spec/rley/parse_rep/groucho_spec.rb +25 -25
- data/spec/rley/parse_rep/parse_forest_builder_spec.rb +28 -26
- data/spec/rley/parse_rep/parse_forest_factory_spec.rb +8 -6
- data/spec/rley/parse_rep/parse_tree_factory_spec.rb +4 -2
- data/spec/rley/parse_tree_visitor_spec.rb +12 -8
- data/spec/rley/parser/error_reason_spec.rb +8 -6
- data/spec/rley/parser/gfg_chart_spec.rb +17 -4
- data/spec/rley/parser/gfg_earley_parser_spec.rb +16 -11
- data/spec/rley/parser/gfg_parsing_spec.rb +41 -252
- data/spec/rley/parser/parse_entry_set_spec.rb +2 -0
- data/spec/rley/parser/parse_entry_spec.rb +21 -19
- data/spec/rley/parser/parse_state_spec.rb +7 -5
- data/spec/rley/parser/parse_tracer_spec.rb +16 -14
- data/spec/rley/parser/parse_walker_factory_spec.rb +10 -8
- data/spec/rley/parser/state_set_spec.rb +24 -22
- data/spec/rley/ptree/non_terminal_node_spec.rb +7 -3
- data/spec/rley/ptree/parse_tree_node_spec.rb +6 -4
- data/spec/rley/ptree/parse_tree_spec.rb +2 -0
- data/spec/rley/ptree/terminal_node_spec.rb +8 -6
- data/spec/rley/sppf/alternative_node_spec.rb +8 -6
- data/spec/rley/sppf/non_terminal_node_spec.rb +5 -3
- data/spec/rley/sppf/token_node_spec.rb +6 -4
- data/spec/rley/support/ambiguous_grammar_helper.rb +5 -4
- data/spec/rley/support/expectation_helper.rb +2 -0
- data/spec/rley/support/grammar_abc_helper.rb +4 -4
- data/spec/rley/support/grammar_ambig01_helper.rb +6 -5
- data/spec/rley/support/grammar_arr_int_helper.rb +6 -5
- data/spec/rley/support/grammar_b_expr_helper.rb +6 -5
- data/spec/rley/support/grammar_helper.rb +2 -0
- data/spec/rley/support/grammar_l0_helper.rb +15 -16
- data/spec/rley/support/grammar_pb_helper.rb +8 -5
- data/spec/rley/support/grammar_sppf_helper.rb +3 -1
- data/spec/rley/syntax/grammar_builder_spec.rb +7 -5
- data/spec/rley/syntax/grammar_spec.rb +8 -6
- data/spec/rley/syntax/grm_symbol_spec.rb +3 -1
- data/spec/rley/syntax/literal_spec.rb +2 -0
- data/spec/rley/syntax/non_terminal_spec.rb +10 -8
- data/spec/rley/syntax/production_spec.rb +15 -13
- data/spec/rley/syntax/symbol_seq_spec.rb +4 -2
- data/spec/rley/syntax/terminal_spec.rb +7 -5
- data/spec/rley/syntax/verbatim_symbol_spec.rb +3 -1
- data/spec/spec_helper.rb +2 -12
- data/spec/support/base_tokenizer_spec.rb +9 -2
- metadata +21 -63
- data/.simplecov +0 -7
- data/Gemfile +0 -8
data/.travis.yml
CHANGED
@@ -9,17 +9,16 @@ script:
|
|
9
9
|
- bundle exec rake
|
10
10
|
|
11
11
|
rvm:
|
12
|
-
- 2.
|
13
|
-
- 2.
|
14
|
-
- 2.
|
15
|
-
- 2.
|
12
|
+
- 2.7.1
|
13
|
+
- 2.6.6
|
14
|
+
- 2.5.8
|
15
|
+
- 2.4.10
|
16
16
|
- ruby-head
|
17
|
-
- jruby-
|
18
|
-
|
17
|
+
- jruby-head
|
18
|
+
before_install: gem install bundler -v 2.0.2
|
19
19
|
|
20
20
|
matrix:
|
21
21
|
allow_failures:
|
22
|
-
- rvm: 2.6.0
|
23
22
|
- rvm: ruby-head
|
24
23
|
- rvm: jruby-head
|
25
24
|
|
data/CHANGELOG.md
CHANGED
@@ -1,10 +1,29 @@
|
|
1
|
+
### 0.7.07 / 2020-11-16
|
2
|
+
- Code restyling to please rubocop 0.93.1
|
3
|
+
* [CHANGE] File `.travis.yml`: updated Ruby versions, drop support for Ruby 2.3.x
|
4
|
+
|
5
|
+
### 0.7.06 / 2019-11-22
|
6
|
+
- [FIX] Method `ParseForestBuilder#process_end_entry`: Added a guard expression to prevent nil error.
|
7
|
+
|
8
|
+
### 0.7.05 / 2019-11-17
|
9
|
+
- [FIX] Method `GFGParsing#nullable_rule`: issue with nullable productions having at least one member in their rhs.
|
10
|
+
|
11
|
+
### 0.7.04 / 2019-08-17
|
12
|
+
- Rley recognizer is about 25% faster than previous version. Kudos to the people
|
13
|
+
behind the *magic_frozen_string_literal* gem.
|
14
|
+
- Code refactoring to use string frozen magic comments (as a consequence, Rley runs only on Rubies 2.3 or newer).
|
15
|
+
- Code restyling to please rubocop 0.7.40.
|
16
|
+
- [CHANGE] Class `ParseEntrySet`: minor code optimization
|
17
|
+
- [CHANGE] File `README.md` removed allusion to Ruby 2.0.x up to 2.2.x.
|
18
|
+
- [CHANGE] File `README.md` added Ruby 2.6.x up as supported version.
|
19
|
+
|
20
|
+
|
1
21
|
### 0.7.03 / 2019-07-21
|
2
22
|
- Minor refactoring for parsing speed improvement.
|
3
23
|
* [CHANGE] Replacing comparison with object_id by `equal?` method
|
4
24
|
* [CHANGE] Method `ParseEntry#hash` added
|
5
25
|
* [CHANGE] Class `ParseEntrySet` added new Hash attribute in order to speed up membership testing.
|
6
26
|
|
7
|
-
|
8
27
|
### 0.7.02 / 2019-01-13
|
9
28
|
- Removed Ruby versions older than 2.3 in CI testing because of breaking changes by Bundler 2.0
|
10
29
|
* [CHANGE] Files `Gemfile`, `.travis.yml`, `appveyor.yml` updated.
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -50,13 +50,11 @@ application range such as:
|
|
50
50
|
|
51
51
|
|
52
52
|
### Compatibility
|
53
|
-
Rley supports the following Ruby implementations:
|
54
|
-
- MRI 2.0
|
55
|
-
- MRI 2.1
|
56
|
-
- MRI 2.2
|
53
|
+
Rley supports the following Ruby implementations:
|
57
54
|
- MRI 2.3
|
58
55
|
- MRI 2.4
|
59
|
-
- MRI 2.5
|
56
|
+
- MRI 2.5
|
57
|
+
- MRI 2.6
|
60
58
|
- JRuby 9.1+
|
61
59
|
|
62
60
|
---
|
@@ -92,7 +90,7 @@ directory
|
|
92
90
|
|
93
91
|
# Let's create a facade object called 'engine'
|
94
92
|
# It provides a unified, higher-level interface
|
95
|
-
engine = Rley
|
93
|
+
engine = Rley::Engine.new
|
96
94
|
```
|
97
95
|
|
98
96
|
|
@@ -448,6 +446,7 @@ actively curated by Andrei Beliankou (aka arbox).
|
|
448
446
|
## Thanks to:
|
449
447
|
* Professor Keshav Pingali, one of the creators of the Grammar Flow Graph parsing approach for his encouraging e-mail exchange.
|
450
448
|
* [Arjun Menon](https://github.com/arjunmenon) for his NLP example that uses `engtagger` gem.
|
449
|
+
* [Gui Heurich](https://github.com/GuiHeurich) for spotting a mistake in the code sample in `README` file.
|
451
450
|
|
452
451
|
## Grammar Flow Graph
|
453
452
|
Since the Grammar Flow Graph parsing approach is quite new, it has not yet taken a place in
|
@@ -460,5 +459,5 @@ standard parser textbooks. Here are a few references (and links) of papers on GF
|
|
460
459
|
|
461
460
|
Copyright
|
462
461
|
---------
|
463
|
-
Copyright (c) 2014-
|
462
|
+
Copyright (c) 2014-2020, Dimitri Geshef.
|
464
463
|
__Rley__ is released under the MIT License see [LICENSE.txt](https://github.com/famished-tiger/Rley/blob/master/LICENSE.txt) for details.
|
data/Rakefile
CHANGED
data/appveyor.yml
CHANGED
@@ -2,17 +2,15 @@ version: '{build}'
|
|
2
2
|
max_jobs: 5
|
3
3
|
environment:
|
4
4
|
matrix:
|
5
|
+
- Ruby_version: 26-x64
|
5
6
|
- Ruby_version: 25-x64
|
6
7
|
- Ruby_version: 24-x64
|
7
8
|
- Ruby_version: 23-x64
|
9
|
+
- Ruby_version: 26
|
8
10
|
- Ruby_version: 25
|
9
11
|
- Ruby_version: 24
|
10
12
|
- Ruby_version: 23
|
11
13
|
|
12
|
-
# These are failing
|
13
|
-
# - Ruby_version: 26
|
14
|
-
# - Ruby_version: 26-x64
|
15
|
-
|
16
14
|
install:
|
17
15
|
- set PATH=C:\Ruby%Ruby_version%\bin;%PATH%
|
18
16
|
- gem update --system
|
data/examples/NLP/engtagger.rb
CHANGED
@@ -1,188 +1,193 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
text = text.gsub(/
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
#
|
105
|
-
|
106
|
-
|
107
|
-
text = text.gsub(
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
# Shift
|
112
|
-
text = text.gsub(
|
113
|
-
|
114
|
-
#
|
115
|
-
|
116
|
-
|
117
|
-
text = text.gsub(/
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
rule '
|
140
|
-
rule '
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
#
|
155
|
-
|
156
|
-
|
157
|
-
#
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rley'
|
4
|
+
require 'engtagger' # Load POS (Part-Of-Speech) tagger EngTagger
|
5
|
+
|
6
|
+
# REGEX to remove XML tags from Engtagger output
|
7
|
+
GET_TAG = /<(.+?)>(.*?)<.+?>/.freeze
|
8
|
+
|
9
|
+
# Text tokenizer
|
10
|
+
# Taken directly from Engtagger, will ensure uniform indexing while parsing
|
11
|
+
def clean_text(text)
|
12
|
+
return false unless valid_text(text)
|
13
|
+
|
14
|
+
text = text.toutf8
|
15
|
+
cleaned_text = text
|
16
|
+
tokenized = []
|
17
|
+
# Tokenize the text (splitting on punctuation as you go)
|
18
|
+
cleaned_text.split(/\s+/).each do |line|
|
19
|
+
tokenized += split_punct(line)
|
20
|
+
end
|
21
|
+
words = split_sentences(tokenized)
|
22
|
+
return words
|
23
|
+
end
|
24
|
+
|
25
|
+
def valid_text(text)
|
26
|
+
if !text
|
27
|
+
# there's nothing to parse
|
28
|
+
puts 'method call on uninitialized variable'
|
29
|
+
return false
|
30
|
+
elsif /\A\s*\z/ =~ text
|
31
|
+
# text is an empty string, nothing to parse
|
32
|
+
return false
|
33
|
+
else
|
34
|
+
# $text is valid
|
35
|
+
return true
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def split_sentences(array)
|
40
|
+
# rubocop: disable Layout/ArrayAlignment
|
41
|
+
tokenized = array
|
42
|
+
people = %w[jr mr ms mrs dr prof esq sr sen sens rep reps gov attys attys
|
43
|
+
supt det mssrs rev]
|
44
|
+
army = %w[col gen lt cmdr adm capt sgt cpl maj brig]
|
45
|
+
inst = %w[dept univ assn bros ph.d]
|
46
|
+
place = %w[arc al ave blvd bld cl ct cres exp expy dist mt mtn ft fy fwy
|
47
|
+
hwy hway la pde pd plz pl rd st tce]
|
48
|
+
comp = %w[mfg inc ltd co corp]
|
49
|
+
state = %w[ala ariz ark cal calif colo col conn del fed fla ga ida id ill
|
50
|
+
ind ia kans kan ken ky la me md is mass mich minn miss mo mont
|
51
|
+
neb nebr nev mex okla ok ore penna penn pa dak tenn tex ut vt
|
52
|
+
va wash wis wisc wy wyo usafa alta man ont que sask yuk]
|
53
|
+
month = %w[jan feb mar apr may jun jul aug sep sept oct nov dec]
|
54
|
+
misc = %w[vs etc no esp]
|
55
|
+
abbr = {}
|
56
|
+
[people, army, inst, place, comp, state, month, misc].flatten.each do |i|
|
57
|
+
abbr[i] = true
|
58
|
+
end
|
59
|
+
words = []
|
60
|
+
tokenized.each_with_index do |_t, i|
|
61
|
+
if tokenized[i + 1] &&
|
62
|
+
tokenized[i + 1] =~ /[A-Z\W]/ && tokenized[i] =~ /\A(.+)\.\z/
|
63
|
+
w = $1
|
64
|
+
# Don't separate the period off words that
|
65
|
+
# meet any of the following conditions:
|
66
|
+
#
|
67
|
+
# 1. It is defined in one of the lists above
|
68
|
+
# 2. It is only one letter long: Alfred E. Sloan
|
69
|
+
# 3. It has a repeating letter-dot: U.S.A. or J.C. Penney
|
70
|
+
unless abbr[w.downcase] ||
|
71
|
+
w =~ /\A[a-z]\z/i || w =~ /[a-z](?:\.[a-z])+\z/i
|
72
|
+
words << w
|
73
|
+
words << '.'
|
74
|
+
next
|
75
|
+
end
|
76
|
+
end
|
77
|
+
words << tokenized[i]
|
78
|
+
end
|
79
|
+
|
80
|
+
# If the final word ends in a period..
|
81
|
+
if words[-1] && words[-1] =~ /\A(.*\w)\.\z/
|
82
|
+
words[-1] = $1
|
83
|
+
words.push '.'
|
84
|
+
end
|
85
|
+
words
|
86
|
+
end
|
87
|
+
# rubocop: enable Layout/ArrayAlignment
|
88
|
+
|
89
|
+
# Separate punctuation from words, where appropriate. This leaves trailing
|
90
|
+
# periods in place to be dealt with later. Called by the clean_text method.
|
91
|
+
def split_punct(text)
|
92
|
+
# If there's no punctuation, return immediately
|
93
|
+
return [text] if /\A\w+\z/ =~ text
|
94
|
+
|
95
|
+
# Sanity checks
|
96
|
+
text = text.gsub(/\W{10,}/o, ' ')
|
97
|
+
|
98
|
+
# Put quotes into a standard format
|
99
|
+
text = text.gsub(/`(?!`)(?=.*\w)/o, '` ') # Shift left quotes off text
|
100
|
+
text = text.gsub(/"(?=.*\w)/o, ' `` ') # Convert left quotes to ``
|
101
|
+
|
102
|
+
# Convert left quote to `
|
103
|
+
text = text.gsub(/(\W|^)'(?=.*\w)/o) { $1 ? "#{$1} ` " : ' ` ' }
|
104
|
+
text = text.gsub(/"/, " '' ") # Convert (remaining) quotes to ''
|
105
|
+
|
106
|
+
# Separate right single quotes
|
107
|
+
text = text.gsub(/(\w)'(?!')(?=\W|$)/o, "\\1 ' ")
|
108
|
+
|
109
|
+
# Handle all other punctuation
|
110
|
+
text = text.gsub(/--+/o, ' - ') # Convert and separate dashes
|
111
|
+
text = text.gsub(/,(?!\d)/o, ' , ') # Shift comma if not following by digit
|
112
|
+
text = text.gsub(/:/o, ' :') # Shift semicolon off
|
113
|
+
text = text.gsub(/(\.\.\.+)/o, ' \1 ') # Shift ellipses off
|
114
|
+
text = text.gsub(/([(\[{}\])])/o, ' \1 ') # Shift off brackets
|
115
|
+
|
116
|
+
# Shift off other ``standard'' punctuation
|
117
|
+
text = text.gsub(/([!?#$%;~|])/o, ' \1 ')
|
118
|
+
|
119
|
+
# English-specific contractions
|
120
|
+
# Separate off 'd 'm 's
|
121
|
+
text = text.gsub(/([A-Za-z])'([dms])\b/o, "\\1 '\\2")
|
122
|
+
text = text.gsub(/n't\b/o, " n't") # Separate off n't
|
123
|
+
text = text.gsub(/'(ve|ll|re)\b/o, " '\\1") # Separate off 've, 'll, 're
|
124
|
+
result = text.split
|
125
|
+
return result
|
126
|
+
end
|
127
|
+
|
128
|
+
|
129
|
+
# Instantiate a facade object as our Rley interface
|
130
|
+
nlp_engine = Rley::Engine.new
|
131
|
+
|
132
|
+
# Now build a very simplified English grammar...
|
133
|
+
nlp_engine.build_grammar do
|
134
|
+
# Terminals have same names as POS tags returned by Engtagger
|
135
|
+
add_terminals('NN', 'NNP')
|
136
|
+
add_terminals('DET', 'IN', 'VBD')
|
137
|
+
|
138
|
+
# Here we define the productions (= grammar rules)
|
139
|
+
rule 'S' => %w[NP VP]
|
140
|
+
rule 'NP' => 'NNP'
|
141
|
+
rule 'NP' => %w[DET NN]
|
142
|
+
rule 'NP' => %w[DET NN PP]
|
143
|
+
rule 'VP' => %w[VBD NP]
|
144
|
+
rule 'VP' => %w[VBD NP PP]
|
145
|
+
rule 'PP' => %w[IN NP]
|
146
|
+
end
|
147
|
+
|
148
|
+
# text = "Yo I'm not done with you"
|
149
|
+
text = 'John saw Mary with a telescope'
|
150
|
+
puts "Input text --> #{text}"
|
151
|
+
|
152
|
+
tgr = EngTagger.new
|
153
|
+
|
154
|
+
# Generate raw POS output
|
155
|
+
tagged = tgr.add_tags(text)
|
156
|
+
|
157
|
+
# Generte tokenied lexicon of input text
|
158
|
+
# Instead of creating a lexicon dictionary,
|
159
|
+
# we would simply generate one each time on the fly for the current text only.
|
160
|
+
lexicon = clean_text(text)
|
161
|
+
|
162
|
+
# Convert EngTagger POS tokens in [[word, pos], ..] format
|
163
|
+
tokens = tagged.scan(GET_TAG).map { |tag, word| [word, tag.upcase] }
|
164
|
+
|
165
|
+
def tokenizer(lexicon, tokens)
|
166
|
+
pos = -1
|
167
|
+
rley_tokens = []
|
168
|
+
lexicon.each_with_index do |word, i|
|
169
|
+
term_name = tokens[i].last
|
170
|
+
rank = Rley::Lexical::Position.new(1, pos + 1)
|
171
|
+
pos += word.length + 1 # Assuming one space between words.
|
172
|
+
rley_tokens << Rley::Lexical::Token.new(word, term_name, rank)
|
173
|
+
end
|
174
|
+
return rley_tokens
|
175
|
+
end
|
176
|
+
|
177
|
+
# Convert input text into a sequence of rley token objects...
|
178
|
+
rley_tokens = tokenizer(lexicon, tokens)
|
179
|
+
|
180
|
+
# Let Rley grok the tokens
|
181
|
+
result = nlp_engine.parse(rley_tokens)
|
182
|
+
|
183
|
+
puts "Parsing successful? #{result.success?}" # => Parsing successful? true
|
184
|
+
puts result.failure_reason.message unless result.success?
|
185
|
+
|
186
|
+
ptree = nlp_engine.convert(result)
|
187
|
+
|
188
|
+
visitor = nlp_engine.ptree_visitor(ptree)
|
189
|
+
|
190
|
+
renderer = Rley::Formatter::Asciitree.new($stdout)
|
191
|
+
|
192
|
+
# Let's visualize the parse tree (in text format...)
|
193
|
+
puts renderer.render(visitor)
|