rley 0.4.06 → 0.4.07

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 (77) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +22 -13
  3. data/.travis.yml +8 -7
  4. data/CHANGELOG.md +9 -0
  5. data/README.md +9 -10
  6. data/examples/NLP/mini_en_demo.rb +7 -7
  7. data/examples/data_formats/JSON/cli_options.rb +5 -6
  8. data/examples/data_formats/JSON/{JSON_demo.rb → json_demo.rb} +2 -2
  9. data/examples/data_formats/JSON/{JSON_grammar.rb → json_grammar.rb} +10 -10
  10. data/examples/data_formats/JSON/{JSON_lexer.rb → json_lexer.rb} +17 -22
  11. data/examples/data_formats/JSON/{JSON_parser.rb → json_parser.rb} +2 -2
  12. data/examples/general/calc/calc_demo.rb +1 -1
  13. data/examples/general/calc/calc_grammar.rb +5 -5
  14. data/examples/general/calc/calc_lexer.rb +14 -17
  15. data/examples/general/calc/calc_parser.rb +2 -2
  16. data/lib/rley/constants.rb +1 -1
  17. data/lib/rley/formatter/asciitree.rb +15 -16
  18. data/lib/rley/formatter/bracket_notation.rb +3 -6
  19. data/lib/rley/formatter/debug.rb +0 -1
  20. data/lib/rley/formatter/json.rb +0 -1
  21. data/lib/rley/gfg/grm_flow_graph.rb +11 -10
  22. data/lib/rley/parse_forest_visitor.rb +0 -3
  23. data/lib/rley/parse_tree_visitor.rb +0 -3
  24. data/lib/rley/parser/error_reason.rb +1 -5
  25. data/lib/rley/parser/gfg_chart.rb +2 -2
  26. data/lib/rley/parser/gfg_earley_parser.rb +1 -2
  27. data/lib/rley/parser/gfg_parsing.rb +3 -7
  28. data/lib/rley/parser/parse_entry.rb +0 -1
  29. data/lib/rley/parser/parse_entry_set.rb +15 -16
  30. data/lib/rley/parser/parse_forest_builder.rb +8 -23
  31. data/lib/rley/parser/parse_state.rb +1 -1
  32. data/lib/rley/parser/parse_tree_builder.rb +2 -30
  33. data/lib/rley/parser/parse_tree_factory.rb +1 -1
  34. data/lib/rley/parser/parse_walker_factory.rb +3 -6
  35. data/lib/rley/parser/state_set.rb +0 -1
  36. data/lib/rley/ptree/parse_tree.rb +0 -1
  37. data/lib/rley/ptree/terminal_node.rb +4 -1
  38. data/lib/rley/rley_error.rb +1 -1
  39. data/lib/rley/sppf/composite_node.rb +0 -1
  40. data/lib/rley/sppf/parse_forest.rb +0 -1
  41. data/lib/rley/syntax/grammar.rb +5 -9
  42. data/lib/rley/syntax/grammar_builder.rb +8 -11
  43. data/lib/rley/syntax/grm_symbol.rb +0 -1
  44. data/lib/rley/syntax/production.rb +5 -4
  45. data/lib/rley/tokens/token_range.rb +0 -1
  46. data/spec/rley/formatter/bracket_notation_spec.rb +3 -1
  47. data/spec/rley/gfg/grm_flow_graph_spec.rb +15 -46
  48. data/spec/rley/gfg/item_vertex_spec.rb +1 -1
  49. data/spec/rley/parse_forest_visitor_spec.rb +1 -1
  50. data/spec/rley/parse_tree_visitor_spec.rb +2 -2
  51. data/spec/rley/parser/error_reason_spec.rb +19 -14
  52. data/spec/rley/parser/gfg_chart_spec.rb +1 -1
  53. data/spec/rley/parser/gfg_earley_parser_spec.rb +15 -15
  54. data/spec/rley/parser/gfg_parsing_spec.rb +3 -3
  55. data/spec/rley/parser/groucho_spec.rb +6 -7
  56. data/spec/rley/parser/parse_forest_builder_spec.rb +5 -5
  57. data/spec/rley/parser/parse_forest_factory_spec.rb +5 -5
  58. data/spec/rley/parser/parse_state_spec.rb +8 -0
  59. data/spec/rley/parser/parse_tracer_spec.rb +1 -1
  60. data/spec/rley/parser/parse_tree_builder_spec.rb +26 -29
  61. data/spec/rley/parser/parse_tree_factory_spec.rb +5 -5
  62. data/spec/rley/parser/parse_walker_factory_spec.rb +5 -5
  63. data/spec/rley/ptree/parse_tree_node_spec.rb +2 -2
  64. data/spec/rley/ptree/terminal_node_spec.rb +1 -1
  65. data/spec/rley/support/ambiguous_grammar_helper.rb +1 -1
  66. data/spec/rley/support/expectation_helper.rb +0 -1
  67. data/spec/rley/support/grammar_abc_helper.rb +1 -1
  68. data/spec/rley/support/grammar_ambig01_helper.rb +2 -3
  69. data/spec/rley/support/grammar_b_expr_helper.rb +2 -2
  70. data/spec/rley/support/grammar_l0_helper.rb +7 -8
  71. data/spec/rley/support/grammar_pb_helper.rb +3 -4
  72. data/spec/rley/support/grammar_sppf_helper.rb +4 -4
  73. data/spec/rley/syntax/grammar_builder_spec.rb +5 -4
  74. data/spec/rley/syntax/grammar_spec.rb +10 -11
  75. data/spec/rley/syntax/symbol_seq_spec.rb +2 -2
  76. data/spec/rley/syntax/terminal_spec.rb +1 -1
  77. metadata +31 -31
