rley 0.3.04 → 0.3.05

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.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +7 -3
  3. data/CHANGELOG.md +3 -0
  4. data/Rakefile +30 -30
  5. data/examples/parsers/parsing_L0.rb +1 -1
  6. data/examples/parsers/parsing_L1.rb +1 -1
  7. data/examples/parsers/parsing_abc.rb +1 -1
  8. data/examples/parsers/parsing_ambig.rb +1 -1
  9. data/examples/parsers/parsing_another.rb +1 -1
  10. data/examples/parsers/parsing_b_expr.rb +1 -1
  11. data/examples/parsers/parsing_err_expr.rb +1 -1
  12. data/examples/parsers/parsing_groucho.rb +1 -1
  13. data/examples/parsers/parsing_right_recursive.rb +1 -1
  14. data/examples/parsers/parsing_tricky.rb +1 -1
  15. data/lib/rley/constants.rb +2 -2
  16. data/lib/rley/formatter/base_formatter.rb +0 -2
  17. data/lib/rley/formatter/debug.rb +0 -2
  18. data/lib/rley/formatter/json.rb +1 -3
  19. data/lib/rley/gfg/call_edge.rb +31 -30
  20. data/lib/rley/gfg/edge.rb +22 -23
  21. data/lib/rley/gfg/end_vertex.rb +22 -24
  22. data/lib/rley/gfg/epsilon_edge.rb +20 -21
  23. data/lib/rley/gfg/grm_flow_graph.rb +39 -39
  24. data/lib/rley/gfg/item_vertex.rb +16 -17
  25. data/lib/rley/gfg/non_terminal_vertex.rb +3 -4
  26. data/lib/rley/gfg/return_edge.rb +32 -31
  27. data/lib/rley/gfg/scan_edge.rb +25 -26
  28. data/lib/rley/gfg/shortcut_edge.rb +25 -26
  29. data/lib/rley/gfg/start_vertex.rb +0 -2
  30. data/lib/rley/gfg/vertex.rb +8 -8
  31. data/lib/rley/parse_forest_visitor.rb +113 -115
  32. data/lib/rley/parse_tree_visitor.rb +0 -2
  33. data/lib/rley/parser/base_parser.rb +27 -27
  34. data/lib/rley/parser/chart.rb +14 -14
  35. data/lib/rley/parser/dotted_item.rb +33 -33
  36. data/lib/rley/parser/earley_parser.rb +6 -6
  37. data/lib/rley/parser/gfg_chart.rb +8 -15
  38. data/lib/rley/parser/gfg_earley_parser.rb +15 -13
  39. data/lib/rley/parser/gfg_parsing.rb +26 -22
  40. data/lib/rley/parser/grm_items_builder.rb +3 -2
  41. data/lib/rley/parser/parse_entry.rb +3 -9
  42. data/lib/rley/parser/parse_entry_set.rb +14 -19
  43. data/lib/rley/parser/parse_entry_tracker.rb +56 -56
  44. data/lib/rley/parser/parse_forest_builder.rb +215 -214
  45. data/lib/rley/parser/parse_forest_factory.rb +57 -56
  46. data/lib/rley/parser/parse_state.rb +8 -11
  47. data/lib/rley/parser/parse_state_tracker.rb +56 -56
  48. data/lib/rley/parser/parse_tracer.rb +3 -3
  49. data/lib/rley/parser/parse_tree_builder.rb +10 -10
  50. data/lib/rley/parser/parse_walker_factory.rb +30 -33
  51. data/lib/rley/parser/parsing.rb +8 -8
  52. data/lib/rley/parser/state_set.rb +23 -26
  53. data/lib/rley/ptree/non_terminal_node.rb +1 -1
  54. data/lib/rley/ptree/token_range.rb +2 -2
  55. data/lib/rley/sppf/alternative_node.rb +32 -34
  56. data/lib/rley/sppf/composite_node.rb +27 -27
  57. data/lib/rley/sppf/epsilon_node.rb +26 -27
  58. data/lib/rley/sppf/leaf_node.rb +11 -12
  59. data/lib/rley/sppf/non_terminal_node.rb +37 -38
  60. data/lib/rley/sppf/sppf_node.rb +1 -1
  61. data/lib/rley/sppf/token_node.rb +29 -29
  62. data/lib/rley/syntax/grammar.rb +1 -3
  63. data/lib/rley/syntax/grammar_builder.rb +8 -8
  64. data/lib/rley/syntax/non_terminal.rb +2 -4
  65. data/lib/rley/syntax/production.rb +3 -3
  66. data/lib/rley/syntax/symbol_seq.rb +1 -1
  67. data/spec/rley/gfg/call_edge_spec.rb +50 -51
  68. data/spec/rley/gfg/edge_spec.rb +33 -33
  69. data/spec/rley/gfg/end_vertex_spec.rb +26 -27
  70. data/spec/rley/gfg/epsilon_edge_spec.rb +25 -25
  71. data/spec/rley/gfg/grm_flow_graph_spec.rb +1 -1
  72. data/spec/rley/gfg/item_vertex_spec.rb +3 -4
  73. data/spec/rley/gfg/return_edge_spec.rb +51 -51
  74. data/spec/rley/gfg/scan_edge_spec.rb +32 -30
  75. data/spec/rley/gfg/shortcut_edge_spec.rb +1 -1
  76. data/spec/rley/gfg/vertex_spec.rb +3 -3
  77. data/spec/rley/parse_forest_visitor_spec.rb +239 -238
  78. data/spec/rley/parser/dotted_item_spec.rb +1 -1
  79. data/spec/rley/parser/earley_parser_spec.rb +16 -16
  80. data/spec/rley/parser/gfg_earley_parser_spec.rb +30 -31
  81. data/spec/rley/parser/gfg_parsing_spec.rb +11 -10
  82. data/spec/rley/parser/grm_items_builder_spec.rb +2 -2
  83. data/spec/rley/parser/parse_entry_set_spec.rb +4 -4
  84. data/spec/rley/parser/parse_entry_spec.rb +0 -2
  85. data/spec/rley/parser/parse_forest_builder_spec.rb +82 -57
  86. data/spec/rley/parser/parse_forest_factory_spec.rb +84 -82
  87. data/spec/rley/parser/parse_walker_factory_spec.rb +10 -9
  88. data/spec/rley/parser/parsing_spec.rb +0 -1
  89. data/spec/rley/sppf/alternative_node_spec.rb +2 -2
  90. data/spec/rley/sppf/non_terminal_node_spec.rb +0 -1
  91. data/spec/rley/support/ambiguous_grammar_helper.rb +1 -1
  92. data/spec/rley/support/expectation_helper.rb +37 -36
  93. data/spec/rley/support/grammar_abc_helper.rb +17 -17
  94. data/spec/rley/support/grammar_b_expr_helper.rb +40 -39
  95. data/spec/rley/support/grammar_helper.rb +2 -1
  96. data/spec/rley/support/{grammar_L0_helper.rb → grammar_l0_helper.rb} +82 -81
  97. data/spec/rley/support/grammar_sppf_helper.rb +24 -25
  98. data/spec/rley/syntax/grammar_spec.rb +1 -1
  99. metadata +2 -2
