rley 0.0.15 → 0.0.16

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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- OWU4NWFjYTZkZmY5NDhiNDBkNzVkMTRlNTIzYWIxODhkZjBmNDZlMA==
4
+ N2UzY2I3ZGYxOWEyMDIyOTg4NTc3OGNmZjBmNmQ2ZjE1ZjVjYjI4ZQ==
5
5
  data.tar.gz: !binary |-
6
- NDJhZWQ4MWFhYzYzNzg5NjkyMGQ5ZGFiNmQ5MDc2NWE0ODg3Yjk2Zg==
6
+ YWZjNjYzZmFkOWEyNjU2NGU1NjVmOWU2ZDdjZThiZjBhNzEyMTVmZg==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- OGUwODkxYjA3ZDQwZjRjYWM4ZmI0NWI3ODdmYWI5MDcwOTI1M2FmYjYxMzE5
10
- ZGYxYTcxNDU5OWJlNWYwNTg4MTM4YTQyMWI4NmE1MTM5OTI5ODZiNjIyZjYz
11
- ZDI4YTcyODIyNTk5NGNmNDQ3MjE0ZTczODAyYWMyNDAzZmVmYzI=
9
+ MTNlOThlZTYzNjBkZTMzNzBmOGYwM2RkNmM0M2IxNGQyMmU5NTZjMjQyMTM5
10
+ MzFmZGNmYTIyYWExMDc3ZjA0Nzc1YTc1ZWI5YjIwYjBiMzgzYTQ0Mjk3NDk3
11
+ MDVmYjk2NGUxMGY0NzBmOTk1NmFkY2I2YjNlZmRhZDk2MGMyYTA=
12
12
  data.tar.gz: !binary |-
13
- MGUyYzA1YTAzMDM2M2MwYjM1YzI5MTIwMTc4YjVjNzEzNGYwZDk1ZmY0YWRh
14
- MDNiZmRiZTQwNDcyNjIwNWQ2MjYxZjU2MmFhMzA2YzgyYTU5MzM2ODI0YTcw
15
- ZTM0MTY4MjJhOTMxOGUyMzdlMTU0ZDBlODY5ZGM5M2FjYzdmNzk=
13
+ ZDI3MWMzMzVjMDBkZDFiZDlmODNmM2MwYTI1ZTFiM2I1YmY3NjY1MDQ4Mjlj
14
+ ZDA4ZWFlZDFjZGNhNmM4YTJiYjg0YmM1ZGI0ZGExMmQxN2U5NzlmNDg2MTA3
15
+ MWRhZDdkYTBkODJhOWZmZDI2NDFmNGVlZWI5MDRmMTQyMTQwN2E=
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ### 0.0.16 / 2014-11-23
2
+ * [NEW] Method `DottedItem#to_s` Returns a text representation of an instance.
3
+ * [NEW] Method `ParseState#to_s`
4
+ * [NEW] Method `GrmSymbol#to_s`
5
+ * [NEW] Method `VerbatimSymbol#to_s`
6
+ * [CHANGE] File `earley_parser_spec.rb`: Parse tests refactored.
7
+
8
+
1
9
  ### 0.0.15 / 2014-11-20
2
10
  * [FIX] `EarleyParser` class source code was out-of-sync.
3
11
 
@@ -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.0.15'
6
+ Version = '0.0.16'
7
7
 
8
8
  # Brief description of the gem.
9
9
  Description = "Ruby implementation of the Earley's parsing algorithm"
@@ -30,6 +30,21 @@ module Rley # This module is used as a namespace
30
30
  @position = valid_position(aPosition)
31
31
  end
32
32
 
33
+ # Return a String representation of the dotted item.
34
+ # @return [String]
35
+ def to_s()
36
+ prefix = "#{production.lhs} => "
37
+ text_values = production.rhs.map(&:to_s)
38
+ if position < 0
39
+ text_values << '.'
40
+ else
41
+ text_values.insert(position, '.')
42
+ end
43
+ suffix = text_values.join(' ')
44
+
45
+ return prefix + suffix
46
+ end
47
+
33
48
  # Return true if the dot position is at the start of the rhs.
34
49
  def at_start?()
35
50
  return position == 0 || position == -2
@@ -36,6 +36,14 @@ module Rley # This module is used as a namespace
36
36
  return dotted_rule.next_symbol
37
37
  end
38
38
 
39
+ # Give a String representation of itself.
40
+ # The format of the text representation is
41
+ # "format of dotted rule" + " | " + origin
42
+ # @return [String]
43
+ def to_s()
44
+ return dotted_rule.to_s + " | #{origin}"
45
+ end
46
+
39
47
  private
40
48
 
41
49
  # Return the validated dotted item(rule)
@@ -53,7 +53,7 @@ module Rley # This module is used as a namespace
53
53
  @symbols << the_lhs unless @symbols.include? the_lhs
