rley 0.5.02 → 0.5.03

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.
@@ -67,7 +67,5 @@ describe 'Calculator' do
67
67
  it 'should evaluate multiple levels of parentheses' do
68
68
  expect_expr('2*(1/(1+3))').to eq(0.5)
69
69
  end
70
-
71
70
  end # describe
72
71
  # End of file
73
-
@@ -3,7 +3,7 @@
3
3
 
4
4
  module Rley # Module used as a namespace
5
5
  # The version number of the gem.
6
- Version = '0.5.02'.freeze
6
+ Version = '0.5.03'.freeze
7
7
 
8
8
  # Brief description of the gem.
9
9
  Description = "Ruby implementation of the Earley's parsing algorithm".freeze
@@ -284,7 +284,7 @@ module Rley # This module is used as a namespace
284
284
  # from the start symbol to the start node .N
285
285
  def mark_unreachable_symbols()
286
286
  # Mark all non-terminals as unreachable
287
- start_vertex_for.values.each do |a_vertex|
287
+ start_vertex_for.each_value do |a_vertex|
288
288
  a_vertex.non_terminal.unreachable = true
289
289
  end
290
290
 
@@ -13,7 +13,6 @@ module Rley # This module is used as a namespace
13
13
  # (say, a parse tree) from simpler objects (terminal and non-terminal
14
14
  # nodes) and using a step by step approach.
15
15
  class CSTBuilder < ParseTreeBuilder
16
-
17
16
  protected
18
17
 
19
18
  # Method to override
@@ -37,9 +36,9 @@ module Rley # This module is used as a namespace
37
36
  # Factory method for creating a parent node object.
38
37
  # @param aProduction [Production] Production rule
39
38
  # @param aRange [Range] Range of tokens matched by the rule
40
- # @param theTokens [Array] The input tokens
39
+ # @param _tokens [Array] The input tokens
41
40
  # @param theChildren [Array] Children nodes (one per rhs symbol)
42
- def new_parent_node(aProduction, aRange, theTokens, theChildren)
41
+ def new_parent_node(aProduction, aRange, _tokens, theChildren)
43
42
  node = Rley::PTree::NonTerminalNode.new(aProduction.lhs, aRange)
44
43
  theChildren.reverse_each { |child| node.add_subnode(child) }
45
44
  return node
@@ -6,12 +6,11 @@ module Rley # This module is used as a namespace
6
6
  # Utility class that helps to create a ParseForest from
7
7
  # a given Parsing object.
8
8
  class ParseForestFactory < ParseRepCreator
9
-
10
9
  protected
11
10
 
12
11
  # Create a Builder, that is, an object
13
12
  # that will create piece by piece the forest
14
- def builder(aParseResult, aBuilder = nil)
13
+ def builder(aParseResult, _builder = nil)
15
14
  ParseForestBuilder.new(aParseResult.tokens)
16
15
  end
17
16
  end # class
@@ -96,10 +96,10 @@ module Rley # This module is used as a namespace
96
96
 
97
97
  # Handler for visit events for ParseEntry matching .N pattern
98
98
  # @param anEvent [Symbol] Kind of visit event. Should be: :visit
99
- # @param anEntry [ParseEntry] The entry being visited
100
- # @param anIndex [anIndex] The token index at end of anEntry
101
- def process_start_entry(anEvent, anEntry, anIndex)
102
- raise NotImplementedError unless [:visit, :revisit].include?(anEvent)
99
+ # @param _entry [ParseEntry] The entry being visited
100
+ # @param _index [Integer] The token index at end of anEntry
101
+ def process_start_entry(anEvent, _entry, _index)
102
+ raise NotImplementedError unless %I[visit revisit].include?(anEvent)
103
103
  end
104
104
 
105
105
  # Handler for visit events for ParseEntry matching N => alpha* . beta*
@@ -130,7 +130,7 @@ module Rley # This module is used as a namespace
130
130
  # @param anEntry [ParseEntry] Entry matching (pattern: N => alpha* .)
131
131
  # @param anIndex [anIndex] The token index at end of anEntry
132
132
  def process_exit_entry(anEntry, anIndex)
133
- production = anEntry.vertex.dotted_item.production
133
+ production = anEntry.vertex.dotted_item.production
134
134
  count_rhs = production.rhs.members.size
135
135
  init_TOS_children(count_rhs) # Create placeholders for children
136
136
  build_terminal(anEntry, anIndex) if terminal_before_dot?(anEntry)
@@ -142,20 +142,18 @@ module Rley # This module is used as a namespace
142
142
  build_terminal(anEntry, anIndex) if terminal_before_dot?(anEntry)
143
143
  end
144
144
 
145
-
146
-
147
145
  # @param anEntry [ParseEntry] Entry matching (pattern: N => . alpha)
148
- # @param anIndex [anIndex] The token index at end of anEntry
149
- def process_entry_entry(anEntry, anIndex)
146
+ # @param anIndex [_index] The token index at end of anEntry
147
+ def process_entry_entry(anEntry, _index)
150
148
  dotted_item = anEntry.vertex.dotted_item
151
149
  rule = dotted_item.production
152
150
  previous_tos = stack.pop
153
151
  non_terminal = entry2nonterm(anEntry)
154
152
  # For debugging purposes
155
153
  raise StandardError if previous_tos.symbol != non_terminal
156
-
154
+
157
155
  new_node = new_parent_node(rule, previous_tos.range,
158
- tokens, previous_tos.children)
156
+ tokens, previous_tos.children)
159
157
  if stack.empty?
160
158
  @result = create_tree(new_node)
161
159
  else
@@ -196,13 +194,12 @@ module Rley # This module is used as a namespace
196
194
  token = tokens[token_position]
197
195
  prod = anEntry.vertex.dotted_item.production
198
196
  term_node = new_leaf_node(prod, term_symbol, token_position, token)
199
-
197
+
200
198
  # Second make it a child of TOS...
201
199
  pos = anEntry.vertex.dotted_item.prev_position # pos. in rhs of rule
202
200
  place_TOS_child(term_node, pos)
203
201
  end
204
202
 
205
-
206
203
  # Place the given node object as one of the children of the TOS
207
204
  # (TOS = Top Of Stack).
208
205
  # Each child has a position that is dictated by the position of the
@@ -217,7 +214,7 @@ module Rley # This module is used as a namespace
217
214
  def place_TOS_child(aNode, aRHSPos)
218
215
  if aRHSPos.nil?
219
216
  # Retrieve index of most rightmost nil child...
220
- pos = tos.children.rindex { |child| child.nil? }
217
+ pos = tos.children.rindex(&:nil?)
221
218
  raise StandardError, 'Internal error' if pos.nil?
222
219
  else
223
220
  pos = aRHSPos
@@ -225,14 +222,14 @@ module Rley # This module is used as a namespace
225
222
 
226
223
  tos.children[pos] = aNode
227
224
  end
228
-
225
+
229
226
  # Retrieve non-terminal symbol of given parse entry
230
227
  def entry2nonterm(anEntry)
231
228
  case anEntry.vertex
232
- when GFG::StartVertex, GFG::EndVertex
233
- non_terminal = anEntry.vertex.non_terminal
234
- when GFG::ItemVertex
235
- non_terminal = anEntry.vertex.lhs
229
+ when GFG::StartVertex, GFG::EndVertex
230
+ non_terminal = anEntry.vertex.non_terminal
231
+ when GFG::ItemVertex
232
+ non_terminal = anEntry.vertex.lhs
236
233
  end
237
234
 
238
235
  return non_terminal
@@ -7,7 +7,6 @@ module Rley # This module is used as a namespace
7
7
  # Utility class that helps to create a ParseTree from
8
8
  # a given Parsing object.
9
9
  class ParseTreeFactory < ParseRepCreator
10
-
11
10
  protected
12
11
 
13
12
  # Create a Builder, that is, an object
@@ -266,7 +266,7 @@ module Rley # This module is used as a namespace
266
266
  (antecd.origin == tos.origin) && tos_dotted_item.successor_of?(item)
