rley 0.7.03 → 0.7.08

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 (174) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +362 -62
  3. data/.travis.yml +6 -7
  4. data/CHANGELOG.md +20 -1
  5. data/LICENSE.txt +1 -1
  6. data/README.md +6 -7
  7. data/Rakefile +2 -0
  8. data/appveyor.yml +2 -4
  9. data/examples/NLP/benchmark_pico_en.rb +2 -0
  10. data/examples/NLP/engtagger.rb +193 -188
  11. data/examples/NLP/nano_eng/nano_en_demo.rb +2 -0
  12. data/examples/NLP/nano_eng/nano_grammar.rb +7 -5
  13. data/examples/NLP/pico_en_demo.rb +2 -0
  14. data/examples/data_formats/JSON/cli_options.rb +3 -1
  15. data/examples/data_formats/JSON/json_ast_builder.rb +14 -9
  16. data/examples/data_formats/JSON/json_ast_nodes.rb +14 -21
  17. data/examples/data_formats/JSON/json_demo.rb +2 -0
  18. data/examples/data_formats/JSON/json_grammar.rb +4 -2
  19. data/examples/data_formats/JSON/json_lexer.rb +10 -8
  20. data/examples/data_formats/JSON/json_minifier.rb +3 -1
  21. data/examples/general/calc_iter1/calc_ast_builder.rb +15 -10
  22. data/examples/general/calc_iter1/calc_ast_nodes.rb +25 -37
  23. data/examples/general/calc_iter1/calc_demo.rb +2 -0
  24. data/examples/general/calc_iter1/calc_grammar.rb +4 -2
  25. data/examples/general/calc_iter1/calc_lexer.rb +8 -4
  26. data/examples/general/calc_iter1/spec/calculator_spec.rb +7 -5
  27. data/examples/general/calc_iter2/calc_ast_builder.rb +7 -3
  28. data/examples/general/calc_iter2/calc_ast_nodes.rb +29 -43
  29. data/examples/general/calc_iter2/calc_demo.rb +2 -0
  30. data/examples/general/calc_iter2/calc_grammar.rb +5 -3
  31. data/examples/general/calc_iter2/calc_lexer.rb +13 -10
  32. data/examples/general/calc_iter2/spec/calculator_spec.rb +28 -26
  33. data/examples/general/left.rb +4 -2
  34. data/examples/general/right.rb +4 -2
  35. data/lib/rley.rb +2 -0
  36. data/lib/rley/base/base_parser.rb +2 -0
  37. data/lib/rley/base/dotted_item.rb +38 -41
  38. data/lib/rley/base/grm_items_builder.rb +2 -0
  39. data/lib/rley/constants.rb +5 -3
  40. data/lib/rley/engine.rb +22 -24
  41. data/lib/rley/formatter/asciitree.rb +6 -4
  42. data/lib/rley/formatter/base_formatter.rb +2 -0
  43. data/lib/rley/formatter/bracket_notation.rb +3 -8
  44. data/lib/rley/formatter/debug.rb +8 -6
  45. data/lib/rley/formatter/json.rb +4 -2
  46. data/lib/rley/gfg/call_edge.rb +3 -1
  47. data/lib/rley/gfg/edge.rb +7 -5
  48. data/lib/rley/gfg/end_vertex.rb +4 -6
  49. data/lib/rley/gfg/epsilon_edge.rb +3 -5
  50. data/lib/rley/gfg/grm_flow_graph.rb +31 -25
  51. data/lib/rley/gfg/item_vertex.rb +12 -22
  52. data/lib/rley/gfg/non_terminal_vertex.rb +6 -4
  53. data/lib/rley/gfg/return_edge.rb +2 -0
  54. data/lib/rley/gfg/scan_edge.rb +3 -1
  55. data/lib/rley/gfg/shortcut_edge.rb +4 -2
  56. data/lib/rley/gfg/start_vertex.rb +6 -8
  57. data/lib/rley/gfg/vertex.rb +47 -41
  58. data/lib/rley/lexical/token.rb +3 -1
  59. data/lib/rley/lexical/token_range.rb +8 -6
  60. data/lib/rley/parse_forest_visitor.rb +7 -5
  61. data/lib/rley/parse_rep/ast_base_builder.rb +11 -11
  62. data/lib/rley/parse_rep/cst_builder.rb +7 -4
  63. data/lib/rley/parse_rep/parse_forest_builder.rb +36 -25
  64. data/lib/rley/parse_rep/parse_forest_factory.rb +5 -3
  65. data/lib/rley/parse_rep/parse_rep_creator.rb +18 -13
  66. data/lib/rley/parse_rep/parse_tree_builder.rb +15 -15
  67. data/lib/rley/parse_rep/parse_tree_factory.rb +27 -25
  68. data/lib/rley/parse_tree_visitor.rb +3 -1
  69. data/lib/rley/parser/error_reason.rb +9 -8
  70. data/lib/rley/parser/gfg_chart.rb +54 -22
  71. data/lib/rley/parser/gfg_earley_parser.rb +3 -1
  72. data/lib/rley/parser/gfg_parsing.rb +51 -31
  73. data/lib/rley/parser/parse_entry.rb +29 -33
  74. data/lib/rley/parser/parse_entry_set.rb +32 -27
  75. data/lib/rley/parser/parse_entry_tracker.rb +6 -4
  76. data/lib/rley/parser/parse_state.rb +18 -21
  77. data/lib/rley/parser/parse_state_tracker.rb +6 -4
  78. data/lib/rley/parser/parse_tracer.rb +15 -13
  79. data/lib/rley/parser/parse_walker_factory.rb +28 -29
  80. data/lib/rley/parser/state_set.rb +11 -10
  81. data/lib/rley/ptree/non_terminal_node.rb +10 -6
  82. data/lib/rley/ptree/parse_tree.rb +6 -4
  83. data/lib/rley/ptree/parse_tree_node.rb +7 -5
  84. data/lib/rley/ptree/terminal_node.rb +9 -7
  85. data/lib/rley/rley_error.rb +12 -10
  86. data/lib/rley/sppf/alternative_node.rb +8 -6
  87. data/lib/rley/sppf/composite_node.rb +9 -7
  88. data/lib/rley/sppf/epsilon_node.rb +5 -3
  89. data/lib/rley/sppf/leaf_node.rb +5 -3
  90. data/lib/rley/sppf/non_terminal_node.rb +2 -0
  91. data/lib/rley/sppf/parse_forest.rb +19 -17
  92. data/lib/rley/sppf/sppf_node.rb +9 -8
  93. data/lib/rley/sppf/token_node.rb +5 -3
  94. data/lib/rley/syntax/grammar.rb +7 -5
  95. data/lib/rley/syntax/grammar_builder.rb +11 -9
  96. data/lib/rley/syntax/grm_symbol.rb +8 -6
  97. data/lib/rley/syntax/literal.rb +2 -0
  98. data/lib/rley/syntax/non_terminal.rb +11 -15
  99. data/lib/rley/syntax/production.rb +13 -11
  100. data/lib/rley/syntax/symbol_seq.rb +10 -10
  101. data/lib/rley/syntax/terminal.rb +6 -5
  102. data/lib/rley/syntax/verbatim_symbol.rb +5 -3
  103. data/lib/support/base_tokenizer.rb +23 -20
  104. data/spec/rley/base/dotted_item_spec.rb +4 -2
  105. data/spec/rley/base/grm_items_builder_spec.rb +2 -0
  106. data/spec/rley/engine_spec.rb +47 -9
  107. data/spec/rley/formatter/asciitree_spec.rb +11 -9
  108. data/spec/rley/formatter/bracket_notation_spec.rb +16 -14
  109. data/spec/rley/formatter/debug_spec.rb +4 -2
  110. data/spec/rley/formatter/json_spec.rb +5 -3
  111. data/spec/rley/gfg/call_edge_spec.rb +2 -0
  112. data/spec/rley/gfg/edge_spec.rb +2 -0
  113. data/spec/rley/gfg/end_vertex_spec.rb +7 -5
  114. data/spec/rley/gfg/epsilon_edge_spec.rb +2 -0
  115. data/spec/rley/gfg/grm_flow_graph_spec.rb +2 -0
  116. data/spec/rley/gfg/item_vertex_spec.rb +12 -10
  117. data/spec/rley/gfg/non_terminal_vertex_spec.rb +5 -3
  118. data/spec/rley/gfg/return_edge_spec.rb +2 -0
  119. data/spec/rley/gfg/scan_edge_spec.rb +2 -0
  120. data/spec/rley/gfg/shortcut_edge_spec.rb +3 -1
  121. data/spec/rley/gfg/start_vertex_spec.rb +7 -5
  122. data/spec/rley/gfg/vertex_spec.rb +5 -3
  123. data/spec/rley/lexical/token_range_spec.rb +18 -16
  124. data/spec/rley/lexical/token_spec.rb +4 -2
  125. data/spec/rley/parse_forest_visitor_spec.rb +167 -163
  126. data/spec/rley/parse_rep/ambiguous_parse_spec.rb +46 -44
  127. data/spec/rley/parse_rep/ast_builder_spec.rb +8 -6
  128. data/spec/rley/parse_rep/cst_builder_spec.rb +7 -5
  129. data/spec/rley/parse_rep/groucho_spec.rb +25 -25
  130. data/spec/rley/parse_rep/parse_forest_builder_spec.rb +28 -26
  131. data/spec/rley/parse_rep/parse_forest_factory_spec.rb +8 -6
  132. data/spec/rley/parse_rep/parse_tree_factory_spec.rb +4 -2
  133. data/spec/rley/parse_tree_visitor_spec.rb +12 -8
  134. data/spec/rley/parser/error_reason_spec.rb +8 -6
  135. data/spec/rley/parser/gfg_chart_spec.rb +17 -4
  136. data/spec/rley/parser/gfg_earley_parser_spec.rb +16 -11
  137. data/spec/rley/parser/gfg_parsing_spec.rb +41 -252
  138. data/spec/rley/parser/parse_entry_set_spec.rb +2 -0
  139. data/spec/rley/parser/parse_entry_spec.rb +21 -19
  140. data/spec/rley/parser/parse_state_spec.rb +7 -5
  141. data/spec/rley/parser/parse_tracer_spec.rb +16 -14
  142. data/spec/rley/parser/parse_walker_factory_spec.rb +10 -8
  143. data/spec/rley/parser/state_set_spec.rb +24 -22
  144. data/spec/rley/ptree/non_terminal_node_spec.rb +7 -3
  145. data/spec/rley/ptree/parse_tree_node_spec.rb +6 -4
  146. data/spec/rley/ptree/parse_tree_spec.rb +2 -0
  147. data/spec/rley/ptree/terminal_node_spec.rb +8 -6
  148. data/spec/rley/sppf/alternative_node_spec.rb +8 -6
  149. data/spec/rley/sppf/non_terminal_node_spec.rb +5 -3
  150. data/spec/rley/sppf/token_node_spec.rb +6 -4
  151. data/spec/rley/support/ambiguous_grammar_helper.rb +5 -4
  152. data/spec/rley/support/expectation_helper.rb +2 -0
  153. data/spec/rley/support/grammar_abc_helper.rb +4 -4
  154. data/spec/rley/support/grammar_ambig01_helper.rb +6 -5
  155. data/spec/rley/support/grammar_arr_int_helper.rb +6 -5
  156. data/spec/rley/support/grammar_b_expr_helper.rb +6 -5
  157. data/spec/rley/support/grammar_helper.rb +2 -0
  158. data/spec/rley/support/grammar_l0_helper.rb +15 -16
  159. data/spec/rley/support/grammar_pb_helper.rb +8 -5
  160. data/spec/rley/support/grammar_sppf_helper.rb +3 -1
  161. data/spec/rley/syntax/grammar_builder_spec.rb +7 -5
  162. data/spec/rley/syntax/grammar_spec.rb +8 -6
  163. data/spec/rley/syntax/grm_symbol_spec.rb +3 -1
  164. data/spec/rley/syntax/literal_spec.rb +2 -0
  165. data/spec/rley/syntax/non_terminal_spec.rb +10 -8
  166. data/spec/rley/syntax/production_spec.rb +15 -13
  167. data/spec/rley/syntax/symbol_seq_spec.rb +4 -2
  168. data/spec/rley/syntax/terminal_spec.rb +7 -5
  169. data/spec/rley/syntax/verbatim_symbol_spec.rb +3 -1
  170. data/spec/spec_helper.rb +2 -12
  171. data/spec/support/base_tokenizer_spec.rb +9 -2
  172. metadata +21 -63
  173. data/.simplecov +0 -7
  174. data/Gemfile +0 -8
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../../spec_helper'
2
4
 