@@ -128,7 +128,6 @@ module Rley # This module is used as a namespace
128
128
  return true
129
129
  end
130
130
 
131
-
132
131
  # Return true if the parse was successful (= input tokens
133
132
  # followed the syntax specified by the grammar)
134
133
  def success?()
@@ -180,11 +179,9 @@ module Rley # This module is used as a namespace
180
179
 
181
180
  # A notification that the parsing reached an end
182
181
  def done
183
- unless self.success? || self.failure_reason
184
- # Parse not successful and no reason identified
185
- # Assuming that parse failed because of a premature end
186
- premature_end
187
- end
182
+ # Parse not successful and no reason identified
183
+ # Assuming that parse failed because of a premature end
184
+ premature_end unless success? || failure_reason
188
185
  end
189
186
 
190
187
  private
@@ -232,7 +229,6 @@ module Rley # This module is used as a namespace
232
229
  return ParseForestBuilder.new(start_production, full_range)
233
230
  end
234
231
 
235
-
236
232
  # Factory method. Creates and initializes a ParseEntryTracker instance.
237
233
  def new_entry_tracker()
238
234
  instance = ParseEntryTracker.new(chart.last_index)
@@ -66,7 +66,6 @@ module Rley # This module is used as a namespace
66
66
  return vertex.kind_of?(GFG::EndVertex)
67
67
  end
68
68
 
69
-
70
69
  # Return the symbol before the dot (if any)
71
70
  def prev_symbol()
72
71
  return vertex.prev_symbol
@@ -9,34 +9,34 @@ module Rley # This module is used as a namespace
9
9
  # - To know all the parse entries in the set
10
10
  class ParseEntrySet
11
11
  extend Forwardable
12
- def_delegators :entries, :empty?, :size, :first, :last, :pop, :each
12
+ def_delegators :entries, :empty?, :size, :first, :last, :pop, :each
13
13
 
14
14
  # The set of parse entries
15
15
  attr_reader :entries
16
16
 
17
17
  def initialize()
18
18
  @entries = []
19
- @entries4term = Hash.new { |hash, key| hash[key] = [] }
19
+ @entries4term = Hash.new { |hash, key| hash[key] = [] }
20
20
  @entries4n_term = Hash.new { |hash, key| hash[key] = [] }
21
21
  end
22
-
22
+
23
23
  # Access the entry at given position
24
24
  def [](index)
25
25
  return entries[index]
26
- end
26
+ end
27
27
 
28
28
  # Returns a Hash with pairs of the form:
29
29
  # terminal symbol => [ parse entry expecting the terminal ]
30
30
  def entries4term(aTerminal)
31
31
  return @entries4term.fetch(aTerminal, [])
32
32
  end
33
-
33
+
34
34
  # Returns a Hash with pairs of the form:
35
35
  # non terminal symbol => [ parse entry expecting the non-terminal ]
36
36
  def entries4n_term(aNonTerminal)
37
37
  return @entries4n_term.fetch(aNonTerminal, [])
38
38
  end
39
-
39
+
40
40
  # Append the given entry (if it isn't yet in the set)
41
41
  # to the list of parse entries
42
42
  # @param anEntry [ParseEntry] the parse entry to push.
@@ -51,27 +51,26 @@ module Rley # This module is used as a namespace
51
51
  add_lookup4symbol(anEntry) if expecting
52
52
  result = anEntry
53
53
  end
54
-
55
- return result
54
+
55
+ return result
56
56
  end
57
57
 
58
-
59
58
  # Return an Array of Arrays of ambiguous parse entries.
60
59
  def ambiguities()
61
60
  complete_entries = entries.select(&:exit_entry?)
62
61
  return [] if complete_entries.size <= 1
63
-
62
+
64
63
  # Group parse entries by lhs symbol and origin
65
64
  groupings = complete_entries.group_by do |entry|
66
65
  entry.vertex.dotted_rule.lhs.object_id.to_s
67
66
  end
68
-
67
+
69
68
  # Retain the groups having more than one element.
70
69
  ambiguous_groups = []
71
70
  groupings.each_value do |a_group|
72
71
  ambiguous_groups << a_group if a_group.size > 1
73
72
  end
74
-
73
+
75
74
  return ambiguous_groups
76
75
  end
77
76
 
@@ -79,16 +78,16 @@ module Rley # This module is used as a namespace
79
78
  # is on the left of a dot in a parse state of the parse set.
80
79
  def expected_terminals()
81
80
  return @entries4term.keys
82
- end
83
-
81
+ end
82
+
84
83
  private
85
84
 
86
85
  def add_lookup4symbol(anEntry)
87
86
  symb = anEntry.next_symbol
88
87
  case symb
89
88
  when Syntax::Terminal
90
- @entries4term[symb] << anEntry
91
-
89
+ @entries4term[symb] << anEntry
90
+
92
91
  when Syntax::NonTerminal
93
92
  @entries4n_term[symb] << anEntry
94
93
  end
@@ -82,11 +82,6 @@ module Rley # This module is used as a namespace
82
82
  when :backtrack
83
83
  # Restore path
84
84
  @curr_path = entry2path_to_alt[anEntry].dup
85
- # puts "Restore path [#{curr_path.map{|e|e.to_string(0)}.join(', ')}]"
86
- antecedent_index = curr_parent.subnodes.size
87
- # puts "Current parent #{curr_parent.to_string(0)}"
88
- # puts "Antecedent index #{antecedent_index}"
89
-
90
85
 
91
86
  when :revisit
92
87
  # Retrieve the already existing node corresponding
@@ -102,7 +97,6 @@ module Rley # This module is used as a namespace
102
97
  end
103
98
  end
104
99
 
105
-
106
100
  def process_item_entry(anEvent, anEntry, anIndex)
107
101
  case anEvent
108
102
  when :visit
@@ -150,14 +144,9 @@ module Rley # This module is used as a namespace
150
144
  when :backtrack
151
145
  # Restore path
152
146
  @curr_path = entry2path_to_alt[anEntry].dup
153
- # puts "Special restore path [#{curr_path.map{|e|e.to_string(0)}.join(', ')}]"
154
- antecedent_index = curr_parent.subnodes.size
155
- # puts "Current parent #{curr_parent.to_string(0)}"
156
- # puts "Antecedent index #{antecedent_index}"
157
-
158
147
  create_alternative_node(anEntry)
159
148
 
160
- when :revisit
149
+ when :revisit
161
150
  # Retrieve the grammar symbol before the dot (if any)
162
151
  prev_symbol = anEntry.prev_symbol
163
152
  case prev_symbol