267
267
  end
268
268
 
269
- new_entry = aContext.curr_entry unless new_entry
269
+ new_entry ||= aContext.curr_entry
270
270
 
271
271
  # puts "Pop from return stack matching entry #{new_entry}"
272
272
  return new_entry
@@ -31,7 +31,7 @@ module Rley # This module is used as a namespace
31
31
  @symbols = []
32
32
  @name2symbol = {}
33
33
  valid_productions = validate_productions(theProductions)
34
- valid_productions.each do |prod|
34
+ valid_productions.each do |prod|
35
35
  add_production(prod)
36
36
  name_production(prod)
37
37
  end
@@ -68,21 +68,23 @@ module Rley # This module is used as a namespace
68
68
 
69
69
  aProduction.rhs.each { |symb| add_symbol(symb) }
70
70
  end
71
-
71
+
72
+ # If the production is anonymous, then assign it
73
+ # a default name
72
74
  def name_production(aProduction)
73
- if aProduction.name.nil?
74
- index = rules.find_index(aProduction)
75
- prefix = aProduction.lhs.name.dup
76
- previous = index.zero? ? nil : rules[index - 1]
77
- if previous.nil? || previous.lhs != aProduction.lhs
78
- suffix = '[0]'
79
- else
80
- prev_serial = previous.name.match(/\[(\d+)\]$/)
81
- suffix = "[#{prev_serial[1].to_i + 1}]"
82
- end
83
-
84
- aProduction.name = prefix + suffix
75
+ return unless aProduction.name.nil?
76
+
77
+ index = rules.find_index(aProduction)
78
+ prefix = aProduction.lhs.name.dup
79
+ previous = index.zero? ? nil : rules[index - 1]
80
+ if previous.nil? || previous.lhs != aProduction.lhs
81
+ suffix = '[0]'
82
+ else
83
+ prev_serial = previous.name.match(/\[(\d+)\]$/)
84
+ suffix = "[#{prev_serial[1].to_i + 1}]"
85
85
  end
86
+
87
+ aProduction.name = prefix + suffix
86
88
  end
87
89
 
88
90
  # Perform some check of the grammar.
@@ -141,7 +143,7 @@ module Rley # This module is used as a namespace
141
143
  could_mark_nterm_generative(a_rule)
142
144
  end
143
145
  break if prev_marked.size == curr_marked.size
144
- end
146
+ end
145
147
 
146
148
  # The nonterminals that are not marked yet are non-generative
147
149
  non_terminals.each do |nterm|
@@ -80,7 +80,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
80
80
  end
81
81
 
82
82
  it 'should have one or more entry edges per start vertex' do
83
- subject.start_vertex_for.values.each do |a_start|
83
+ subject.start_vertex_for.each_value do |a_start|
84
84
  expect(a_start.edges.size >= 1).to be_truthy
85
85
  a_start.edges.each do |edge|
86
86
  expect(edge.successor.dotted_item.at_start?).to be_truthy
@@ -12,7 +12,6 @@ require_relative '../support/grammar_arr_int_helper'
12
12
 
13
13
  module Rley # This module is used as a namespace
14
14
  module Parser # This module is used as a namespace
15
-
16
15
  ArrayNode = Struct.new(:children) do
17
16
  def initialize()
18
17
  super
@@ -32,7 +31,7 @@ module Rley # This module is used as a namespace
32
31
  end
33
32
 
34
33
  def interpret()
35
- self.value
34
+ value
36
35
  end
37
36
  end
38
37
 
@@ -44,7 +43,6 @@ module Rley # This module is used as a namespace
44
43
  # (say, a parse tree) from simpler objects (terminal and non-terminal
45
44
  # nodes) and using a step by step approach.
46
45
  class ASTBuilder < ParseTreeBuilder
47
-
48
46
  protected
49
47
 
50
48
  # Method to override
@@ -76,53 +74,54 @@ module Rley # This module is used as a namespace
76
74
  # @param theChildren [Array] Children nodes (one per rhs symbol)
