rley 0.3.04 → 0.3.05

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