@@ -181,7 +170,6 @@ module Rley # This module is used as a namespace
181
170
  return Rley::SPPF::ParseForest.new(aRootNode)
182
171
  end
183
172
 
184
-
185
173
  # Factory method. Build and return an SPPF non-terminal node.
186
174
  def create_non_terminal_node(anEntry, aRange, nonTSymb = nil)
187
175
  non_terminal = nonTSymb.nil? ? anEntry.vertex.non_terminal : nonTSymb
@@ -193,7 +181,6 @@ module Rley # This module is used as a namespace
193
181
  return new_node
194
182
  end
195
183
 
196
-
197
184
  # Add an alternative node to the forest
198
185
  def create_alternative_node(anEntry)
199
186
  vertex = anEntry.vertex
@@ -220,7 +207,6 @@ module Rley # This module is used as a namespace
220
207
  return candidate
221
208
  end
222
209
 
223
-
224
210
  def create_epsilon_node(anEntry, anIndex)
225
211
  new_node = SPPF::EpsilonNode.new(anIndex)
226
212
  candidate = add_node_to_forest(new_node)
@@ -232,19 +218,18 @@ module Rley # This module is used as a namespace
232
218
  # Add the given node if not yet present in parse forest
233
219
  def add_node_to_forest(aNode)
234
220
  key_node = aNode.key
235
- if forest.include?(key_node)
236
- new_node = forest.key2node[key_node]
237
- else
238
- new_node = aNode
239
- forest.key2node[key_node] = new_node
240
- # puts "FOREST ADD #{key_node}"
241
- end
221
+ if forest.include?(key_node)
222
+ new_node = forest.key2node[key_node]
223
+ else
224
+ new_node = aNode
225
+ forest.key2node[key_node] = new_node
226
+ # puts "FOREST ADD #{key_node}"
227
+ end
242
228
  add_subnode(new_node, false)
243
229
 
244
230
  return new_node
245
231
  end
246
232
 
247
-
248
233
  # Add the given node as sub-node of current parent node
249
234
  # Optionally add the node to the current path
250
235
  def add_subnode(aNode, addToPath = true)
@@ -40,7 +40,7 @@ module Rley # This module is used as a namespace
40
40
 
41
41
  # Does this parse state have the 'other' as successor?
42
42
  def precedes?(other)
43
- return false if self == other
43
+ return false if other == self
44
44
 
45
45
  return false unless origin == other.origin
46
46
  other_production = other.dotted_rule.production
@@ -77,7 +77,6 @@ module Rley # This module is used as a namespace
77
77
  end
78
78
  end
79
79
 
80
-
81
80
  def process_item_entry(anEvent, anEntry, anIndex)
82
81
  case anEvent
83
82
  when :visit
@@ -117,32 +116,8 @@ module Rley # This module is used as a namespace
117
116
  curr_path.pop if curr_parent.kind_of?(SPPF::AlternativeNode)
118
117
  end
119
118
 
120
- when :backtrack
121
- # # Restore path
122
- # @curr_path = entry2path_to_alt[anEntry].dup
123
- # # puts "Special restore path [#{curr_path.map{|e|e.to_string(0)}.join(', ')}]"
124
- # antecedent_index = curr_parent.subnodes.size
125
- # # puts "Current parent #{curr_parent.to_string(0)}"
126
- # # puts "Antecedent index #{antecedent_index}"
127
-
128
- # create_alternative_node(anEntry)
129
-
130
- when :revisit
131
- # # Retrieve the grammar symbol before the dot (if any)
132
- # prev_symbol = anEntry.prev_symbol
133
- # case prev_symbol
134
- # when Syntax::Terminal
135
- # # Add node without changing current path
136
- # create_token_node(anEntry, anIndex)
137
-
138
- # when NilClass # Dot at the beginning of production
139
- # if anEntry.vertex.dotted_item.production.empty?
140
- # # Empty rhs => create an epsilon node ...
141
- # # ... without changing current path
142
- # create_epsilon_node(anEntry, anIndex)
143
- # end
144
- # curr_path.pop if curr_parent.kind_of?(PTree::AlternativeNode)
145
- # end
119
+ # when :backtrack
120
+ # when :revisit
146
121
  end
147
122
  end
148
123
 
@@ -151,7 +126,6 @@ module Rley # This module is used as a namespace
151
126
  return Rley::PTree::ParseTree.new(aRootNode)
152
127
  end
153
128
 
154
-
155
129
  # Factory method. Build and return an PTree non-terminal node.
156
130
  def create_non_terminal_node(anEntry, aRange, nonTSymb = nil)
157
131
  non_terminal = nonTSymb.nil? ? anEntry.vertex.non_terminal : nonTSymb
@@ -163,7 +137,6 @@ module Rley # This module is used as a namespace
163
137
  return new_node
164
138
  end
165
139
 
166
-
167
140
  # Add an alternative node to the tree
168
141
  def create_alternative_node(anEntry)
169
142
  vertex = anEntry.vertex
@@ -199,7 +172,6 @@ module Rley # This module is used as a namespace
199
172
  return new_node
200
173
  end
201
174
 
202
-
203
175
  # Add the given node as sub-node of current parent node
204
176
  # Optionally add the node to the current path
205
177
  def add_subnode(aNode, addToPath = true)
@@ -54,4 +54,4 @@ module Rley # This module is used as a namespace
54
54
  end # module
55
55
  end # module
56
56
 
57
- # End of file
57
+ # End of file
@@ -25,7 +25,6 @@ module Rley # This module is used as a namespace
25
25
  :antecedent_index
26
26
  )
27
27
 
28
-
29
28
  # A factory that creates an enumerator
30
29
  # that itself walks through a given parsing graph.
31
30
  # The walker yields visit events.
@@ -84,7 +83,6 @@ module Rley # This module is used as a namespace
84
83
  return context
85
84
  end
86
85
 
87
-
88
86
  # Initialize the non-terminal to start entry mapping
89
87
  def init_nterm2start()
90
88
  h = Hash.new do |hsh, defval|
@@ -139,7 +137,6 @@ module Rley # This module is used as a namespace
139
137
  return nil unless aContext.curr_entry.dotted_entry?
140
138
  end
141
139
 
142
-
143
140
  # Given the current entry from context object
144
141
  # Go to the parse entry that is one of its antecedent
145
142
  # The context object is updated
@@ -168,7 +165,8 @@ module Rley # This module is used as a namespace
168
165
  aContext.return_stack << aContext.curr_entry
169
166
  elsif traversed_edge.kind_of?(GFG::CallEdge)
170
167
  # Pop top of stack
171
- fail ScriptError, "Return stack empty!" if aContext.return_stack.empty?
168
+ err_msg = 'Return stack empty!'
169
+ raise ScriptError, err_msg if aContext.return_stack.empty?
172
170
  aContext.return_stack.pop
173
171
  # puts "Pop from return stack matching entry #{new_entry}"
174
172
  elsif traversed_edge.kind_of?(GFG::ScanEdge)
@@ -220,7 +218,6 @@ module Rley # This module is used as a namespace
220
218
  return bp
221
219
  end
222
220
 
223
-
224
221
  def use_backtrack_point(aContext)
225
222
  bp = aContext.backtrack_points.last
226
223
  bp.antecedent_index += 1
@@ -246,7 +243,7 @@ module Rley # This module is used as a namespace
246
243
  # Observation: calling parse entry is an parse entry linked
247
244
  # to a item vertex
248
245
  def select_calling_entry(aContext)
249
- fail ScriptError, "Empty return stack" if aContext.return_stack.empty?
246
+ raise ScriptError, 'Empty return stack' if aContext.return_stack.empty?
250
247
  # Retrieve top of stack
251
248
  tos = aContext.return_stack.pop
252
249
  tos_dotted_item = tos.vertex.dotted_item
@@ -35,7 +35,6 @@ module Rley # This module is used as a namespace
35
35
  return states.select { |s| s.dotted_rule.next_symbol == aSymbol }
36
36
  end
37
37
 
38
-
39
38
  # The list of complete ParseState that have the given non-terminal
40
39
  # symbol as the lhs of their production.