77
75
  def new_parent_node(aProduction, aRange, theTokens, theChildren)
78
76
  node = case aProduction.name
79
- when 'P[0]'
80
- reduce_P_0(aRange, theTokens, theChildren)
77
+ when 'P[0]'
78
+ reduce_P_0(aRange, theTokens, theChildren)
81
79
 
82
- when 'arr[0]'
83
- reduce_arr_0(aRange, theTokens, theChildren)
80
+ when 'arr[0]'
81
+ reduce_arr_0(aRange, theTokens, theChildren)
84
82
 
85
- when 'sequence[0]'
86
- reduce_sequence_0(aRange, theTokens, theChildren)
83
+ when 'sequence[0]'
84
+ reduce_sequence_0(aRange, theTokens, theChildren)
87
85
 
88
- when 'sequence[1]'
89
- reduce_sequence_1(aRange, theTokens, theChildren)
86
+ when 'sequence[1]'
87
+ reduce_sequence_1(aRange, theTokens, theChildren)
90
88
 
91
- when 'list[0]'
92
- reduce_list_0(aRange, theTokens, theChildren)
89
+ when 'list[0]'
90
+ reduce_list_0(aRange, theTokens, theChildren)
93
91
 
94
- when 'list[1]'
95
- reduce_list_1(aRange, theTokens, theChildren)
96
- else
97
- raise StandardError, "Don't know production #{aProduction.name}"
98
- end
92
+ when 'list[1]'
93
+ reduce_list_1(aRange, theTokens, theChildren)
94
+ else
95
+ err_msg = "Don't know production #{aProduction.name}"
96
+ raise StandardError, err_msg
97
+ end
99
98
 
100
99
  return node
101
100
  end
102
101
 
103
- def reduce_P_0(aRange, theTokens, theChildren)
102
+ def reduce_P_0(_range, _tokens, theChildren)
104
103
  return theChildren[0]
105
104
  end
106
105
 
107
- def reduce_arr_0(aRange, theTokens, theChildren)
106
+ def reduce_arr_0(_range, _tokens, theChildren)
108
107
  return theChildren[1]
109
108
  end
110
109
 
111
- def reduce_sequence_0(aRange, theTokens, theChildren)
110
+ def reduce_sequence_0(_range, _tokens, theChildren)
112
111
  return theChildren[0]
113
112
  end
114
113
 
115
- def reduce_sequence_1(aRange, theTokens, theChildren)
114
+ def reduce_sequence_1(_range, _tokens, _children)
116
115
  return ArrayNode.new
117
116
  end
118
117
 
119
- def reduce_list_0(aRange, theTokens, theChildren)
118
+ def reduce_list_0(_range, _tokens, theChildren)
120
119
  node = theChildren[0]
121
120
  node.children << theChildren[2]
122
121
  return node
123
122
  end
124
123
 
125
- def reduce_list_1(aRange, theTokens, theChildren)
124
+ def reduce_list_1(_range, _tokens, theChildren)
126
125
  node = ArrayNode.new
127
126
  node.children << theChildren[0]
128
127
  return node
@@ -163,12 +162,13 @@ module Rley # Open this namespace to avoid module qualifier prefixes
163
162
  subject.receive_event(*event)
164
163
  end
165
164
  end
165
+
166
166
  def get_stack(aBuilder)
167
167
  return aBuilder.send(:stack)
168
168
  end
169
169
 
170
170
  def create_range(low, high)
171
- return Tokens::TokenRange.new({low: low, high: high })
171
+ return Tokens::TokenRange.new(low: low, high: high)
172
172
  end
173
173
 
174
174
  context 'Initialization:' do
@@ -190,7 +190,6 @@ module Rley # Open this namespace to avoid module qualifier prefixes
190
190
  end # context
191
191
 
192
192
  context 'Parse tree construction (no null symbol):' do
193
-
194
193
  def next_event(expectation)
195
194
  event = @walker.next
196
195
  (ev_type, entry, index) = event
@@ -244,9 +243,9 @@ module Rley # Open this namespace to avoid module qualifier prefixes
244
243
  expect(stack.size).to eq(1)