@@ -126,7 +126,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
126
126
 
127
127
  # Case: different productions
128
128
  instance = DottedItem.new(empty_prod, 0)
129
- expect(subject).not_to be_successor_of(subject)
129
+ expect(subject).not_to be_successor_of(instance)
130
130
 
131
131
  # Case: one position difference
132
132
  instance = DottedItem.new(sample_prod, 0)
@@ -220,8 +220,8 @@ module Rley # Open this namespace to avoid module qualifier prefixes
220
220
  ######################
221
221
  # Expectation chart[5]:
222
222
  expected = [
223
- "A => 'a' A 'c' . | 0", # scan from S(4) 1
224
- 'S => A . | 0' # complete from 0 and S(0) 0
223
+ "A => 'a' A 'c' . | 0", # scan from S(4) 1
224
+ 'S => A . | 0' # complete from 0 and S(0) 0
225
225
  ]
226
226
  state_set_5 = parse_result.chart[5]
227
227
  expect(state_set_5.states.size).to eq(2)
@@ -325,7 +325,7 @@ SNIPPET
325
325
  ###################### S(5): 2 + 3 * 4 .
326
326
  # Expectation chart[5]:
327
327
  expected = [
328
- 'T => integer . | 4', # scan from S(4) 2
328
+ 'T => integer . | 4', # scan from S(4) 2
329
329
  "M => M '*' T . | 2", # complete from (1) and S(4) 1
330
330
  "S => S '+' M . | 0", # complete from (2) and S(2) 1
331
331
  "M => M . '*' T | 2", # complete from (2) and S(2) 2
@@ -357,14 +357,14 @@ SNIPPET
357
357
  "Ss => . A A 'x' | 0", # Start rule
358
358
  'A => . | 0', # predict from (1)
359
359
  "Ss => A . A 'x' | 0", # modified predict from (1)
360
- "Ss => A A . 'x' | 0", # modified predict from (1)
360
+ "Ss => A A . 'x' | 0" # modified predict from (1)
361
361
  ]
362
362
  compare_state_texts(parse_result.chart[0], expected)
363
363
 
364
364
  ###################### S(1): x .
365
365
  # Expectation chart[1]:
366
366
  expected = [
367
- "Ss => A A 'x' . | 0", # scan from S(0) 4
367
+ "Ss => A A 'x' . | 0" # scan from S(0) 4
368
368
  ]
369
369
  compare_state_texts(parse_result.chart[1], expected)
370
370
  end
@@ -415,7 +415,7 @@ SNIPPET
415
415
  ###################### S(1): 2 . + 3 * 4
416
416
  # Expectation chart[1]:
417
417
  expected = [
418
- 'L => integer . | 0', # scan from S(0) 4
418
+ 'L => integer . | 0', # scan from S(0) 4
419
419
  'S => L . | 0', # complete from (1) and S(0) 4
420
420
  'P => S . | 0', # complete from (2) and S(0) 1
421
421
  "S => S . '+' S | 0", # complete from (2) and S(0) 2
@@ -439,7 +439,7 @@ SNIPPET
439
439
  expected = [
440
440
  'L => integer . | 2', # scan from S(2) 5
441
441
  'S => L . | 2', # complete from (1) and S(2) 4
442
- "S => S '+' S . | 0", # complete from (2) and S(2) 1
442
+ "S => S '+' S . | 0", # complete from (2) and S(2) 1
443
443
  "S => S . '+' S | 2", # complete from (2) and S(2) 2
444
444
  "S => S . '*' S | 2", # complete from (2) and S(2) 3
445
445
  'P => S . | 0', # complete from (2) and S(0) 1
@@ -649,15 +649,15 @@ MSG
649
649
  ###################### S(1) == a . a / a
650
650
  # Expectation chart[1]:
651
651
  expected = [
652
- "F => 'a' . | 0", # scan from S(0) 4
653
- 'E => F . | 0', # complete from (1) and S(0) 3
654
- 'Z => E . | 0', # complete from (2) and S(0) 1
655
- 'E => E . Q F | 0', # complete from (2) and S(0) 2
656
- "Q => . '*' | 1", # Predict from (4)
657
- "Q => . '/' | 1", # Predict from (4)
658
- 'Q => . | 1', # Predict from (4)
659
- 'E => E Q . F | 0', # Modified predict from (4)
660
- "F => . 'a' | 1" # Predict from (8)
652
+ "F => 'a' . | 0", # scan from S(0) 4
653
+ 'E => F . | 0', # complete from (1) and S(0) 3
654
+ 'Z => E . | 0', # complete from (2) and S(0) 1
655
+ 'E => E . Q F | 0', # complete from (2) and S(0) 2
656
+ "Q => . '*' | 1", # Predict from (4)
657
+ "Q => . '/' | 1", # Predict from (4)
658
+ 'Q => . | 1', # Predict from (4)
659
+ 'E => E Q . F | 0', # Modified predict from (4)
660
+ "F => . 'a' | 1" # Predict from (8)
661
661
  ]
662
662
  compare_state_texts(parse_result.chart[1], expected)
663
663
 
@@ -66,11 +66,15 @@ module Rley # Open this namespace to avoid module qualifier prefixes
66
66
 
67
67
  # Helper method that mimicks the output of a tokenizer
68
68
  # for the language specified by grammar_expr
69
- def grm2_tokens()
70
- input_sequence = [ {'2' => 'integer'}, '+', {'3' => 'integer'},
71
- '*', {'4' => 'integer'}
69
+ def grm2_tokens()
70
+ input_sequence = [
71
+ { '2' => 'integer' },
72
+ '+',
73
+ { '3' => 'integer' },
74
+ '*',
75
+ { '4' => 'integer' }
72
76
  ]
73
- return build_token_sequence(input_sequence, grammar_expr)
77
+ return build_token_sequence(input_sequence, grammar_expr)
74
78
  end
75
79
 
76
80
  # Default instantiation rule
@@ -272,7 +276,7 @@ SNIPPET
272
276
  "M => M . '*' T | 2", # end rule
273
277
  'S. | 0', # exit rule
274
278
  'P => S . | 0', # end rule
275
- "S => S . '+' M | 0", # end rule
279
+ "S => S . '+' M | 0", # end rule
276
280
  'P. | 0' # exit rule
277
281
  ]
278
282
  compare_entry_texts(parse_result.chart[3], expected)
@@ -361,12 +365,12 @@ SNIPPET
361
365
  builder.add_production('S' => %w(S * S))
362
366
  builder.add_production('S' => 'L')
363
367
  builder.add_production('L' => 'integer')
364
- input_sequence = [
365
- {'2' => 'integer'},
366
- '+',
367
- {'3' => 'integer'},
368
- '*',
369
- {'4' => 'integer'}
368
+ input_sequence = [
369
+ { '2' => 'integer' },
370
+ '+',
371
+ { '3' => 'integer' },
372
+ '*',
373
+ { '4' => 'integer' }
370
374
  ]
371
375
  tokens = build_token_sequence(input_sequence, builder.grammar)
372
376
  instance = GFGEarleyParser.new(builder.grammar)
@@ -470,7 +474,7 @@ SNIPPET
470
474
  'P. | 0' # exit rule
471
475
  ]
472
476
  compare_entry_texts(parse_result.chart[5], expected)
473
-
477
+
474
478
  expected_antecedents = {
475
479
  'L => integer . | 4' => ['L => . integer | 4'],
476
480
  'L. | 4' => ['L => integer . | 4'],
@@ -478,14 +482,14 @@ SNIPPET
478
482
  'S. | 4' => ['S => L . | 4'],
479
483
  "S => S '*' S . | 2" => ['S. | 4'],
480
484
  "S => S '*' S . | 0" => ['S. | 4'],
481
- "S => S . '+' S | 4" => ['S. | 4'],
485
+ "S => S . '+' S | 4" => ['S. | 4'],
482
486
  "S => S . '*' S | 4" => ['S. | 4'],
483
487
  'S. | 2' => ["S => S '*' S . | 2"],
484
488
  'S. | 0' => ["S => S '*' S . | 0", "S => S '+' S . | 0"],
485
489
  "S => S '+' S . | 0" => ['S. | 2'],
486
490
  "S => S . '+' S | 2" => ['S. | 2'],
487
491
  "S => S . '*' S | 2" => ['S. | 2'],
488
- 'P => S . | 0' => ['S. | 0'],
492
+ 'P => S . | 0' => ['S. | 0'],
489
493
  "S => S . '+' S | 0" => ['S. | 0'],
490
494
  "S => S . '*' S | 0" => ['S. | 0'],
491
495
  'P. | 0' => ['P => S . | 0']
@@ -518,7 +522,7 @@ SNIPPET
518
522
  # Expectation chart[1]:
519
523
  expected = [
520
524
  'E => id . | 0', # scan 'abc'
521
- 'E. | 0', # exit rule
525
+ 'E. | 0', # exit rule
522
526
  'S => E . | 0', # end rule
523
527
  'E => E . + E | 0', # end rule
524
528
  'S. | 0' # exit rule
@@ -603,14 +607,14 @@ MSG
603
607
  builder.add_terminals(t_int, t_plus, t_lparen, t_rparen)
604
608
  builder.add_production('S' => 'E')
605
609
  builder.add_production('E' => 'int')
606
- builder.add_production('E' => %w[( E + E )])
607
- builder.add_production('E' => %w( E + E ))
608
- input_sequence = [
609
- {'7' => 'int'},
610
- '+',
611
- {'8' => 'int'},
612
- '+',
613
- {'9' => 'int'}
610
+ builder.add_production('E' => %w(( E + E )))
611
+ builder.add_production('E' => %w(E + E))
612
+ input_sequence = [
613
+ { '7' => 'int' },
614
+ '+',
615
+ { '8' => 'int' },
616
+ '+',
617
+ { '9' => 'int' }
614
618
  ]
615
619
  tokens = build_token_sequence(input_sequence, builder.grammar)
616
620
  instance = GFGEarleyParser.new(builder.grammar)
@@ -644,7 +648,7 @@ MSG
644
648
  expected = [
645
649
  "E => E '+' . E | 0", # scan '+'
646
650
  '.E | 2', # exit rule
647
- 'E => . int | 2', # start rule
651
+ 'E => . int | 2', # start rule
648
652
  "E => . '(' E '+' E ')' | 2", # start rule
649
653
  "E => . E '+' E | 2" # start rule
650
654
  ]
@@ -718,7 +722,7 @@ MSG
718
722
  builder.add_production('Q' => t_star)
719
723
  builder.add_production('Q' => t_slash)
720
724
  builder.add_production('Q' => []) # Empty production
721
-
725
+
722
726
  tokens = build_token_sequence(%w(a a / a), builder.grammar)
723
727
  instance = GFGEarleyParser.new(builder.grammar)
724
728
  expect { instance.parse(tokens) }.not_to raise_error
@@ -823,9 +827,6 @@ MSG
823
827
  # S => ;
824
828
  # This grammar requires a time that is quadratic in the number of
825
829
  # input tokens
826
-
827
- t_x = Syntax::VerbatimSymbol.new('x')
828
-
829
830
  builder = Syntax::GrammarBuilder.new
830
831
  builder.add_terminals('a')
831
832
  builder.add_production('S' => %w(a S))
@@ -909,10 +910,8 @@ MSG
909
910
  ]
910
911
  compare_entry_texts(parse_result.chart[4], expected)
911
912
  end
912
-
913
913
  end # context
914
914
  end # describe
915
915
  end # module
916
916
  end # module
917
-
918
- # End of module
917
+ # End of file
@@ -79,8 +79,9 @@ module Rley # Open this namespace to avoid module qualifier prefixes
79
79
  end
80
80
 
81
81
  it 'should have no antecedence for the initial parse entry' do
82
- expect(subject.antecedence.size).to eq(1)
83
- expect(subject.antecedence.fetch(subject.initial_entry)).to be_empty
82
+ antecedence = subject.antecedence
83
+ expect(antecedence.size).to eq(1)
84
+ expect(antecedence.fetch(subject.initial_entry)).to be_empty
84
85
  end
85
86
 
86
87
  =begin
@@ -186,7 +187,7 @@ SNIPPET
186
187
 
187
188
  it 'should apply the scan rule correctly' do
188
189
  # Filling manually first entry set...
189
- fill_first_set()
190
+ fill_first_set
190
191
  # There are two entries expecting a terminal:
191
192
  # ['A => . a A c', 'A => . b']
192
193
  fourth_entry = subject.chart[0].entries[3] # 'A => . a A c'
@@ -201,15 +202,16 @@ SNIPPET
201
202
  # Entry must be past the terminal symbol
202
203
  expect(last_entry.vertex.label).to eq('A => a . A c')
203
204
  expect(last_entry.origin).to eq(0)
204
- expect(subject.antecedence.fetch(last_entry)).to eq([fourth_entry])
205
+ antecedence = subject.antecedence
206
+ expect(antecedence.fetch(last_entry)).to eq([fourth_entry])
205
207
  end
206
208
 
207
209
  it 'should apply the exit rule correctly' do
208
210
  # Filling manually first entry set...
209
- fill_first_set()
211
+ fill_first_set
210
212
 
211
213
  # Initial manually first entry set...
212
- seed_second_set()
214
+ seed_second_set
213
215
 
214
216
  # Given that the scanned token is 'b'...
215
217
  # Then a new entry is added in next entry set
@@ -231,10 +233,10 @@ SNIPPET
231
233
 
232
234
  it 'should apply the end rule correctly' do
233
235
  # Filling manually first entry set...
234
- fill_first_set()
236
+ fill_first_set
235
237
 
236
238
  # Initial manually first entry set...
237
- seed_second_set()
239
+ seed_second_set
238
240
  last_entry = subject.chart[1].last
239
241
 
240
242
  # Given that the scanned token is 'b'...
@@ -290,7 +292,6 @@ SNIPPET
290
292
  end # context
291
293
 
292
294
  context 'Parse forest building:' do
293
-
294
295
  let(:sample_grammar1) do
295
296
  builder = grammar_abc_builder
296
297
  builder.grammar
@@ -318,7 +319,7 @@ SNIPPET
318
319
  end
319
320
 
320
321
  it 'should build a parse forest' do
321
- expect{subject.parse_forest }.not_to raise_error
322
+ expect { subject.parse_forest }.not_to raise_error
322
323
 
323
324
  end
324
325
  =begin
@@ -31,7 +31,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
31
31
  'A => a A . c',
32
32
  'A => a A c .',
33
33
  'A => . b',
34
- 'A => b .',
34
+ 'A => b .'
35
35
  ]
36
36
  expect(items.map(&:to_s)).to eq(expectations)
37
37
  end
@@ -40,4 +40,4 @@ module Rley # Open this namespace to avoid module qualifier prefixes
40
40
  end # module
41
41
  end # module
42
42
 
43
- # End of file
43
+ # End of file
@@ -20,10 +20,10 @@ module Rley # Open this namespace to avoid module qualifier prefixes
20
20
  let(:t_a) { Rley::Syntax::Terminal.new('a') }
21
21
  let(:t_b) { Rley::Syntax::Terminal.new('b') }
22
22
  let(:t_c) { Rley::Syntax::Terminal.new('c') }
23
- let(:nt_repeated_c) { Rley::Syntax::NonTerminal.new('Repetition') }
24
- let(:repeated_prod) { build_prod(nt_repeated_c, t_c, nt_repeated_c) }
23
+ let(:nt_rep_c) { Rley::Syntax::NonTerminal.new('Repetition') }
24
+ let(:repeated_prod) { build_prod(nt_rep_c, t_c, nt_rep_c) }
25
25
  let(:nt_sentence) { Rley::Syntax::NonTerminal.new('Sentence') }
26
- let(:sample_prod) { build_prod(nt_sentence, t_a, t_b, t_b, nt_repeated_c) }
26
+ let(:sample_prod) { build_prod(nt_sentence, t_a, t_b, t_b, nt_rep_c) }
27
27
 
28
28
  let(:sample_item1) { Parser::DottedItem.new(sample_prod, 1) }
29
29
  let(:sample_item2) { Parser::DottedItem.new(sample_prod, 2) }
@@ -88,7 +88,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
88
88
  it 'should list the entries expecting a given non-terminal' do
89
89
  # Case: an entry expecting a non-terminal
90
90
  subject.push_entry(entry3)
91
- expect(subject.entries4n_term(nt_repeated_c)).to eq([entry3])
91
+ expect(subject.entries4n_term(nt_rep_c)).to eq([entry3])
92
92
  end
93
93
 
94
94
  =begin
@@ -11,7 +11,6 @@ require_relative '../../../lib/rley/parser/parse_entry'
11
11
  module Rley # Open this namespace to avoid module qualifier prefixes
12
12
  module Parser # Open this namespace to avoid module qualifier prefixes
13
13
  describe ParseEntry do
14
-
15
14
  let(:t_a) { Syntax::Terminal.new('A') }
16
15
  let(:t_b) { Syntax::Terminal.new('B') }
17
16
  let(:t_c) { Syntax::Terminal.new('C') }
@@ -25,7 +24,6 @@ module Rley # Open this namespace to avoid module qualifier prefixes
25
24
  Syntax::Production.new(nt_sentence, [])
26
25
  end
27
26
 
28
-
29
27
  let(:dotted_rule) { DottedItem.new(sample_prod, 2) }
30
28
  let(:origin_val) { 3 }
31
29
  let(:vertex_faked) { double('fake-vertex') }
@@ -5,7 +5,7 @@ require_relative '../../../lib/rley/parser/parse_walker_factory'
5
5
 
6
6
  require_relative '../support/grammar_helper'
7
7
  require_relative '../support/expectation_helper'
8
- require_relative '../support/grammar_L0_helper'
8
+ require_relative '../support/grammar_l0_helper'
9
9
 
10
10
  # Load the class under test
11
11
  require_relative '../../../lib/rley/parser/parse_forest_builder'
@@ -23,13 +23,13 @@ module Rley # Open this namespace to avoid module qualifier prefixes
23
23
  # contains a hidden left recursion and a cycle
24
24
  builder = Syntax::GrammarBuilder.new
25
25
  builder.add_terminals('a', 'b')
26
- builder.add_production('Phi' => %'S')
27
- builder.add_production('S' => %w[A T])
28
- builder.add_production('S' => %w[a T])
26
+ builder.add_production('Phi' => 'S')
27
+ builder.add_production('S' => %w(A T))
28
+ builder.add_production('S' => %w(a T))
29
29
  builder.add_production('A' => 'a')
30
- builder.add_production('A' => %w[B A])
30
+ builder.add_production('A' => %w(B A))
31
31
  builder.add_production('B' => [])
32
- builder.add_production('T' => %w( b b b))
32
+ builder.add_production('T' => %w(b b b))
33
33
  builder.grammar
34
34
  end
35
35
 
@@ -53,7 +53,9 @@ module Rley # Open this namespace to avoid module qualifier prefixes
53
53
 
54
54
  # Emit a text representation of the current path.
55
55
  def path_to_s()
56
- text_parts = subject.curr_path.map { |path_element| path_element.to_string(0) }
56
+ text_parts = subject.curr_path.map do |path_element|
57
+ path_element.to_string(0)
58
+ end
57
59
  return text_parts.join('/')
58
60
  end
59
61
 
@@ -70,10 +72,9 @@ module Rley # Open this namespace to avoid module qualifier prefixes
70
72
  it 'should have an empty path' do
71
73
  expect(subject.curr_path).to be_empty
72
74
  end
73
- end
75
+ end # context
74
76
 
75
77
  context 'Parse forest construction' do
76
-
77
78
  it 'should initialize the root node' do
78
79
  first_event = walker.next
79
80
  subject.receive_event(*first_event)
@@ -108,7 +109,8 @@ module Rley # Open this namespace to avoid module qualifier prefixes
108
109
  event4 = walker.next
109
110
  subject.receive_event(*event4)
110
111
 
111
- expect(subject.curr_parent.to_string(0)).to eq('Alt(S => a T .)[0, 4]')
112
+ parent_as_text = subject.curr_parent.to_string(0)
113
+ expect(parent_as_text).to eq('Alt(S => a T .)[0, 4]')
112
114
  expected_path4 = 'Phi[0, 4]/S[0, 4]/Alt(S => a T .)[0, 4]'
113
115
  expect(path_to_s).to eq(expected_path4)
114
116
  expect(subject.curr_path[-2].refinement).to eq(:or)
@@ -136,7 +138,8 @@ module Rley # Open this namespace to avoid module qualifier prefixes
136
138
  expect(path_to_s).to eq(expected_path6)
137
139
  expect(subject.curr_parent.subnodes.size).to eq(1)
138
140
  token_event6 = 'b[3, 4]'
139
- expect(subject.curr_parent.subnodes.first.to_string(0)).to eq(token_event6)
141
+ child = subject.curr_parent.subnodes.first
142
+ expect(child.to_string(0)).to eq(token_event6)
140
143
 
141
144
  event7 = walker.next
142
145
  subject.receive_event(*event7)
@@ -146,7 +149,8 @@ module Rley # Open this namespace to avoid module qualifier prefixes
146
149
  expect(path_to_s).to eq(expected_path7)
147
150
  expect(subject.curr_parent.subnodes.size).to eq(2)
148
151
  token_event7 = 'b[2, 3]'
149
- expect(subject.curr_parent.subnodes.first.to_string(0)).to eq(token_event7)
152
+ child = subject.curr_parent.subnodes.first
153
+ expect(child.to_string(0)).to eq(token_event7)
150
154
 
151
155
  event8 = walker.next
152
156
  subject.receive_event(*event8)
@@ -156,7 +160,8 @@ module Rley # Open this namespace to avoid module qualifier prefixes
156
160
  expect(path_to_s).to eq(expected_path8)
157
161
  expect(subject.curr_parent.subnodes.size).to eq(3)
158
162
  token_event8 = 'b[1, 2]'
159
- expect(subject.curr_parent.subnodes.first.to_string(0)).to eq(token_event8)
163
+ child = subject.curr_parent.subnodes.first
164
+ expect(child.to_string(0)).to eq(token_event8)
160
165
 
161
166
  event9 = walker.next
162
167
  subject.receive_event(*event9)
@@ -168,19 +173,22 @@ module Rley # Open this namespace to avoid module qualifier prefixes
168
173
  event10 = walker.next
169
174
  subject.receive_event(*event10)
170
175
  expect(event10[1].to_s).to eq('.T | 1')
171
- expect(subject.curr_parent.to_string(0)).to eq('Alt(S => a T .)[0, 4]')
176
+ parent_as_text = subject.curr_parent.to_string(0)
177
+ expect(parent_as_text).to eq('Alt(S => a T .)[0, 4]')
172
178
  expected_path10 = 'Phi[0, 4]/S[0, 4]/Alt(S => a T .)[0, 4]'
173
179
  expect(path_to_s).to eq(expected_path10)
174
180
 
175
181
  event11 = walker.next
176
182
  subject.receive_event(*event11)
177
183
  expect(event11[1].to_s).to eq('S => a . T | 0')
178
- expect(subject.curr_parent.to_string(0)).to eq('Alt(S => a T .)[0, 4]')
184
+ parent_as_text = subject.curr_parent.to_string(0)
185
+ expect(parent_as_text).to eq('Alt(S => a T .)[0, 4]')
179
186
  expected_path11 = 'Phi[0, 4]/S[0, 4]/Alt(S => a T .)[0, 4]'
180
187
  expect(path_to_s).to eq(expected_path11)
181
188
  expect(subject.curr_parent.subnodes.size).to eq(2)
182
189
  token_event11 = 'a[0, 1]'
183
- expect(subject.curr_parent.subnodes.first.to_string(0)).to eq(token_event11)
190
+ child = subject.curr_parent.subnodes.first
191
+ expect(child.to_string(0)).to eq(token_event11)
184
192
 
185
193
  event12 = walker.next
186
194
  subject.receive_event(*event12)
@@ -219,7 +227,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
219
227
 
220
228
  event16 = walker.next
221
229
  subject.receive_event(*event16)
222
- expect(event16[0]).to eq(:backtrack) # Backtrack event!
230
+ expect(event16[0]).to eq(:backtrack) # Backtrack event!
223
231
  expect(event16[1].to_s).to eq('S. | 0')
224
232
  expect(subject.curr_parent.to_string(0)).to eq('S[0, 4]')
225
233
  expected_path16 = 'Phi[0, 4]/S[0, 4]'
@@ -229,7 +237,8 @@ module Rley # Open this namespace to avoid module qualifier prefixes
229
237
  event17 = walker.next
230
238
  subject.receive_event(*event17)
231
239
  expect(event17[1].to_s).to eq('S => A T . | 0')
232
- expect(subject.curr_parent.to_string(0)).to eq('Alt(S => A T .)[0, 4]')
240
+ parent_as_text = subject.curr_parent.to_string(0)
241
+ expect(parent_as_text).to eq('Alt(S => A T .)[0, 4]')
233
242
  expected_path17 = 'Phi[0, 4]/S[0, 4]/Alt(S => A T .)[0, 4]'
234
243
  expect(path_to_s).to eq(expected_path17)
235
244
  expect(subject.curr_path[-2].refinement).to eq(:or)
@@ -243,16 +252,18 @@ module Rley # Open this namespace to avoid module qualifier prefixes
243
252
 
244
253
  event18 = walker.next
245
254
  subject.receive_event(*event18)
246
- expect(event18[0]).to eq(:revisit) # Revisit event!
255
+ expect(event18[0]).to eq(:revisit) # Revisit event!
247
256
  expect(event18[1].to_s).to eq('T. | 1')
248
- expect(subject.curr_parent.to_string(0)).to eq('Alt(S => A T .)[0, 4]')
257
+ parent_as_text = subject.curr_parent.to_string(0)
258
+ expect(parent_as_text).to eq('Alt(S => A T .)[0, 4]')
249
259
  expected_path18 = 'Phi[0, 4]/S[0, 4]/Alt(S => A T .)[0, 4]'
250
260
  expect(path_to_s).to eq(expected_path18)
251
261
 
252
262
  event19 = walker.next
253
263
  subject.receive_event(*event19)
254
264
  expect(event19[1].to_s).to eq('S => A . T | 0')
255
- expect(subject.curr_parent.to_string(0)).to eq('Alt(S => A T .)[0, 4]')
265
+ parent_as_text = subject.curr_parent.to_string(0)
266
+ expect(parent_as_text).to eq('Alt(S => A T .)[0, 4]')
256
267
  expected_path19 = 'Phi[0, 4]/S[0, 4]/Alt(S => A T .)[0, 4]'
257
268
  expect(path_to_s).to eq(expected_path19)
258
269
 
@@ -268,8 +279,10 @@ module Rley # Open this namespace to avoid module qualifier prefixes
268
279
  event21 = walker.next
269
280
  subject.receive_event(*event21)
270
281
  expect(event21[1].to_s).to eq('A => a . | 0')
271
- expect(subject.curr_parent.to_string(0)).to eq('Alt(A => a .)[0, 1]')
272
- expected_path21 = 'Phi[0, 4]/S[0, 4]/Alt(S => A T .)[0, 4]/A[0, 1]/Alt(A => a .)[0, 1]'
282
+ parent_as_text = subject.curr_parent.to_string(0)
283
+ expect(parent_as_text).to eq('Alt(A => a .)[0, 1]')
284
+ path_prefix = 'Phi[0, 4]/S[0, 4]/Alt(S => A T .)[0, 4]/A[0, 1]/'
285
+ expected_path21 = path_prefix + 'Alt(A => a .)[0, 1]'
273
286
  expect(path_to_s).to eq(expected_path21)
274
287
  expect(subject.curr_path[-2].refinement).to eq(:or)
275
288
 
@@ -283,7 +296,8 @@ module Rley # Open this namespace to avoid module qualifier prefixes
283
296
  event23 = walker.next
284
297
  subject.receive_event(*event23)
285
298
  expect(event23[1].to_s).to eq('.A | 0')
286
- expect(subject.curr_parent.to_string(0)).to eq('Alt(S => A T .)[0, 4]')
299
+ parent_as_text = subject.curr_parent.to_string(0)
300
+ expect(parent_as_text).to eq('Alt(S => A T .)[0, 4]')
287
301
  expected_path23 = 'Phi[0, 4]/S[0, 4]/Alt(S => A T .)[0, 4]'
288
302
  expect(path_to_s).to eq(expected_path23)
289
303
 
@@ -318,7 +332,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
318
332
 
319
333
  event27 = walker.next
320
334
  subject.receive_event(*event27)
321
- expect(event27[0]).to eq(:backtrack) # Backtrack event!
335
+ expect(event27[0]).to eq(:backtrack) # Backtrack event!
322
336
  expect(event27[1].to_s).to eq('A. | 0')
323
337
  expect(subject.curr_parent.to_string(0)).to eq('A[0, 1]')
324
338
  expected_path27 = 'Phi[0, 4]/S[0, 4]/Alt(S => A T .)[0, 4]/A[0, 1]'
@@ -328,24 +342,28 @@ module Rley # Open this namespace to avoid module qualifier prefixes
328
342
  subject.receive_event(*event28)
329
343
  expect(event28[0]).to eq(:visit)
330
344
  expect(event28[1].to_s).to eq('A => B A . | 0')
331
- expect(subject.curr_parent.to_string(0)).to eq('Alt(A => B A .)[0, 1]')
332
- expected_path28 = 'Phi[0, 4]/S[0, 4]/Alt(S => A T .)[0, 4]/A[0, 1]/Alt(A => B A .)[0, 1]'
345
+ parent_as_text = subject.curr_parent.to_string(0)
346
+ expect(parent_as_text).to eq('Alt(A => B A .)[0, 1]')
347
+ path_prefix = 'Phi[0, 4]/S[0, 4]/Alt(S => A T .)[0, 4]/A[0, 1]/'
348
+ expected_path28 = path_prefix + 'Alt(A => B A .)[0, 1]'
333
349
  expect(path_to_s).to eq(expected_path28)
334
350
 
335
351
  event29 = walker.next
336
352
  subject.receive_event(*event29)
337
- expect(event29[0]).to eq(:revisit) # Revisit event!
353
+ expect(event29[0]).to eq(:revisit) # Revisit event!
338
354
  expect(event29[1].to_s).to eq('A. | 0')
339
- expect(subject.curr_parent.to_string(0)).to eq('Alt(A => B A .)[0, 1]')
340
- expected_path29 = 'Phi[0, 4]/S[0, 4]/Alt(S => A T .)[0, 4]/A[0, 1]/Alt(A => B A .)[0, 1]'
355
+ parent_as_text = subject.curr_parent.to_string(0)
356
+ expect(parent_as_text).to eq('Alt(A => B A .)[0, 1]')
357
+ expected_path29 = path_prefix + 'Alt(A => B A .)[0, 1]'
341
358
  expect(path_to_s).to eq(expected_path29)
342
359
 
343
360
  event30 = walker.next
344
361
  subject.receive_event(*event30)
345
362
  expect(event30[0]).to eq(:visit)
346
363
  expect(event30[1].to_s).to eq('A => B . A | 0')
347
- expect(subject.curr_parent.to_string(0)).to eq('Alt(A => B A .)[0, 1]')
348
- expected_path30 = 'Phi[0, 4]/S[0, 4]/Alt(S => A T .)[0, 4]/A[0, 1]/Alt(A => B A .)[0, 1]'
364
+ parent_as_text = subject.curr_parent.to_string(0)
365
+ expect(parent_as_text).to eq('Alt(A => B A .)[0, 1]')
366
+ expected_path30 = path_prefix + 'Alt(A => B A .)[0, 1]'
349
367
  expect(path_to_s).to eq(expected_path30)
350
368
 
351
369
  event31 = walker.next
@@ -353,7 +371,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
353
371
  expect(event31[0]).to eq(:visit)
354
372
  expect(event31[1].to_s).to eq('B. | 0')
355
373
  expect(subject.curr_parent.to_string(0)).to eq('B[0, 0]')
356
- expected_path31 = 'Phi[0, 4]/S[0, 4]/Alt(S => A T .)[0, 4]/A[0, 1]/Alt(A => B A .)[0, 1]/B[0, 0]'
374
+ expected_path31 = path_prefix + 'Alt(A => B A .)[0, 1]/B[0, 0]'
357
375
  expect(path_to_s).to eq(expected_path31)
358
376
 
359
377
  event32 = walker.next
@@ -362,15 +380,16 @@ module Rley # Open this namespace to avoid module qualifier prefixes
362
380
  # Empty production!
363
381
  expect(event32[1].to_s).to eq('B => . | 0')
364
382
  expect(subject.curr_parent.to_string(0)).to eq('B[0, 0]')
365
- expected_path30 = 'Phi[0, 4]/S[0, 4]/Alt(S => A T .)[0, 4]/A[0, 1]/Alt(A => B A .)[0, 1]/B[0, 0]'
383
+ expected_path30 = path_prefix + 'Alt(A => B A .)[0, 1]/B[0, 0]'
366
384
  expect(path_to_s).to eq(expected_path30)
367
385
 
368
386
  event33 = walker.next
369
387
  subject.receive_event(*event33)
370
388
  expect(event33[0]).to eq(:visit)
371
389
  expect(event33[1].to_s).to eq('.B | 0')
372
- expect(subject.curr_parent.to_string(0)).to eq('Alt(A => B A .)[0, 1]')
373
- expected_path33 = 'Phi[0, 4]/S[0, 4]/Alt(S => A T .)[0, 4]/A[0, 1]/Alt(A => B A .)[0, 1]'
390
+ parent_as_text = subject.curr_parent.to_string(0)
391
+ expect(parent_as_text).to eq('Alt(A => B A .)[0, 1]')
392
+ expected_path33 = path_prefix + 'Alt(A => B A .)[0, 1]'
374
393
  expect(path_to_s).to eq(expected_path33)
375
394
 
376
395
  event34 = walker.next
@@ -378,14 +397,15 @@ module Rley # Open this namespace to avoid module qualifier prefixes
378
397
  expect(event34[0]).to eq(:visit)
379
398
  expect(event34[1].to_s).to eq('A => . B A | 0')
380
399
  expect(subject.curr_parent.to_string(0)).to eq('A[0, 1]')
381
- expected_path34 = 'Phi[0, 4]/S[0, 4]/Alt(S => A T .)[0, 4]/A[0, 1]'
382
- expect(path_to_s).to eq(expected_path34)
400
+ path34 = 'Phi[0, 4]/S[0, 4]/Alt(S => A T .)[0, 4]/A[0, 1]'
401
+ expect(path_to_s).to eq(path34)
383
402
 
384
403
  event35 = walker.next
385
404
  subject.receive_event(*event35)
386
405
  expect(event35[0]).to eq(:revisit)
387
406
  expect(event35[1].to_s).to eq('.A | 0')
388
- expect(subject.curr_parent.to_string(0)).to eq('Alt(S => A T .)[0, 4]')
407
+ parent_as_text = subject.curr_parent.to_string(0)
408
+ expect(parent_as_text).to eq('Alt(S => A T .)[0, 4]')
389
409
  expected_path35 = 'Phi[0, 4]/S[0, 4]/Alt(S => A T .)[0, 4]'
390
410
  expect(path_to_s).to eq(expected_path35)
391
411
 
@@ -410,18 +430,18 @@ module Rley # Open this namespace to avoid module qualifier prefixes
410
430
  context 'Natural language processing' do
411
431
  include GrammarL0Helper
412
432
 
413
- let(:grammar_L0) do
414
- builder = grammar_L0_builder
433
+ let(:grammar_l0) do
434
+ builder = grammar_l0_builder
415
435
  builder.grammar
416
436
  end
417
437
 
418
438
  let(:sentence_tokens) do
419
439
  sentence = 'I prefer a morning flight'
420
- tokenizer_L0(sentence, grammar_L0)
440
+ tokenizer_l0(sentence, grammar_l0)
421
441
  end
422
442
 
423
443
  let(:sentence_result) do
424
- parser = Parser::GFGEarleyParser.new(grammar_L0)
444
+ parser = Parser::GFGEarleyParser.new(grammar_l0)
425
445
  parser.parse(sentence_tokens)
426
446
  end
427
447
 
@@ -500,7 +520,8 @@ module Rley # Open this namespace to avoid module qualifier prefixes
500
520
  expect(path_to_s).to eq(expected_path8)
501
521
  expect(subject.curr_parent.subnodes.size).to eq(1)
502
522
  token_event8 = 'Noun[4, 5]'
503
- expect(subject.curr_parent.subnodes.first.to_string(0)).to eq(token_event8)
523
+ child = subject.curr_parent.subnodes.first
524
+ expect(child.to_string(0)).to eq(token_event8)
504
525
 
505
526
  event9 = walker.next
506
527
  subject.receive_event(*event9)
@@ -515,27 +536,28 @@ module Rley # Open this namespace to avoid module qualifier prefixes
515
536
  expect(event10[0]).to eq(:visit)
516
537
  expect(event10[1].to_s).to eq('Nominal. | 3')
517
538
  expect(subject.curr_parent.to_string(0)).to eq('Nominal[3, 4]')
518
- expected_path10 = 'S[0, 5]/VP[1, 5]/NP[2, 5]/Nominal[3, 5]/Nominal[3, 4]'
519
- expect(path_to_s).to eq(expected_path10)
539
+ path10 = 'S[0, 5]/VP[1, 5]/NP[2, 5]/Nominal[3, 5]/Nominal[3, 4]'
540
+ expect(path_to_s).to eq(path10)
520
541
 
521
542
  event11 = walker.next
522
543
  subject.receive_event(*event11)
523
544
  expect(event11[0]).to eq(:visit)
524
545
  expect(event11[1].to_s).to eq('Nominal => Noun . | 3')
525
546
  expect(subject.curr_parent.to_string(0)).to eq('Nominal[3, 4]')
526
- expected_path11 = 'S[0, 5]/VP[1, 5]/NP[2, 5]/Nominal[3, 5]/Nominal[3, 4]'
527
- expect(path_to_s).to eq(expected_path11)
547
+ path11 = 'S[0, 5]/VP[1, 5]/NP[2, 5]/Nominal[3, 5]/Nominal[3, 4]'
548
+ expect(path_to_s).to eq(path11)
528
549
  expect(subject.curr_parent.subnodes.size).to eq(1)
529
550
  token_event11 = 'Noun[3, 4]'
530
- expect(subject.curr_parent.subnodes.first.to_string(0)).to eq(token_event11)
551
+ child = subject.curr_parent.subnodes.first
552
+ expect(child.to_string(0)).to eq(token_event11)
531
553
 
532
554
  event12 = walker.next
533
555
  subject.receive_event(*event12)
534
556
  expect(event12[0]).to eq(:visit)
535
557
  expect(event12[1].to_s).to eq('Nominal => . Noun | 3')
536
558
  expect(subject.curr_parent.to_string(0)).to eq('Nominal[3, 4]')
537
- expected_path12 = 'S[0, 5]/VP[1, 5]/NP[2, 5]/Nominal[3, 5]/Nominal[3, 4]'
538
- expect(path_to_s).to eq(expected_path12)
559
+ path12 = 'S[0, 5]/VP[1, 5]/NP[2, 5]/Nominal[3, 5]/Nominal[3, 4]'
560
+ expect(path_to_s).to eq(path12)
539
561
 
540
562
  event13 = walker.next
541
563
  subject.receive_event(*event13)
@@ -569,7 +591,8 @@ module Rley # Open this namespace to avoid module qualifier prefixes
569
591
  expected_path16 = 'S[0, 5]/VP[1, 5]/NP[2, 5]'
570
592
  expect(path_to_s).to eq(expected_path16)
571
593
  token_event16 = 'Determiner[2, 3]'
572
- expect(subject.curr_parent.subnodes.first.to_string(0)).to eq(token_event16)
594
+ child = subject.curr_parent.subnodes.first
595
+ expect(child.to_string(0)).to eq(token_event16)
573
596
 
574
597
  event17 = walker.next
575
598
  subject.receive_event(*event17)
@@ -595,7 +618,8 @@ module Rley # Open this namespace to avoid module qualifier prefixes
595
618
  expected_path19 = 'S[0, 5]/VP[1, 5]'
596
619
  expect(path_to_s).to eq(expected_path19)
597
620
  token_event19 = 'Verb[1, 2]'
598
- expect(subject.curr_parent.subnodes.first.to_string(0)).to eq(token_event19)
621
+ child = subject.curr_parent.subnodes.first
622
+ expect(child.to_string(0)).to eq(token_event19)
599
623
 
600
624
  event20 = walker.next
601
625
  subject.receive_event(*event20)
@@ -637,8 +661,9 @@ module Rley # Open this namespace to avoid module qualifier prefixes
637
661
  expected_path24 = 'S[0, 5]/NP[0, 1]'
638
662
  expect(path_to_s).to eq(expected_path24)
639
663
  token_event24 = 'Pronoun[0, 1]'
640
- expect(subject.curr_parent.subnodes.first.to_string(0)).to eq(token_event24)
641
-
664
+ child = subject.curr_parent.subnodes.first
665
+ expect(child.to_string(0)).to eq(token_event24)
666
+
642
667
  event25 = walker.next
643
668
  subject.receive_event(*event25)
644
669
  expect(event25[0]).to eq(:visit)
@@ -668,10 +693,10 @@ module Rley # Open this namespace to avoid module qualifier prefixes
668
693
  expect(event28[0]).to eq(:visit)
669
694
  expect(event28[1].to_s).to eq('.S | 0')
670
695
  expected_path28 = ''
671
- expect(path_to_s).to eq(expected_path28)
696
+ expect(path_to_s).to eq(expected_path28)
672
697
  end
673
698
  end # context
674
699
  end # describe
675
700
  end # module
676
701
  end # module
677
- # End of file
702
+ # End of file