41
40
  def states_rewriting(aNonTerm)
@@ -20,7 +20,6 @@ module Rley # This module is used as a namespace
20
20
  @root = theRootNode
21
21
  end
22
22
 
23
-
24
23
  # Part of the 'visitee' role in the Visitor design pattern.
25
24
  # A visitee is expected to accept the visit from a visitor object
26
25
  # @param aVisitor [ParseTreeVisitor] the visitor object
@@ -8,7 +8,10 @@ module Rley # This module is used as a namespace
8
8
 
9
9
  # aPosition is the position of the token in the input stream.
10
10
  def initialize(aToken, aPos)
11
- range = aPos.kind_of?(Fixnum) ? { low: aPos, high: aPos + 1 } : aPos
11
+ (major, minor) =
12
+
13
+ # Use '1.class' trick to support both Integer and Fixnum classes
14
+ range = aPos.kind_of?(1.class) ? { low: aPos, high: aPos + 1 } : aPos
12
15
  super(aToken.terminal, range)
13
16
  @token = aToken
14
17
  end
@@ -7,4 +7,4 @@ module Rley # Module used as a namespace
7
7
  end # class
8
8
  end # module
9
9
 
10
- # End of file
10
+ # End of file
@@ -13,7 +13,6 @@ module Rley # This module is used as a namespace
13
13
  @subnodes = []
14
14
  end
15
15
 
16
-
17
16
  def add_subnode(aSubnode)
18
17
  subnodes.unshift(aSubnode)
19
18
  end
@@ -40,7 +40,6 @@ module Rley # This module is used as a namespace
40
40
  return @is_ambiguous
41
41
  end
42
42
 
43
-
44
43
  # Part of the 'visitee' role in the Visitor design pattern.
45
44
  # A visitee is expected to accept the visit from a visitor object
46
45
  # @param aVisitor [ParseForestVisitor] the visitor object
@@ -88,8 +88,6 @@ module Rley # This module is used as a namespace
88
88
  undefined.each { |n_term| n_term.undefined = true }
89
89
  end
90
90
 
91
-
92
-
93
91
  # Mark all non-terminals and production rules as
94
92
  # generative or not.
95
93
  # A production is generative when it can derive a string of terminals.
@@ -101,7 +99,7 @@ module Rley # This module is used as a namespace
101
99
  curr_marked = []
102
100
 
103
101
  # Iterate until no new rule can be marked.
104
- begin
102
+ loop do
105
103
  prev_marked = curr_marked.dup
106
104
 
107
105
  rules.each do |a_rule|
@@ -123,7 +121,8 @@ module Rley # This module is used as a namespace
123
121
  curr_marked << a_rule
124
122
  could_mark_nterm_generative(a_rule)
125
123
  end
126
- end until prev_marked.size == curr_marked.size
124
+ break if prev_marked.size == curr_marked.size
125
+ end
127
126
 
128
127
  # The nonterminals that are not marked yet are non-generative
129
128
  non_terminals.each do |nterm|
@@ -151,14 +150,13 @@ module Rley # This module is used as a namespace
151
150
  nterm.generative = true
152
151
  all_false = false
153
152
  break
154
- else
155
- all_false = false if prod.generative?.nil?
153
+ elsif prod.generative?.nil?
154
+ all_false = false
156
155
  end
157
156
  end
158
157
  nterm.generative = false if all_false
159
158
  end
160
159
 
161
-
162
160
  # For each non-terminal determine whether it is nullable or not.
163
161
  # A nullable nonterminal is a nonterminal that can match an empty string.
164
162
  def compute_nullable()
@@ -189,7 +187,6 @@ module Rley # This module is used as a namespace
189
187
  end
190
188
  end
191
189
 
192
-
193
190
  # Return the set of nonterminals which have one of their
194
191
  # production rules empty
195
192
  def direct_nullable()
@@ -216,7 +213,6 @@ module Rley # This module is used as a namespace
216
213
  def rules_for(aNonTerm)
217
214
  rules.select { |a_rule| a_rule.lhs == aNonTerm }
218
215
  end
219
-
220
216
  end # class
221
217
  end # module
222
218
  end # module