3
5
  require_relative '../../../lib/rley/parser/gfg_earley_parser'
@@ -23,12 +25,12 @@ module Rley # Open this namespace to avoid module qualifier prefixes
23
25
  builder = Syntax::GrammarBuilder.new do
24
26
  add_terminals('a', 'b')
25
27
  rule 'Phi' => 'S'
26
- rule 'S' => %w[A T]
27
- rule 'S' => %w[a T]
28
+ rule 'S' => 'A T'
29
+ rule 'S' => 'a T'
28
30
  rule 'A' => 'a'
29
- rule 'A' => %w[B A]
31
+ rule 'A' => 'B A'
30
32
  rule 'B' => []
31
- rule 'T' => %w[b b b]
33
+ rule 'T' => 'b b b'
32
34
  end
33
35
  builder.grammar
34
36
  end
@@ -47,11 +49,11 @@ module Rley # Open this namespace to avoid module qualifier prefixes
47
49
  end
48
50
 
49
51
  # Emit a text representation of the current path.
50
- def path_to_s()
52
+ def path_to_s
51
53
  text_parts = subject.curr_path.map do |path_element|
52
54
  path_element.to_string(0)
53
55
  end
54
- return text_parts.join('/')
56
+ text_parts.join('/')
55
57
  end
56
58
 
57
59
  context 'Initialization:' do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../../spec_helper'
2
4
 
3
5
  require_relative '../../../lib/rley/parser/gfg_earley_parser'
@@ -36,11 +38,11 @@ module Rley # Open this namespace to avoid module qualifier prefixes
36
38
  end
37
39
 
38
40
  # Emit a text representation of the current path.
39
- def path_to_s()
41
+ def path_to_s
40
42
  text_parts = subject.curr_path.map do |path_element|
41
43
  path_element.to_string(0)
42
44
  end
43
- return text_parts.join('/')
45
+ text_parts.join('/')
44
46
  end
45
47
 
46
48
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../spec_helper'
2
4
 
3
5
  require_relative '../../lib/rley/lexical/token'
@@ -9,7 +11,7 @@ require_relative './support/grammar_sppf_helper'
9
11
  require_relative '../../lib/rley/parse_tree_visitor'
10
12
 
11
13
  module Rley # Open this namespace to avoid module qualifier prefixes
12
- describe ParseTreeVisitor do
14
+ describe ParseTreeVisitor do
13
15
  let(:grammar_abc) do
14
16
  sandbox = Object.new
15
17
  sandbox.extend(GrammarABCHelper)
@@ -43,7 +45,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
43
45
  # Capital letters represent non-terminal nodes
44
46
  let(:grm_abc_ptree1) do
45
47
  engine = Rley::Engine.new
46
- engine.use_grammar(grammar_abc)
48
+ engine.use_grammar(grammar_abc)
47
49
  parse_result = engine.parse(grm_abc_tokens1)
48
50
  ptree = engine.convert(parse_result)
49
51
  ptree
@@ -159,6 +161,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
159
161
  subject.end_visit_ptree(grm_abc_ptree1)
160
162
  end
161
163
 
164
+ # rubocop: disable Naming/VariableNumber
162
165
  it 'should begin the visit when requested' do
163
166
  # Reminder: parse tree structure is
164
167
  # S[0,5]
@@ -207,11 +210,11 @@ module Rley # Open this namespace to avoid module qualifier prefixes
207
210
  expectations.each do |(msg, args)|
208
211
  expect(listener1).to receive(msg).with(*args).ordered
209
212
  end
210
-
213
+
211
214
  # Here we go...
212
215
  subject.start
213
216
  end
214
-
217
+
215
218
  it 'should also visit in pre-order' do
216
219
  # Reminder: parse tree structure is
217
220
  # S[0,5]
@@ -226,7 +229,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
226
229
  root = grm_abc_ptree1.root
227
230
  # Here we defeat encapsulation for the good cause
228
231
  subject.instance_variable_set(:@traversal, :pre_order)
229
-
232
+
230
233
  children = root.subnodes
231
234
  big_a_1 = children[0]
232
235
  big_a_1_children = big_a_1.subnodes
@@ -237,7 +240,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
237
240
  expectations = [
238
241
  [:before_ptree, [grm_abc_ptree1]]
239
242
  # TODO: fix this test
240
- # [:before_subnodes, [root, children]],
243
+ # [:before_subnodes, [root, children]],
241
244
  # [:before_non_terminal, [root]],
242
245
 
243
246
  # [:before_non_terminal, [big_a_1]],
@@ -265,10 +268,11 @@ module Rley # Open this namespace to avoid module qualifier prefixes
265
268
  expectations.each do |(msg, args)|
266
269
  expect(listener1).to receive(msg).with(*args).ordered
267
270
  end
268
-
271
+
269
272
  # Here we go...
270
273
  subject.start
271
- end
274
+ end
275
+ # rubocop: enable Naming/VariableNumber
272
276
  end # context
273
277
  end # describe
274
278
  end # module
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../../spec_helper'
2
4
  require_relative '../../../lib/rley/lexical/token'
3
5
 
@@ -44,8 +46,8 @@ module Rley # Open this namespace to avoid module qualifier prefixes
44
46
 
45
47
  context 'Initialization:' do
46
48
  it 'should be created with arguments' do
47
- expect do
48
- ExpectationNotMet.new(3, err_token, terminals)
49
+ expect do
50
+ ExpectationNotMet.new(3, err_token, terminals)
49
51
  end.not_to raise_error
50
52
  end
51
53
 
@@ -73,8 +75,8 @@ module Rley # Open this namespace to avoid module qualifier prefixes
73
75
 
74
76
  context 'Initialization:' do
75
77
  it 'should be created with arguments' do
76
- expect do
77
- UnexpectedToken.new(3, err_token, terminals)
78
+ expect do
79
+ UnexpectedToken.new(3, err_token, terminals)
78
80
  end.not_to raise_error
79
81
  end
80
82
  end # context
@@ -105,8 +107,8 @@ MESSAGE_END
105
107
 
106
108
  context 'Initialization:' do
107
109
  it 'should be created with arguments' do
108
- expect do
109
- PrematureInputEnd.new(3, err_token, terminals)
110
+ expect do
111
+ PrematureInputEnd.new(3, err_token, terminals)
110
112
  end.not_to raise_error
111
113
  end
112
114
  end # context
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../../spec_helper'
2
4
  require 'stringio'
3
5
 
@@ -75,13 +77,13 @@ module Rley # Open this namespace to avoid module qualifier prefixes
75
77
 
76
78
  context 'Provided services:' do
77
79
  it 'should accept the pushing of a parse entry in existing set' do
78
- expect(subject.sets[0].entries.size).to eq(1)
80
+ expect(subject.sets[0].entries.size).to eq(1)
79
81
  subject.push_entry(second_vertex, 0, 0, :scan_rule)
80
82
  expect(subject.sets[0].entries.size).to eq(2)
81
83
  end
82
-
84
+
83
85
  it 'should accept the pushing of a parse entry in new set' do
84
- expect(subject.sets[0].entries.size).to eq(1)
86
+ expect(subject.sets[0].entries.size).to eq(1)
85
87
  subject.push_entry(second_vertex, 0, 1, :scan_rule)
86
88
  expect(subject.sets[0].entries.size).to eq(1)
87
89
  expect(subject.sets.size).to eq(2)
@@ -90,7 +92,18 @@ module Rley # Open this namespace to avoid module qualifier prefixes
90
92
 
91
93
  it 'should retrieve an existing set at given position' do
92
94
  expect(subject[0]).to eq(subject.sets[0])
93
- end
95
+ end
96
+
97
+ it 'should a user-friendly text representation of itself' do
98
+ subject.push_entry(second_vertex, 0, 1, :scan_rule)
99
+ representation = <<REPR
100
+ State[0]
101
+ .S | 0
102
+ State[1]
103
+ S => . A | 0
104
+ REPR
105
+ expect(subject.to_s).to eq(representation)
106
+ end
94
107
  end # context
95
108
  end # describe
96
109
  end # module
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../../spec_helper'
2
4
  require 'stringio'
3
5
  require_relative '../../../lib/rley/syntax/verbatim_symbol'
@@ -53,7 +55,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
53
55
  let(:plus) { Syntax::VerbatimSymbol.new('+') }
54
56
  let(:star) { Syntax::VerbatimSymbol.new('*') }
55
57
  let(:integer) do
56
- integer_pattern = /[-+]?[0-9]+/ # Decimal notation
58
+ integer_pattern = /[-+]?[0-9]+/ # Decimal notation
57
59
  Syntax::Literal.new('integer', integer_pattern)
58
60
  end
59
61
  let(:prod_P) { Syntax::Production.new(nt_P, [nt_S]) }
@@ -69,7 +71,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
69
71
 
70
72
  # Helper method that mimicks the output of a tokenizer
71
73
  # for the language specified by grammar_expr
72
- def grm2_tokens()
74
+ def grm2_tokens
73
75
  input_sequence = [
74
76
  { '2' => 'integer' },
75
77
  '+',
@@ -77,7 +79,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
77
79
  '*',
78
80
  { '4' => 'integer' }
79
81
  ]
80
- return build_token_sequence(input_sequence, grammar_expr)
82
+ build_token_sequence(input_sequence, grammar_expr)
81
83
  end
82
84
 
83
85
  # Default instantiation rule
@@ -102,6 +104,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
102
104
  end # context
103
105
 
104
106
  context 'Parsing: ' do
107
+ # rubocop: disable Naming/VariableNumber
105
108
  it 'should parse a valid simple input' do
106
109
  parse_result = subject.parse(grm1_tokens)
107
110
  expect(parse_result.success?).to eq(true)
@@ -149,7 +152,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
149
152
  expected = [
150
153
  'A => b . | 2', # scan 'b'
151
154
  'A. | 2', # exit rule
152
- 'A => a A . c | 1', # end rule
155
+ 'A => a A . c | 1' # end rule
153
156
  ]
154
157
  entry_set_3 = parse_result.chart[3]
155
158
  expect(entry_set_3.entries.size).to eq(3)
@@ -181,6 +184,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
181
184
  expect(entry_set_5.entries.size).to eq(4)
182
185
  compare_entry_texts(entry_set_5, expected)
183
186
  end
187
+ # rubocop: enable Naming/VariableNumber
184
188
 
185
189
  it 'should parse a valid simple expression' do
186
190
  instance = GFGEarleyParser.new(grammar_expr)
@@ -284,10 +288,11 @@ module Rley # Open this namespace to avoid module qualifier prefixes
284
288
  # A => ;
285
289
  t_x = Syntax::VerbatimSymbol.new('x')
286
290
 
287
- builder = Syntax::GrammarBuilder.new
288
- builder.add_terminals(t_x)
289
- builder.add_production('Ss' => %w[A A x])
290
- builder.add_production('A' => [])
291
+ builder = Syntax::GrammarBuilder.new do
292
+ add_terminals(t_x)
293
+ rule 'Ss' => 'A A x'
294
+ rule 'A' => []
295
+ end
291
296
  pos = Lexical::Position.new(1, 1)
292
297
  tokens = [Lexical::Token.new('x', t_x, pos)]
293
298
 
@@ -406,7 +411,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
406
411
  'P => S . | 0', # end rule
407
412
  "S => S . '+' S | 0", # end rule
408
413
  "S => S . '*' S | 0", # end rule
409
- 'P. | 0', # exit rule
414
+ 'P. | 0' # exit rule
410
415
  ]
411
416
  compare_entry_texts(parse_result.chart[3], expected)
412
417
 
@@ -549,7 +554,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
549
554
  'E => E . + E | 2', # end rule
550
555
  'S => E . | 0', # end rule
551
556
  'E => E . + E | 0', # end rule
552
- 'S. | 0', # exit rule
557
+ 'S. | 0' # exit rule
553
558
  ]
554
559
  compare_entry_texts(parse_result.chart[5], expected)
555
560
  end
@@ -618,7 +623,7 @@ MSG
618
623
  ]
619
624
  compare_entry_texts(parse_result.chart[2], expected)
620
625
 
621
- err_msg = "Premature end of input after '+' at position line 1, "
626
+ err_msg = +"Premature end of input after '+' at position line 1, "
622
627
  err_msg << 'column 3'
623
628
  err_msg << "\nExpected one of: ['int', '(']."
624
629
  expect(parse_result.failure_reason.message).to eq(err_msg)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../../spec_helper'
2
4
  require 'stringio'
3
5
 
@@ -25,7 +27,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
25
27
  include GrammarABCHelper # Mix-in module with builder for grammar abc
