rley 0.0.15 → 0.0.16

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