245
244
  # stack: [P[0, 7]]
246
245
  expect(stack.last.range).to eq(create_range(0, 7))
247
- expect(stack.last.children).to be_nil
246
+ expect(stack.last.children).to be_nil
248
247
  end
249
-
248
+
250
249
  it 'should build a tree for an empty array' do
251
250
  stack = get_stack(subject)
252
251
 
@@ -317,7 +316,8 @@ module Rley # Open this namespace to avoid module qualifier prefixes
317
316
 
318
317
  next_event('visit list. | 1 2')
319
318
  expect(stack.size).to eq(6)
320
- # stack: [P[0, 7], arr[0, 7], sequence[1, 6], list[1, 6], list[1, 4], list[1, 2]
319
+ # stack: [P[0, 7], arr[0, 7], sequence[1, 6], list[1, 6],
320
+ # list[1, 4], list[1, 2]
321
321
  expect(stack.last.range).to eq(create_range(1, 2))
322
322
  expect(stack.last.children).to be_nil
323
323
 
@@ -48,7 +48,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
48
48
  end
49
49
 
50
50
  def create_range(low, high)
51
- return Tokens::TokenRange.new({low: low, high: high })
51
+ return Tokens::TokenRange.new(low: low, high: high)
52
52
  end
53
53
 
54
54
  context 'Initialization:' do
@@ -340,8 +340,8 @@ module Rley # Open this namespace to avoid module qualifier prefixes
340
340
 
341
341
  # The visit events were generated with the following snippets:
342
342
  # 13.times do
343
- # event = @walker.next
344
- # subject.receive_event(*event)
343
+ # event = @walker.next
344
+ # subject.receive_event(*event)
345
345
  # end
346
346
  # The events are:
347
347
  # Event: visit P. | 0 2
@@ -80,10 +80,10 @@ module Rley # Open this namespace to avoid module qualifier prefixes
80
80
 
81
81
  context 'Provided services:' do
82
82
  it 'should emit a message' do
83
- text = <<MSG_END
83
+ text = <<MESSAGE_END
84
84
  Syntax error at or near token 4 >>>-<<<
85
85
  Expected one of: ['PLUS', 'LPAREN'], found a 'MINUS' instead.
86
- MSG_END
86
+ MESSAGE_END
87
87
  expect(subject.to_s).to eq(text.chomp)
88
88
  expect(subject.message).to eq(text.chomp)
89
89
  end
@@ -111,10 +111,10 @@ MSG_END
111
111
 
112
112
  context 'Provided services:' do
113
113
  it 'should emit a message' do
114
- text = <<MSG_END
114
+ text = <<MESSAGE_END
115
115
  Premature end of input after '+' at position 4
116
116
  Expected one of: ['INT', 'LPAREN'].
117
- MSG_END
117
+ MESSAGE_END
118
118
  expect(subject.to_s).to eq(text.chomp)
119
119
  expect(subject.message).to eq(text.chomp)
120
120
  end
@@ -13,10 +13,10 @@ module GrammarArrIntHelper
13
13
  builder = Rley::Syntax::GrammarBuilder.new do
14
14
  add_terminals('[', ']', ',', 'integer')
15
15
  rule 'P' => 'arr'
16
- rule 'arr' => %w( [ sequence ] )
16
+ rule 'arr' => %w([ sequence ])
17
17
  rule 'sequence' => ['list']
18
18
  rule 'sequence' => []
19
- rule 'list' => %w[list , integer] # Right-recursive rule
19
+ rule 'list' => %w[list , integer] # Right-recursive rule
20
20
  rule 'list' => 'integer'
21
21
  end
22
22
  builder
@@ -27,7 +27,7 @@ module GrammarArrIntHelper
27
27
  tokens = []
28
28
  scanner = StringScanner.new(aText)
29
29
 
30
- until scanner.eos? do
30
+ until scanner.eos?
31
31
  scanner.skip(/\s+/)
32
32
  lexeme = scanner.scan(/[\[,\]]/)
33
33
  if lexeme