26
28
  include GrammarBExprHelper # Mix-in with builder for simple expressions
27
29
  include GrammarHelper # Mix-in with method for creating token sequence
28
-
30
+
29
31
  # Helper method. Create an array of dotted items
30
32
  # from the given grammar
31
33
  def build_items_for_grammar(aGrammar)
@@ -93,14 +95,14 @@ SNIPPET
93
95
 
94
96
  context 'Parsing:' do
95
97
  # Utility method to fill the first entry set...
96
- def fill_first_set()
98
+ def fill_first_set
97
99
  subject.start_rule(subject.initial_entry, 0)
98
100
  subject.call_rule(subject.chart[0].last, 0)
99
101
  subject.start_rule(subject.chart[0].last, 0)
100
102
  end
101
103
 
102
104
  # Utility method to initialize the second entry set...
103
- def seed_second_set()
105
+ def seed_second_set
104
106
  # Cheating: we change the tokens to scan...
105
107
  # Seeding second entry set...
106
108
  subject.scan_rule(0, grm1_token_b[0])
@@ -164,7 +166,7 @@ SNIPPET
164
166
  expect(subject.chart[0].size).to eq(3)
165
167
  # Last entry is: (.A, 0)
166
168
  dot_A_entry = subject.chart[0].last
167
-
169
+
168
170
  subject.start_rule(dot_A_entry, 0)
169
171
 
170
172
  # Expectations: two entries:
@@ -194,7 +196,7 @@ SNIPPET
194
196
  expect(last_entry.vertex.label).to eq('A => a . A c')
195
197
  expect(last_entry.origin).to eq(0)
196
198
  antecedence = subject.antecedence
197
- expect(antecedence.fetch(last_entry)).to eq([fourth_entry])
199
+ expect(antecedence.fetch(last_entry)).to eq([fourth_entry])
198
200
  end
199
201
 
200
202
  it 'should apply the exit rule correctly' do
@@ -219,7 +221,7 @@ SNIPPET
219
221
  exit_entry = subject.chart[1].last
220
222
  expect(exit_entry.vertex.label).to eq('A.')
221
223
  expect(exit_entry.origin).to eq(0)
222
- expect(subject.antecedence.fetch(exit_entry)).to eq([last_entry])
224
+ expect(subject.antecedence.fetch(exit_entry)).to eq([last_entry])
223
225
  end
224
226
 
225
227
  it 'should apply the end rule correctly' do
@@ -248,10 +250,8 @@ SNIPPET
248
250
  expect(end_entry.origin).to eq(0)
249
251
  expect(subject.antecedence.fetch(end_entry)).to eq([exit_entry])
250
252
  end
251
- =begin
252
-
253
-
254
253
 
254
+ =begin
255
255
  it 'should retrieve the parse states that expect a given terminal' do
256
256
  item1 = DottedItem.new(prod_A1, 2)
257
257
  item2 = DottedItem.new(prod_A1, 1)
@@ -282,18 +282,7 @@ SNIPPET
282
282
  =end
283
283
  end # context
284
284
 
285
- context 'Parse forest building:' do
286
- let(:sample_grammar1) do
287
- builder = grammar_abc_builder
288
- builder.grammar
289
- end
290
-
291
- let(:token_seq1) do
292
- %w[a a b c c].map do |letter|
293
- Lexical::Token.new(letter, sample_grammar1.name2symbol[letter])
294
- end
295
- end
296
-
285
+ context 'Provided services:' do
297
286
  let(:b_expr_grammar) do
298
287
  builder = grammar_expr_builder
299
288
  builder.grammar
@@ -308,247 +297,47 @@ SNIPPET
308
297
  tokens = expr_tokenizer('2 + 3 * 4')
309
298
  parser.parse(tokens)
310
299
  end
311
-
312
- it 'should indicate whether a parse succeeded' do
313
- expect(subject.success?).to be_truthy
314
- end
315
-
316
- it 'should build a parse forest' do
317
- expect { subject.parse_forest }.not_to raise_error if subject.success?
318
- end
319
- =begin
320
- it 'should create the root of a parse forest' do
321
- (entry_tracker, builder) = prepare_parse_forest(subject)
322
- # The root node should correspond to the start symbol and
323
- # its direct children should correspond to rhs of start production
324
- expected_text = <<-SNIPPET
325
- P[0, 5]
326
- +- S[0, 5]
327
- SNIPPET
328
- root_text = builder.root.to_string(0)
329
- expect(root_text).to eq(expected_text.chomp)
330
-
331
- expect(entry_tracker.entry_set_index).to eq(subject.tokens.size)
332
- expected_entry = 'P => S . | 0'
333
- expect(entry_tracker.parse_entry.to_s).to eq(expected_entry)
334
- expect(builder.current_node.to_string(0)).to eq('S[0, 5]')
335
- end
336
- =end
337
- =begin
338
- it 'should use a reduce item for a matched non-terminal' do
339
- # Setup
340
- (entry_tracker, builder) = prepare_parse_tree(subject)
341
- # Same entry as in previous example
342
-
343
- # Given matched symbol is S[0, 5]
344
- # And its reduce item is S => S + M . | 0
345
- # Then add child nodes corresponding to the rhs symbols
346
- # And make M[?, 5] the current symbol
347
- subject.insert_matched_symbol(entry_tracker, builder)
348
- expected_text = <<-SNIPPET
349
- P[0, 5]
350
- +- S[0, 5]
351
- +- S[0, ?]
352
- +- +[?, ?]: '(nil)'
353
- +- M[?, 5]
354
- SNIPPET
355
- root_text = builder.root.to_string(0)
356
- expect(root_text).to eq(expected_text.chomp)
357
- expected_entry = 'S => S + M . | 0'
358
- expect(entry_tracker.parse_entry.to_s).to eq(expected_entry)
359
- expect(entry_tracker.entry_set_index).to eq(5)
360
- expect(builder.current_node.to_string(0)).to eq('M[?, 5]')
361
-
362
- # Second similar test
363
-
364
- # Given matched symbol is M[?, 5]
365
- # And its reduce item is M => M * T . | 2
366
- # Then add child nodes corresponding to the rhs symbols
367
- # And make T[?, 5] the current symbol
368
- subject.insert_matched_symbol(entry_tracker, builder)
369
- expected_text = <<-SNIPPET
370
- P[0, 5]
371
- +- S[0, 5]
372
- +- S[0, ?]
373
- +- +[?, ?]: '(nil)'
374
- +- M[2, 5]
375
- +- M[2, ?]
376
- +- *[?, ?]: '(nil)'
377
- +- T[?, 5]
378
- SNIPPET
379
- root_text = builder.root.to_string(0)
380
- expect(root_text).to eq(expected_text.chomp)
381
- expected_entry = 'M => M * T . | 2'
382
- expect(entry_tracker.parse_entry.to_s).to eq(expected_entry)
383
- expect(entry_tracker.entry_set_index).to eq(5)
384
- expect(builder.current_node.to_string(0)).to eq('T[?, 5]')
385
- end
386
-
387
-
388
300
 
389
- it 'should use a previous item for a terminal symbol' do
390
- # Setup
391
- (entry_tracker, builder) = prepare_parse_tree(subject)
392
- 3.times do
393
- subject.insert_matched_symbol(entry_tracker, builder)
394
- end
395
-
396
- # Given matched symbol is T[?, 5]
397
- # And its reduce item is T => integer . | 4
398
- # Then add child node corresponding to the rhs symbol
399
- # And make integer[4, 5]: '(nil)' the current symbol
400
- expected_text = <<-SNIPPET
401
- P[0, 5]
402
- +- S[0, 5]
403
- +- S[0, ?]
404
- +- +[?, ?]: '(nil)'
405
- +- M[2, 5]
406
- +- M[2, ?]
407
- +- *[?, ?]: '(nil)'
408
- +- T[4, 5]
409
- +- integer[4, 5]: '(nil)'
410
- SNIPPET
411
- root_text = builder.root.to_string(0)
412
- expect(root_text).to eq(expected_text.chomp)
413
- expected_entry = 'T => integer . | 4'
414
- expect(entry_tracker.parse_entry.to_s).to eq(expected_entry)
415
- expect(entry_tracker.entry_set_index).to eq(5)
416
- integer_repr = "integer[4, 5]: '(nil)'"
417
- expect(builder.current_node.to_string(0)).to eq(integer_repr)
418
-
419
- # Given current tree symbol is integer[4, 5]: '(nil)'
420
- # And its previous item is T => . integer | 4
421
- # Then attach the token to the terminal node
422
- # And decrement the entry index by one
423
- # Make *[?, ?]: '(nil)' the current symbol
424
- subject.insert_matched_symbol(entry_tracker, builder)
425
- expected_text = <<-SNIPPET
426
- P[0, 5]
427
- +- S[0, 5]
428
- +- S[0, ?]
429
- +- +[?, ?]: '(nil)'
430
- +- M[2, 5]
431
- +- M[2, ?]
432
- +- *[?, ?]: '(nil)'
433
- +- T[4, 5]
434
- +- integer[4, 5]: '4'
435
- SNIPPET
436
- root_text = builder.root.to_string(0)
437
- expect(root_text).to eq(expected_text.chomp)
438
- expected_entry = 'T => . integer | 4'
439
- expect(entry_tracker.parse_entry.to_s).to eq(expected_entry)
440
- expect(entry_tracker.entry_set_index).to eq(4)
441
- next_symbol = "*[?, ?]: '(nil)'"
442
- expect(builder.current_node.to_string(0)).to eq(next_symbol)
301
+ it 'should give a text representation of itself' do
302
+ repr = subject.to_s
303
+ expect(repr).to match(/^success\? true/)
304
+
305
+ # Let's test the last chart state only
306
+ expectation = <<REPR
307
+ State[5]
308
+ T => integer . | 4
309
+ T. | 4
310
+ M => M * T . | 2
311
+ M. | 2
312
+ S => S + M . | 0
313
+ M => M . * T | 2
314
+ S. | 0
315
+ P => S . | 0
316
+ S => S . + M | 0
317
+ P. | 0
318
+ REPR
443
319
  end
320
+ end # context
444
321
 
445
- it 'should handle [no symbol before dot, terminal tree node] case' do
446
- # Setup
447
- (entry_tracker, builder) = prepare_parse_tree(subject)
448
- 4.times do
449
- subject.insert_matched_symbol(entry_tracker, builder)
450
- end
451
-
452
- # Given current tree symbol is *[?, ?]: '(nil)'
453
- # And current dotted item is T => . integer | 4
454
- # When one retrieves the parse entry expecting the T
455
- # Then new parse entry is changed to: M => M * . T | 2
456
- subject.insert_matched_symbol(entry_tracker, builder)
457
-
458
- expected_text = <<-SNIPPET
459
- P[0, 5]
460
- +- S[0, 5]
461
- +- S[0, ?]
462
- +- +[?, ?]: '(nil)'
463
- +- M[2, 5]
464
- +- M[2, ?]
465
- +- *[?, ?]: '(nil)'
466
- +- T[4, 5]
467
- +- integer[4, 5]: '4'
468
- SNIPPET
469
- root_text = builder.root.to_string(0)
470
- expect(root_text).to eq(expected_text.chomp)
471
- expected_entry = 'M => M * . T | 2'
472
- expect(entry_tracker.parse_entry.to_s).to eq(expected_entry)
473
- expect(entry_tracker.entry_set_index).to eq(4)
474
- next_symbol = "*[?, ?]: '(nil)'"
475
- expect(builder.current_node.to_string(0)).to eq(next_symbol)
476
-
477
- subject.insert_matched_symbol(entry_tracker, builder)
478
- next_symbol = 'M[2, ?]'
479
- expect(builder.current_node.to_string(0)).to eq(next_symbol)
322
+ context 'Parse forest building:' do
323
+ let(:b_expr_grammar) do
324
+ builder = grammar_expr_builder
325
+ builder.grammar
480
326
  end
481
327
 
482
- it 'should handle the end of parse tree generation' do
483
- # Begin setup
484
- is_done = false
485
- (entry_tracker, builder) = prepare_parse_tree(subject)
486
- 16.times do
487
- is_done = subject.insert_matched_symbol(entry_tracker, builder)
488
- end
489
-
490
- expected_text = <<-SNIPPET
491
- P[0, 5]
492
- +- S[0, 5]
493
- +- S[0, 1]
494
- +- M[0, 1]
495
- +- T[0, 1]
496
- +- integer[0, 1]: '2'
497
- +- +[1, 2]: '+'
498
- +- M[2, 5]
499
- +- M[2, 3]
500
- +- T[2, 3]
501
- +- integer[2, 3]: '3'
502
- +- *[3, 4]: '*'
503
- +- T[4, 5]
504
- +- integer[4, 5]: '4'
505
- SNIPPET
506
- root_text = builder.root.to_string(0)
507
- expect(root_text).to eq(expected_text.chomp)
508
-
509
- expected_entry = 'T => . integer | 0'
510
- expect(entry_tracker.parse_entry.to_s).to eq(expected_entry)
511
- expect(entry_tracker.entry_set_index).to eq(0)
512
- expect(is_done).to eq(true)
328
+ def grm_symbol(aSymbolName)
329
+ b_expr_grammar.name2symbol[aSymbolName]
513
330
  end
514
331
 
515
-
516
-
517
- it 'should build the parse tree for a simple non-ambiguous grammar' do
518
- parser = EarleyParser.new(sample_grammar1)
519
- instance = parser.parse(token_seq1)
520
- ptree = instance.parse_tree
521
- expect(ptree).to be_kind_of(PTree::ParseTree)
332
+ subject do
333
+ parser = GFGEarleyParser.new(b_expr_grammar)
334
+ tokens = expr_tokenizer('3 * 4')
335
+ parser.parse(tokens)
522
336
  end
523
337
 
524
- it 'should build the parse tree for a simple expression grammar' do
525
- parser = EarleyParser.new(b_expr_grammar)
526
- tokens = expr_tokenizer('2 + 3 * 4', b_expr_grammar)
527
- instance = parser.parse(tokens)
528
- ptree = instance.parse_tree
529
- expect(ptree).to be_kind_of(PTree::ParseTree)
530
-
531
- # Expect parse tree:
532
- expected_text = <<-SNIPPET
533
- P[0, 5]
534
- +- S[0, 5]
535
- +- S[0, 1]
536
- +- M[0, 1]
537
- +- T[0, 1]
538
- +- integer[0, 1]: '2'
539
- +- +[1, 2]: '+'
540
- +- M[2, 5]
541
- +- M[2, 3]
542
- +- T[2, 3]
543
- +- integer[2, 3]: '3'
544
- +- *[3, 4]: '*'
545
- +- T[4, 5]
546
- +- integer[4, 5]: '4'
547
- SNIPPET
548
- actual = ptree.root.to_string(0)
549
- expect(actual).to eq(expected_text.chomp)
338
+ it 'should indicate whether a parse succeeded' do
339
+ expect(subject.success?).to be_truthy
550
340
  end
551
- =end
552
341
  end # context
553
342
  end # describe
554
343
  end # module