54
54
 
55
55
  # TODO: remove quadratic execution time
56
- aProduction.rhs.members.each do |symb|
56
+ aProduction.rhs.each do |symb|
57
57
  next if symbols.include? symb
58
58
  @symbols << symb
59
59
  end
@@ -68,7 +68,7 @@ module Rley # This module is used as a namespace
68
68
 
69
69
  # Drop productions with one terminal in rhs or with a nullable lhs
70
70
  filtered_rules = rules.reject do |prod|
71
- prod.lhs.nullable? || prod.rhs.members.find do |symb|
71
+ prod.lhs.nullable? || prod.rhs.find do |symb|
72
72
  symb.kind_of?(Terminal)
73
73
  end
74
74
  end
@@ -11,6 +11,12 @@ module Rley # This module is used as a namespace
11
11
  def initialize(aName)
12
12
  @name = aName.dup
13
13
  end
14
+
15
+ # The String representation of the grammar symbol
16
+ # @return [String]
17
+ def to_s()
18
+ return name.to_s
19
+ end
14
20
 
15
21
  end # class
16
22
  end # module
@@ -5,7 +5,7 @@ module Rley # This module is used as a namespace
5
5
  # A symbol sequence is a suite of grammar symbols
6
6
  class SymbolSeq
7
7
  extend Forwardable
8
- def_delegators :@members, :empty?, :size, :[]
8
+ def_delegators :@members, :empty?, :size, :[], :each, :find, :map
9
9
 
10
10
  # The sequence of symbols
11
11
  attr_reader(:members)
@@ -28,6 +28,8 @@ module Rley # This module is used as a namespace
28
28
 
29
29
  return result
30
30
  end
31
+
32
+
31
33
  end # class
32
34
  end # module
33
35
  end # module
@@ -12,6 +12,12 @@ module Rley # This module is used as a namespace
12
12
  super(aText) # Do we need to separate the text from the name?
13
13
  @text = aText.dup
14
14
  end
15
+
16
+ # The String representation of the verbatim symbol
17
+ # @return [String]
18
+ def to_s()
19
+ return "'#{text}'"
20
+ end
15
21
  end # class
16
22
  end # module
17
23
  end # module
@@ -94,6 +94,11 @@ module Rley # Open this namespace to avoid module qualifier prefixes
94
94
  it 'should know the symbol after the dot' do
95
95
  expect(subject.next_symbol).to eq(t_b)
96
96
  end
97
+
98
+ it 'should give its text representation' do
99
+ expectation = "sentence => A . B C"
100
+ expect(subject.to_s).to eq(expectation)
101
+ end
97
102
  end
98
103
 
99
104
  end # describe
@@ -149,20 +149,11 @@ module Rley # Open this namespace to avoid module qualifier prefixes
149
149
  end # context
150
150
 
151
151
  context 'Parsing: ' do
152
- # Helper method. Compare the data from the parse state
153
- # with values from expectation hash.
154
- def compare_state(aState, expectations)
155
- expect(aState.origin).to eq(expectations[:origin])
156
- dotted_item = aState.dotted_rule
157
- expect(dotted_item.production).to eq(expectations[:production])
158
- expect(dotted_item.position).to eq(expectations[:dot])
159
- end
160
-
161
152
  # Helper method. Compare the data from all the parse states
162
- # of a given StateSet with an array of expectation hashes.
163
- def compare_state_set(aStateSet, expectations)
153
+ # of a given StateSet with an array of expectation string.
154
+ def compare_state_texts(aStateSet, expectations)
164
155
  (0...expectations.size).each do |i|
165
- compare_state(aStateSet.states[i], expectations[i])
156
+ expect(aStateSet.states[i].to_s).to eq(expectations[i])
166
157
  end
167
158
  end
168
159
 
@@ -172,79 +163,65 @@ module Rley # Open this namespace to avoid module qualifier prefixes
172
163
 
173
164
  ######################
174
165
  # Expectation chart[0]:
175
- # S -> . A, 0 # start rule
176
- # A -> . "a" A "c", 0 # predict from 0
177
- # A -> . "b", 0 # predict from 0
178
- expectations = [
179
- { origin: 0, production: prod_S, dot: 0 },
180
- { origin: 0, production: prod_A1, dot: 0 },
181
- { origin: 0, production: prod_A2, dot: 0 }
166
+ expected = [
167
+ "S => . A | 0", # start rule
168
+ "A => . 'a' A 'c' | 0", # predict from 0
169
+ "A => . 'b' | 0" # predict from 0
182
170
  ]
183
- compare_state_set(parse_result.chart[0], expectations)
171
+ compare_state_texts(parse_result.chart[0], expected)
184
172
 
185
173
  ######################
186
- state_set_1 = parse_result.chart[1]
187
- expect(state_set_1.states.size).to eq(3)
188
174
  # Expectation chart[1]:
189
- # 0: A -> "a" . A "c", 0 # scan from S(0) 1
190
- # 1: A -> . "a" A "c", 1 # predict from 0
191
- # 2: A -> . "b", 1 # predict from 0
192
- expectations = [
193
- { origin: 0, production: prod_A1, dot: 1 },
194
- { origin: 1, production: prod_A1, dot: 0 },
195
- { origin: 1, production: prod_A2, dot: 0 }
175
+ expected = [
176
+ "A => 'a' . A 'c' | 0", # scan from S(0) 1
177
+ "A => . 'a' A 'c' | 1", # predict from 0
178
+ "A => . 'b' | 1" # predict from 0
196
179
  ]
197
- compare_state_set(state_set_1, expectations)
180
+ state_set_1 = parse_result.chart[1]
181
+ expect(state_set_1.states.size).to eq(3)
182
+ compare_state_texts(state_set_1, expected)
198
183
 
199
184
  ######################
200
- state_set_2 = parse_result.chart[2]
201
- expect(state_set_2.states.size).to eq(3)
202
185
  # Expectation chart[2]:
203
- # 0: A -> "a" . A "c", 1 # scan from S(0) 1
204
- # 1: A -> . "a" A "c", 2 # predict from 0
205
- # 2: A -> . "b", 2 # predict from 0
206
- expectations = [
207
- { origin: 1, production: prod_A1, dot: 1 },
208
- { origin: 2, production: prod_A1, dot: 0 },
209
- { origin: 2, production: prod_A2, dot: 0 }
186
+ expected = [
187
+ "A => 'a' . A 'c' | 1", # scan from S(0) 1
188
+ "A => . 'a' A 'c' | 2", # predict from 0
189
+ "A => . 'b' | 2" # predict from 0
210
190
  ]
211
- compare_state_set(state_set_2, expectations)
191
+ state_set_2 = parse_result.chart[2]
192
+ expect(state_set_2.states.size).to eq(3)
193
+ compare_state_texts(state_set_2, expected)
212
194
 
213
195
  ######################
214
- state_set_3 = parse_result.chart[3]
215
- expect(state_set_3.states.size).to eq(2)
216
196
  # Expectation chart[3]:
217
- # 0: A -> "b" ., 2 # scan from S(2) 2
218
- # 1: A -> "a" A . "c", 1 # complete from 0 and S(2) 0
219
- expectations = [
220
- { origin: 2, production: prod_A2, dot: -1 },
221
- { origin: 1, production: prod_A1, dot: 2 }
197
+ expected = [
198
+ "A => 'b' . | 2", # scan from S(2) 2
199
+ "A => 'a' A . 'c' | 1" # complete from 0 and S(2) 0
222
200
  ]
223
- compare_state_set(state_set_3, expectations)
201
+ state_set_3 = parse_result.chart[3]
202
+ expect(state_set_3.states.size).to eq(2)
203
+ compare_state_texts(state_set_3, expected)
204
+
224
205
 
225
206
  ######################
226
- state_set_4 = parse_result.chart[4]
227
- expect(state_set_4.states.size).to eq(2)
228
207
  # Expectation chart[4]:
229
- # 0: A -> "a" A "c" ., 1 # scan from S(3) 1
230
- # 1: A -> "a" A . "c", 0 # complete from 0 and S(1) 0
231
- expectations = [
232
- { origin: 1, production: prod_A1, dot: -1 },
233
- { origin: 0, production: prod_A1, dot: 2 }
208
+ expected = [
209
+ "A => 'a' A 'c' . | 1", # scan from S(3) 1
210
+ "A => 'a' A . 'c' | 0" # complete from 0 and S(1) 0
234
211
  ]
235
- compare_state_set(state_set_4, expectations)
212
+ state_set_4 = parse_result.chart[4]
213
+ expect(state_set_4.states.size).to eq(2)
214
+ compare_state_texts(state_set_4, expected)
236
215
 
237
216
  ######################
238
- state_set_5 = parse_result.chart[5]
239
- expect(state_set_5.states.size).to eq(2)
240
217
  # Expectation chart[5]:
241
- # 0: A -> "a" A "c" ., 0 # scan from S(4) 1
242
- # 1: S -> A ., 0 # complete from 0 and S(0) 0
243
- expectations = [
244
- { origin: 0, production: prod_A1, dot: -1 },
245
- { origin: 0, production: prod_S, dot: -1 }
218
+ expected = [
219
+ "A => 'a' A 'c' . | 0", # scan from S(4) 1
220
+ "S => A . | 0" # complete from 0 and S(0) 0
246
221
  ]
247
- compare_state_set(state_set_5, expectations)
222
+ state_set_5 = parse_result.chart[5]
223
+ expect(state_set_5.states.size).to eq(2)
224
+ compare_state_texts(state_set_5, expected)
248
225
  end
249
226
 
250
227
  it 'should parse a valid simple expression' do
@@ -254,112 +231,85 @@ module Rley # Open this namespace to avoid module qualifier prefixes
254
231
 
255
232
  ###################### S(0): . 2 + 3 * 4
256
233
  # Expectation chart[0]:
257
- # (1) P -> . S, 0 # start rule
258
- # (2) S -> . S "+" M, 0 # predict from (1)
259
- # (3) S -> . M, 0 # predict from (1)
260
- # (4) M -> . M "*" T, 0 # predict from (3)
261
- # (5) M -> . T, 0 # predict from (3)
262
- # (6) T -> . integer, 0 # predict from (3)
263
- expectations = [
264
- { origin: 0, production: prod_P, dot: 0 },
265
- { origin: 0, production: prod_S1, dot: 0 },
266
- { origin: 0, production: prod_S2, dot: 0 },
267
- { origin: 0, production: prod_M1, dot: 0 },
268
- { origin: 0, production: prod_M2, dot: 0 },
269
- { origin: 0, production: prod_T, dot: 0 }
234
+ expected = [
235
+ "P => . S | 0", # start rule
236
+ "S => . S '+' M | 0", # predict from (1)
237
+ "S => . M | 0", # predict from (1)
238
+ "M => . M '*' T | 0", # predict from (3)
239
+ "M => . T | 0", # predict from (3)
240
+ "T => . integer | 0" # predict from (3)
270
241
  ]
271
- compare_state_set(parse_result.chart[0], expectations)
242
+ compare_state_texts(parse_result.chart[0], expected)
243
+
272
244
 
273
245
  ###################### S(1): 2 . + 3 * 4
274
246
  # Expectation chart[1]:
275
- # (1) T -> integer ., 0 # scan from S(0) 6
276
- # (2) M -> T ., 0 # complete from (1) and S(0) 5
277
- # (3) S -> M ., 0 # complete from (2) and S(0) 3
278
- # (4) M -> M . "*" T, 0 # complete from (2) and S(0) 4
279
- # (5) P -> S ., 0 # complete from (4) and S(0) 1
280
- # (6) S -> S . "+" M, 0 # complete from (4) and S(0) 2
281
- expectations = [
282
- { origin: 0, production: prod_T, dot: -1 },
283
- { origin: 0, production: prod_M2, dot: -1 },
284
- { origin: 0, production: prod_S2, dot: -1 },
285
- { origin: 0, production: prod_M1, dot: 1 },
286
- { origin: 0, production: prod_P, dot: -1 },
287
- { origin: 0, production: prod_S1, dot: 1 }
247
+ expected = [
248
+ "T => integer . | 0", # scan from S(0) 6
249
+ "M => T . | 0", # complete from (1) and S(0) 5
250
+ "S => M . | 0", # complete from (2) and S(0) 3
251
+ "M => M . '*' T | 0", # complete from (2) and S(0) 4
252
+ "P => S . | 0", # complete from (4) and S(0) 1
253
+ "S => S . '+' M | 0" # complete from (4) and S(0) 2
288
254
  ]
289
- compare_state_set(parse_result.chart[1], expectations)
255
+ compare_state_texts(parse_result.chart[1], expected)
290
256
 
291
257
 
292
258
  ###################### S(2): 2 + . 3 * 4
293
259
  # Expectation chart[2]:
294
- # (1) S -> S "+" . M, 0 # scan from S(1) 6
295
- # (2) M -> . M "*" T, 2 # predict from (1)
296
- # (3) M -> . T, 2 # predict from (1)
297
- # (4) T -> . integer, 2 # predict from (3)
298
- expectations = [
299
- { origin: 0, production: prod_S1, dot: 2 },
300
- { origin: 2, production: prod_M1, dot: 0 },
301
- { origin: 2, production: prod_M2, dot: 0 },
302
- { origin: 2, production: prod_T, dot: 0 }
260
+ expected = [
261
+ "S => S '+' . M | 0", # scan from S(1) 6
262
+ "M => . M '*' T | 2", # predict from (1)
263
+ "M => . T | 2", # predict from (1)
264
+ "T => . integer | 2" # predict from (3)
303
265
  ]
304
- compare_state_set(parse_result.chart[2], expectations)
266
+ compare_state_texts(parse_result.chart[2], expected)
267
+
305
268
 
306
269
  ###################### S(3): 2 + 3 . * 4
307
270
  # Expectation chart[3]:
308
- # (1) T -> integer ., 2 # scan from S(2) 4
309
- # (2) M -> T ., 2 # complete from (1) and S(2) 3
310
- # (3) S -> S "+" M ., 0 # complete from (1) and S(2) 1
311
- # (4) M -> M . "*" T, 2 # complete from (2) and S(2) 2
312
- # (5) P -> S ., 0 # complete from (4) and S(0) 1
313
- expectations = [
314
- { origin: 2, production: prod_T, dot: -1 },
315
- { origin: 2, production: prod_M2, dot: -1 },
316
- { origin: 0, production: prod_S1, dot: -1 },
317
- { origin: 2, production: prod_M1, dot: 1 },
318
- { origin: 0, production: prod_P, dot: -1 }
271
+ expected = [
272
+ "T => integer . | 2", # scan from S(2) 4
273
+ "M => T . | 2", # complete from (1) and S(2) 3
274
+ "S => S '+' M . | 0", # complete from (1) and S(2) 1
275
+ "M => M . '*' T | 2", # complete from (2) and S(2) 2
276
+ "P => S . | 0" # complete from (4) and S(0) 1
319
277
  ]
320
- compare_state_set(parse_result.chart[3], expectations)
278
+ compare_state_texts(parse_result.chart[3], expected)
321
279
 
322
280
  ###################### S(4): 2 + 3 * . 4
323
281
  # Expectation chart[4]:
324
- # (1) M -> M "*" . T, 2 # scan from S(3) 4
325
- # (2) T -> . number, 4 # predict from (1)
326
-
327
- expectations = [
328
- { origin: 2, production: prod_M1, dot: 2 },
329
- { origin: 4, production: prod_T, dot: 0 }
282
+ expected = [
283
+ "M => M '*' . T | 2", # scan from S(3) 4
284
+ "T => . integer | 4" # predict from (1)
330
285
  ]
331
- compare_state_set(parse_result.chart[4], expectations)
286
+ compare_state_texts(parse_result.chart[4], expected)
332
287
 
333
288
  ###################### S(5): 2 + 3 * 4 .
334
289
  # Expectation chart[5]:
335
- # (1) T -> number ., 4 # scan from S(4) 2
336
- # (2) M -> M "*" T ., 2 # complete from (1) and S(4) 1
337
- # (3) S -> S "+" M ., 0 # complete from (2) and S(2) 1
338
- # (4) M -> M . "*" T, 2 # complete from (2) and S(2) 2
339
- # (5) P -> S ., 0 # complete from (3) and S(2) 2
340
- expectations = [
341
- { origin: 4, production: prod_T, dot: -1 },
342
- { origin: 2, production: prod_M1, dot: -1 },
343
- { origin: 0, production: prod_S1, dot: -1 },
344
- { origin: 2, production: prod_M1, dot: 1 },
345
- { origin: 0, production: prod_P, dot: -1 }
290
+ expected = [
291
+ "T => integer . | 4", # scan from S(4) 2
292
+ "M => M '*' T . | 2", # complete from (1) and S(4) 1
293
+ "S => S '+' M . | 0", # complete from (2) and S(2) 1
294
+ "M => M . '*' T | 2", # complete from (2) and S(2) 2
295
+ "P => S . | 0" # complete from (3) and S(2) 2
346
296
  ]
347
- compare_state_set(parse_result.chart[5], expectations)
297
+ compare_state_texts(parse_result.chart[5], expected)
348
298
  end
349
-
350
-
299
+
300
+
351
301
  it 'should parse an ambiguous grammar' do
352
302
  # Grammar 3: A ambiguous arithmetic expression language
353
303
  # (based on example in article on Earley's algorithm in Wikipedia)
354
- # P ::= S.
355
- # S ::= S "+" S.
356
- # S ::= S "*" S.
357
- # S ::= T.
358
- # T ::= an integer number token.
304
+ # P => S.
305
+ # S => S "+" S.
306
+ # S => S "*" S.
307
+ # S => T.
308
+ # T => an integer number token.
359
309
  t_int = Syntax::Literal.new('integer', /[-+]?\d+/)
360
310
  t_plus = Syntax::VerbatimSymbol.new('+')
361
311
  t_star = Syntax::VerbatimSymbol.new('*')
362
-
312
+
363
313
  builder = Syntax::GrammarBuilder.new
364
314
  builder.add_terminals(t_int, t_plus, t_star)
365
315
  builder.add_production('P' => 'S')
@@ -394,49 +344,35 @@ module Rley # Open this namespace to avoid module qualifier prefixes
394
344
 
395
345
  ###################### S(0) == . a a c c
396
346
  # Expectation chart[0]:
397
- # S -> . A, 0 # start rule
398
- # A -> . "a" A "c", 0
399
- # A -> . "b", 0
400
- expectations = [
401
- { origin: 0, production: prod_S, dot: 0 },
402
- { origin: 0, production: prod_A1, dot: 0 },
403
- { origin: 0, production: prod_A2, dot: 0 }
347
+ expected = [
348
+ "S => . A | 0", # start rule
349
+ "A => . 'a' A 'c' | 0", # predict from 0
350
+ "A => . 'b' | 0" # predict from 0
404
351
  ]
405
- compare_state_set(parse_result.chart[0], expectations)
352
+ compare_state_texts(parse_result.chart[0], expected)
406
353
 
407
354
  ###################### S(1) == a . a c c
408
- state_set_1 = parse_result.chart[1]
409
- expect(state_set_1.states.size).to eq(3)
410
- # Expectation chart[1]:
411
- # 0: A -> "a" . A "c", 0 # scan from S(0) 1
412
- # 1: A -> . "a" A "c", 1 # predict from 0
413
- # 2: A -> . "b", 1 # predict from 0
414
- expectations = [
415
- { origin: 0, production: prod_A1, dot: 1 },
416
- { origin: 1, production: prod_A1, dot: 0 },
417
- { origin: 1, production: prod_A2, dot: 0 }
355
+ expected = [
356
+ "A => 'a' . A 'c' | 0", # scan from S(0) 1
357
+ "A => . 'a' A 'c' | 1", # predict from 0
358
+ "A => . 'b' | 1" # predict from 0
418
359
  ]
419
- compare_state_set(state_set_1, expectations)
360
+ compare_state_texts(parse_result.chart[1], expected)
420
361
 
421
362
  ###################### S(2) == a a . c c
422
- state_set_2 = parse_result.chart[2]
423
- expect(state_set_2.states.size).to eq(3)
424
- # Expectation chart[2]:
425
- # 0: A -> "a" . A "c", 1 # scan from S(0) 1
426
- # 1: A -> . "a" A "c", 2 # predict from 0
427
- # 2: A -> . "b", 2 # predict from 0
428
- expectations = [
429
- { origin: 1, production: prod_A1, dot: 1 },
430
- { origin: 2, production: prod_A1, dot: 0 },
431
- { origin: 2, production: prod_A2, dot: 0 }
363
+ expected = [
364
+ "A => 'a' . A 'c' | 1", # scan from S(0) 1
365
+ "A => . 'a' A 'c' | 2", # predict from 0
366
+ "A => . 'b' | 2" # predict from 0
432
367
  ]
433
- compare_state_set(state_set_2, expectations)
368
+ compare_state_texts(parse_result.chart[2], expected)
369
+
434
370
 
435
371
  ###################### S(3) == a a c? c
436
372
  state_set_3 = parse_result.chart[3]
437
373
  expect(state_set_3.states).to be_empty # This is an error symptom
438
374
  end
439
-
375
+
440
376
  it 'should parse a grammar with nullable nonterminals' do
441
377
  # Grammar 4: A grammar with nullable nonterminal
442
378
  # based on example in "Parsing Techniques" book (D. Grune, C. Jabobs)
@@ -446,11 +382,11 @@ module Rley # Open this namespace to avoid module qualifier prefixes
446
382
  # F ::= a.
447
383
  # Q ::= *.
448
384
  # Q ::= /.
449
- # Q ::=.
385
+ # Q ::=.
450
386
  t_a = Syntax::VerbatimSymbol.new('a')
451
387
  t_star = Syntax::VerbatimSymbol.new('*')
452
388
  t_slash = Syntax::VerbatimSymbol.new('/')
453
-
389
+
454
390
  builder = Syntax::GrammarBuilder.new
455
391
  builder.add_terminals(t_a, t_star, t_slash)
456
392
  builder.add_production('Z' => 'E')
@@ -458,8 +394,8 @@ module Rley # Open this namespace to avoid module qualifier prefixes
458
394
  builder.add_production('E' => 'F')
459
395
  builder.add_production('F' => t_a)
460
396
  builder.add_production('Q' => t_star)
461
- builder.add_production('Q' => t_slash)
462
- builder.add_production('Q' => []) # Empty production
397
+ builder.add_production('Q' => t_slash)
398
+ builder.add_production('Q' => []) # Empty production
463
399
  tokens = [
464
400
  Token.new('a', t_a),
465
401
  Token.new('a', t_a),
@@ -473,111 +409,77 @@ module Rley # Open this namespace to avoid module qualifier prefixes
473
409
  prod_Q1 = builder.productions[4]
474
410
  prod_Q2 = builder.productions[5]
475
411
  prod_Q3 = builder.productions[6]
476
-
412
+
477
413
  instance = EarleyParser.new(builder.grammar)
478
414
  expect { instance.parse(tokens) }.not_to raise_error
479
415
  parse_result = instance.parse(tokens)
480
416
  expect(parse_result.success?).to eq(true)
481
-
417
+
482
418
  ###################### S(0) == . a a / a
483
419
  # Expectation chart[0]:
484
- # (1) S -> . E, 0 # start rule
485
- # (2) E -> . E Q F, 0 # predict from (1)
486
- # (3) E -> . F, 0 # predict from (1)
487
- # (4) F -> . a # predict from (3)
488
- expectations = [
489
- { origin: 0, production: prod_Z, dot: 0 },
490
- { origin: 0, production: prod_E1, dot: 0 },
491
- { origin: 0, production: prod_E2, dot: 0 },
492
- { origin: 0, production: prod_F, dot: 0 }
420
+ expected = [
421
+ "Z => . E | 0", # start rule
422
+ "E => . E Q F | 0", # predict from (1)
423
+ "E => . F | 0", # predict from (1)
424
+ "F => . 'a' | 0" # predict from (3)
493
425
  ]
494
- compare_state_set(parse_result.chart[0], expectations)
426
+ compare_state_texts(parse_result.chart[0], expected)
495
427
 
496
428
  ###################### S(1) == a . a / a
497
429
  # Expectation chart[1]:
498
- # (1) F -> a ., 0 # scan from S(0) 4
499
- # (2) E -> F ., 0 # complete from (1) and S(0) 3
500
- # (3) S -> E ., 0 # complete from (2) and S(0) 1
501
- # (4) E -> E . Q F, 0 # complete from (2) and S(0) 2
502
- # (5) Q -> . *, 1 # Predict from (4)
503
- # (6) Q -> . /, 1 # Predict from (4)
504
- # (7) Q -> ., 1 # Predict from (4)
505
- # (8) E -> E Q . F, 0 # Modified predict from (4)
506
- # (9) F -> . a, 1 # Predict from (8)
507
- expectations = [
508
- { origin: 0, production: prod_F, dot: -1 },
509
- { origin: 0, production: prod_E2, dot: -1 },
510
- { origin: 0, production: prod_Z, dot: -1 },
511
- { origin: 0, production: prod_E1, dot: 1 },
512
- { origin: 1, production: prod_Q1, dot: 0 },
513
- { origin: 1, production: prod_Q2, dot: 0 },
514
- { origin: 1, production: prod_Q3, dot: -2 },
515
- { origin: 0, production: prod_E1, dot: 2 },
516
- { origin: 1, production: prod_F, dot: 0 }
430
+ expected = [
431
+ "F => 'a' . | 0", # scan from S(0) 4
432
+ "E => F . | 0", # complete from (1) and S(0) 3
433
+ "Z => E . | 0", # complete from (2) and S(0) 1
434
+ "E => E . Q F | 0", # complete from (2) and S(0) 2
435
+ "Q => . '*' | 1", # Predict from (4)
436
+ "Q => . '/' | 1", # Predict from (4)
437
+ "Q => . | 1", # Predict from (4)
438
+ "E => E Q . F | 0", # Modified predict from (4)
439
+ "F => . 'a' | 1" # Predict from (8)
517
440
  ]
518
- compare_state_set(parse_result.chart[1], expectations)
441
+ compare_state_texts(parse_result.chart[1], expected)
519
442
 
520
443
  ###################### S(2) == a a . / a
521
444
  # Expectation chart[2]:
522
- # (1) F -> a ., 1 # scan from S(1) 9
523
- # (2) E -> E Q F ., 0 # complete from (1) and S(1) 8
524
- # (3) S -> E ., 0 # complete from (1) and S(0) 1
525
- # (4) E -> E . Q F, 0 # complete from (1) and S(0) 2
526
- # (5) Q -> . *, 2 # Predict from (4)
527
- # (6) Q -> . /, 2 # Predict from (4)
528
- # (7) Q -> ., 2 # Predict from (4)
529
- # (8) E -> E Q . F, 0 # Complete from (5) and S(1) 4
530
- # (9) F -> . a, 1 # Predict from (8)
531
- expectations = [
532
- { origin: 1, production: prod_F, dot: -1 },
533
- { origin: 0, production: prod_E1, dot: -1 },
534
- { origin: 0, production: prod_Z, dot: -1 },
535
- { origin: 0, production: prod_E1, dot: 1 },
536
- { origin: 2, production: prod_Q1, dot: 0 },
537
- { origin: 2, production: prod_Q2, dot: 0 },
538
- { origin: 2, production: prod_Q3, dot: -2 },
539
- { origin: 0, production: prod_E1, dot: 2 },
540
- { origin: 2, production: prod_F, dot: 0 },
445
+ expected = [
446
+ "F => 'a' . | 1", # scan from S(1) 9
447
+ "E => E Q F . | 0", # complete from (1) and S(1) 8
448
+ "Z => E . | 0", # complete from (1) and S(0) 1
449
+ "E => E . Q F | 0", # complete from (1) and S(0) 2
450
+ "Q => . '*' | 2", # Predict from (4)
451
+ "Q => . '/' | 2", # Predict from (4)
452
+ "Q => . | 2", # Predict from (4)
453
+ "E => E Q . F | 0", # Complete from (5) and S(1) 4
454
+ "F => . 'a' | 2" # Predict from (8)
541
455
  ]
542
- compare_state_set(parse_result.chart[2], expectations)
456
+ compare_state_texts(parse_result.chart[2], expected)
457
+
543
458
 
544
459
  ###################### S(3) == a a / . a
545
460
  # Expectation chart[3]:
546
- # (1) Q -> / ., 2 # scan from S(2) 6
547
- # (2) E -> E Q . F, 0 # complete from (1) and S(1) 4
548
- # (3) F -> . a, 3 # Predict from (2)
549
- expectations = [
550
- { origin: 2, production: prod_Q2, dot: -1 },
551
- { origin: 0, production: prod_E1, dot: 2 },
552
- { origin: 3, production: prod_F, dot: 0 }
461
+ expected = [
462
+ "Q => '/' . | 2", # scan from S(2) 6
463
+ "E => E Q . F | 0", # complete from (1) and S(1) 4
464
+ "F => . 'a' | 3" # Predict from (2)
553
465
  ]
554
- compare_state_set(parse_result.chart[3], expectations)
466
+ compare_state_texts(parse_result.chart[3], expected)
467
+
555
468
 
556
-
557
469
  ###################### S(4) == a a / a .
558
470
  # Expectation chart[4]:
559
- # (1) F -> a ., 3 # scan from S(3) 3
560
- # (2) E -> E Q F ., 0 # complete from (1) and S(3) 2
561
- # (3) S -> E ., 0 # complete from (2) and S(0) 1
562
- # (4) E -> E . Q F, 0 # complete from (2) and S(0) 2
563
- # (5) Q -> . *, 3 # Predict from (4)
564
- # (6) Q -> . /, 3 # Predict from (4)
565
- # (7) Q -> ., 3 # Predict from (4)
566
- # (8) E -> E Q . F, 0 # Modified predict from (4)
567
- # (9) F -> . a, 4 # Predict from (8)
568
- expectations = [
569
- { origin: 3, production: prod_F, dot: -1 },
570
- { origin: 0, production: prod_E1, dot: -1 },
571
- { origin: 0, production: prod_Z, dot: -1 },
572
- { origin: 0, production: prod_E1, dot: 1 },
573
- { origin: 4, production: prod_Q1, dot: 0 },
574
- { origin: 4, production: prod_Q2, dot: 0 },
575
- { origin: 4, production: prod_Q3, dot: -2 },
576
- { origin: 0, production: prod_E1, dot: 2 },
577
- { origin: 4, production: prod_F, dot: 0 },
471
+ expected = [
472
+ "F => 'a' . | 3", # scan from S(3) 3
473
+ "E => E Q F . | 0", # complete from (1) and S(3) 2
474
+ "Z => E . | 0", # complete from (2) and S(0) 1
475
+ "E => E . Q F | 0", # complete from (2) and S(0) 2
476
+ "Q => . '*' | 4", # Predict from (4)
477
+ "Q => . '/' | 4", # Predict from (4)
478
+ "Q => . | 4", # Predict from (4)
479
+ "E => E Q . F | 0", # Modified predict from (4)
480
+ "F => . 'a' | 4" # Predict from (8)
578
481
  ]
579
- compare_state_set(parse_result.chart[4], expectations)
580
-
482
+ compare_state_texts(parse_result.chart[4], expected)
581
483
  end
582
484
  end # context
583
485
 
@@ -90,6 +90,11 @@ module Rley # Open this namespace to avoid module qualifier prefixes
90
90
  it 'should know the next expected symbol' do
91
91
  expect(subject.next_symbol).to eq(t_c)
92
92
  end
93
+
94
+ it 'should know its text representation' do
95
+ expected = 'sentence => A B . C | 3'
96
+ expect(subject.to_s).to eq(expected)
97
+ end
93
98
  end # context
94
99
 
95
100
  end # describe
@@ -18,6 +18,12 @@ module Rley # Open this namespace to avoid module qualifier prefixes
18
18
  expect(subject.name).to eq(sample_name)
19
19
  end
20
20
  end # context
21
+
22
+ context 'Provided services:' do
23
+ it 'should give its text representation' do
24
+ expect(subject.to_s).to eq(sample_name)
25
+ end
26
+ end # context
21
27
 
22
28
  end # describe
23
29
  end # module
@@ -22,6 +22,13 @@ module Rley # Open this namespace to avoid module qualifier prefixes
22
22
  expect(subject.text).to eq(sample_name)
23
23
  end
24
24
  end # context
25
+
26
+ context 'Provided services:' do
27
+ it 'should give its text representation' do
28
+ expected = "'#{sample_name}'"
29
+ expect(subject.to_s).to eq(expected)
30
+ end
31
+ end # context
25
32
 
26
33
  end # describe
27
34
  end # module
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rley
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.15
4
+ version: 0.0.16
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dimitri Geshef
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-20 00:00:00.000000000 Z
11
+ date: 2014-11-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake