rley 0.5.02 → 0.5.03

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