rley 0.4.06 → 0.4.07

Sign up to get free protection for your applications and to get access to all the features.
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