rley 0.7.06 → 0.8.01

Sign up to get free protection for your applications and to get access to all the features.
Files changed (167) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +362 -62
  3. data/.travis.yml +6 -6
  4. data/CHANGELOG.md +20 -4
  5. data/LICENSE.txt +1 -1
  6. data/README.md +7 -7
  7. data/examples/NLP/engtagger.rb +193 -190
  8. data/examples/NLP/nano_eng/nano_en_demo.rb +7 -11
  9. data/examples/NLP/nano_eng/nano_grammar.rb +21 -21
  10. data/examples/NLP/pico_en_demo.rb +2 -2
  11. data/examples/data_formats/JSON/cli_options.rb +1 -1
  12. data/examples/data_formats/JSON/json_ast_builder.rb +21 -27
  13. data/examples/data_formats/JSON/json_ast_nodes.rb +12 -21
  14. data/examples/data_formats/JSON/json_demo.rb +1 -2
  15. data/examples/data_formats/JSON/json_grammar.rb +13 -13
  16. data/examples/data_formats/JSON/json_lexer.rb +8 -8
  17. data/examples/data_formats/JSON/json_minifier.rb +1 -1
  18. data/examples/general/calc_iter1/calc_ast_builder.rb +13 -10
  19. data/examples/general/calc_iter1/calc_ast_nodes.rb +23 -37
  20. data/examples/general/calc_iter1/calc_grammar.rb +7 -6
  21. data/examples/general/calc_iter1/calc_lexer.rb +6 -4
  22. data/examples/general/calc_iter1/spec/calculator_spec.rb +5 -5
  23. data/examples/general/calc_iter2/calc_ast_builder.rb +5 -3
  24. data/examples/general/calc_iter2/calc_ast_nodes.rb +27 -43
  25. data/examples/general/calc_iter2/calc_grammar.rb +12 -12
  26. data/examples/general/calc_iter2/calc_lexer.rb +11 -10
  27. data/examples/general/calc_iter2/spec/calculator_spec.rb +26 -26
  28. data/examples/general/left.rb +2 -2
  29. data/examples/general/right.rb +2 -2
  30. data/lib/rley.rb +1 -1
  31. data/lib/rley/base/dotted_item.rb +28 -31
  32. data/lib/rley/base/grm_items_builder.rb +6 -0
  33. data/lib/rley/constants.rb +2 -2
  34. data/lib/rley/engine.rb +22 -25
  35. data/lib/rley/formatter/asciitree.rb +3 -3
  36. data/lib/rley/formatter/bracket_notation.rb +1 -8
  37. data/lib/rley/formatter/debug.rb +6 -6
  38. data/lib/rley/formatter/json.rb +2 -2
  39. data/lib/rley/gfg/call_edge.rb +1 -1
  40. data/lib/rley/gfg/edge.rb +5 -5
  41. data/lib/rley/gfg/end_vertex.rb +2 -6
  42. data/lib/rley/gfg/epsilon_edge.rb +1 -5
  43. data/lib/rley/gfg/grm_flow_graph.rb +27 -23
  44. data/lib/rley/gfg/item_vertex.rb +10 -10
  45. data/lib/rley/gfg/non_terminal_vertex.rb +4 -4
  46. data/lib/rley/gfg/scan_edge.rb +1 -1
  47. data/lib/rley/gfg/shortcut_edge.rb +2 -2
  48. data/lib/rley/gfg/start_vertex.rb +4 -8
  49. data/lib/rley/gfg/vertex.rb +43 -39
  50. data/lib/rley/interface.rb +16 -0
  51. data/lib/rley/lexical/token_range.rb +6 -6
  52. data/lib/rley/notation/all_notation_nodes.rb +2 -0
  53. data/lib/rley/notation/ast_builder.rb +191 -0
  54. data/lib/rley/notation/ast_node.rb +44 -0
  55. data/lib/rley/notation/ast_visitor.rb +113 -0
  56. data/lib/rley/notation/grammar.rb +49 -0
  57. data/lib/rley/notation/grammar_builder.rb +504 -0
  58. data/lib/rley/notation/grouping_node.rb +23 -0
  59. data/lib/rley/notation/parser.rb +56 -0
  60. data/lib/rley/notation/sequence_node.rb +35 -0
  61. data/lib/rley/notation/symbol_node.rb +29 -0
  62. data/lib/rley/notation/tokenizer.rb +192 -0
  63. data/lib/rley/parse_forest_visitor.rb +5 -5
  64. data/lib/rley/parse_rep/ast_base_builder.rb +48 -11
  65. data/lib/rley/parse_rep/cst_builder.rb +5 -6
  66. data/lib/rley/parse_rep/parse_forest_builder.rb +22 -18
  67. data/lib/rley/parse_rep/parse_forest_factory.rb +3 -3
  68. data/lib/rley/parse_rep/parse_rep_creator.rb +14 -16
  69. data/lib/rley/parse_rep/parse_tree_builder.rb +4 -4
  70. data/lib/rley/parse_rep/parse_tree_factory.rb +27 -27
  71. data/lib/rley/parse_tree_visitor.rb +1 -1
  72. data/lib/rley/parser/error_reason.rb +4 -5
  73. data/lib/rley/parser/gfg_chart.rb +118 -26
  74. data/lib/rley/parser/gfg_parsing.rb +22 -33
  75. data/lib/rley/parser/parse_entry.rb +25 -31
  76. data/lib/rley/parser/parse_entry_set.rb +19 -16
  77. data/lib/rley/parser/parse_entry_tracker.rb +4 -4
  78. data/lib/rley/parser/parse_tracer.rb +13 -13
  79. data/lib/rley/parser/parse_walker_factory.rb +23 -28
  80. data/lib/rley/ptree/non_terminal_node.rb +7 -5
  81. data/lib/rley/ptree/parse_tree.rb +3 -3
  82. data/lib/rley/ptree/parse_tree_node.rb +5 -5
  83. data/lib/rley/ptree/terminal_node.rb +7 -7
  84. data/lib/rley/rley_error.rb +12 -12
  85. data/lib/rley/sppf/alternative_node.rb +6 -6
  86. data/lib/rley/sppf/composite_node.rb +7 -7
  87. data/lib/rley/sppf/epsilon_node.rb +3 -3
  88. data/lib/rley/sppf/leaf_node.rb +3 -3
  89. data/lib/rley/sppf/parse_forest.rb +16 -16
  90. data/lib/rley/sppf/sppf_node.rb +7 -8
  91. data/lib/rley/sppf/token_node.rb +3 -3
  92. data/lib/rley/syntax/{grammar_builder.rb → base_grammar_builder.rb} +61 -23
  93. data/lib/rley/syntax/grammar.rb +5 -5
  94. data/lib/rley/syntax/grm_symbol.rb +7 -7
  95. data/lib/rley/syntax/match_closest.rb +43 -0
  96. data/lib/rley/syntax/non_terminal.rb +9 -15
  97. data/lib/rley/syntax/production.rb +16 -10
  98. data/lib/rley/syntax/symbol_seq.rb +7 -9
  99. data/lib/rley/syntax/terminal.rb +4 -5
  100. data/lib/rley/syntax/verbatim_symbol.rb +3 -3
  101. data/lib/support/base_tokenizer.rb +19 -18
  102. data/spec/rley/base/dotted_item_spec.rb +2 -2
  103. data/spec/rley/engine_spec.rb +23 -21
  104. data/spec/rley/formatter/asciitree_spec.rb +7 -7
  105. data/spec/rley/formatter/bracket_notation_spec.rb +13 -13
  106. data/spec/rley/formatter/json_spec.rb +1 -1
  107. data/spec/rley/gfg/end_vertex_spec.rb +5 -5
  108. data/spec/rley/gfg/grm_flow_graph_spec.rb +2 -2
  109. data/spec/rley/gfg/item_vertex_spec.rb +10 -10
  110. data/spec/rley/gfg/non_terminal_vertex_spec.rb +3 -3
  111. data/spec/rley/gfg/shortcut_edge_spec.rb +1 -1
  112. data/spec/rley/gfg/start_vertex_spec.rb +5 -5
  113. data/spec/rley/gfg/vertex_spec.rb +3 -3
  114. data/spec/rley/lexical/token_range_spec.rb +16 -16
  115. data/spec/rley/lexical/token_spec.rb +2 -2
  116. data/spec/rley/notation/grammar_builder_spec.rb +302 -0
  117. data/spec/rley/notation/parser_spec.rb +184 -0
  118. data/spec/rley/notation/tokenizer_spec.rb +370 -0
  119. data/spec/rley/parse_forest_visitor_spec.rb +165 -163
  120. data/spec/rley/parse_rep/ambiguous_parse_spec.rb +44 -44
  121. data/spec/rley/parse_rep/ast_builder_spec.rb +6 -7
  122. data/spec/rley/parse_rep/cst_builder_spec.rb +5 -5
  123. data/spec/rley/parse_rep/groucho_spec.rb +24 -26
  124. data/spec/rley/parse_rep/parse_forest_builder_spec.rb +27 -27
  125. data/spec/rley/parse_rep/parse_forest_factory_spec.rb +8 -8
  126. data/spec/rley/parse_rep/parse_tree_factory_spec.rb +3 -3
  127. data/spec/rley/parse_tree_visitor_spec.rb +10 -8
  128. data/spec/rley/parser/dangling_else_spec.rb +445 -0
  129. data/spec/rley/parser/error_reason_spec.rb +6 -6
  130. data/spec/rley/parser/gfg_earley_parser_spec.rb +120 -12
  131. data/spec/rley/parser/gfg_parsing_spec.rb +6 -13
  132. data/spec/rley/parser/parse_entry_spec.rb +19 -19
  133. data/spec/rley/parser/parse_walker_factory_spec.rb +10 -10
  134. data/spec/rley/ptree/non_terminal_node_spec.rb +5 -3
  135. data/spec/rley/ptree/parse_tree_node_spec.rb +4 -4
  136. data/spec/rley/ptree/terminal_node_spec.rb +6 -6
  137. data/spec/rley/sppf/alternative_node_spec.rb +6 -6
  138. data/spec/rley/sppf/non_terminal_node_spec.rb +3 -3
  139. data/spec/rley/sppf/token_node_spec.rb +4 -4
  140. data/spec/rley/support/ambiguous_grammar_helper.rb +4 -5
  141. data/spec/rley/support/grammar_abc_helper.rb +3 -5
  142. data/spec/rley/support/grammar_ambig01_helper.rb +5 -6
  143. data/spec/rley/support/grammar_arr_int_helper.rb +5 -6
  144. data/spec/rley/support/grammar_b_expr_helper.rb +5 -6
  145. data/spec/rley/support/grammar_int_seq_helper.rb +51 -0
  146. data/spec/rley/support/grammar_l0_helper.rb +14 -17
  147. data/spec/rley/support/grammar_pb_helper.rb +8 -7
  148. data/spec/rley/support/grammar_sppf_helper.rb +3 -3
  149. data/spec/rley/syntax/{grammar_builder_spec.rb → base_grammar_builder_spec.rb} +35 -16
  150. data/spec/rley/syntax/grammar_spec.rb +6 -6
  151. data/spec/rley/syntax/grm_symbol_spec.rb +1 -1
  152. data/spec/rley/syntax/match_closest_spec.rb +46 -0
  153. data/spec/rley/syntax/non_terminal_spec.rb +8 -8
  154. data/spec/rley/syntax/production_spec.rb +17 -13
  155. data/spec/rley/syntax/symbol_seq_spec.rb +2 -2
  156. data/spec/rley/syntax/terminal_spec.rb +5 -5
  157. data/spec/rley/syntax/verbatim_symbol_spec.rb +1 -1
  158. data/spec/spec_helper.rb +0 -12
  159. data/spec/support/base_tokenizer_spec.rb +7 -2
  160. metadata +48 -74
  161. data/.simplecov +0 -7
  162. data/lib/rley/parser/parse_state.rb +0 -83
  163. data/lib/rley/parser/parse_state_tracker.rb +0 -59
  164. data/lib/rley/parser/state_set.rb +0 -101
  165. data/spec/rley/parser/parse_state_spec.rb +0 -125
  166. data/spec/rley/parser/parse_tracer_spec.rb +0 -200
  167. data/spec/rley/parser/state_set_spec.rb +0 -130
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Load the builder class
4
- require_relative '../../../lib/rley/syntax/grammar_builder'
4
+ require_relative '../../../lib/rley/syntax/base_grammar_builder'
5
5
  require_relative '../../../lib/support/base_tokenizer'
6
6
  require_relative '../../../lib/rley/lexical/token'
7
7
 
@@ -12,9 +12,9 @@ class GrammarPBHelper
12
12
  # expression based on example found in paper of
13
13
  # K. Pingali and G. Bilardi:
14
14
  # "A Graphical Model for Context-Free Grammar Parsing"
15
- def grammar()
15
+ def grammar
16
16
  @grammar ||= begin
17
- builder = Rley::Syntax::GrammarBuilder.new do
17
+ builder = Rley::Syntax::BaseGrammarBuilder.new do
18
18
  add_terminals('int', '+', '(', ')')
19
19
  rule 'S' => 'E'
20
20
  rule 'E' => 'int'
@@ -24,12 +24,13 @@ class GrammarPBHelper
24
24
  builder.grammar
25
25
  end
26
26
  end
27
-
27
+
28
28
  class PB_Tokenizer < BaseTokenizer
29
29
  protected
30
30
 
31
- def recognize_token()
32
- if (lexeme = scanner.scan(/[\(\)]/)) # Single characters
31
+ # rubocop: disable Lint/DuplicateBranch
32
+ def recognize_token
33
+ if (lexeme = scanner.scan(/[()]/)) # Single characters
33
34
  # Delimiters, separators => single character token
34
35
  build_token(lexeme, lexeme)
35
36
  elsif (lexeme = scanner.scan(/(?:\+)(?=\s|$)/)) # Isolated char
@@ -38,6 +39,7 @@ class GrammarPBHelper
38
39
  build_token('int', lexeme)
39
40
  end
40
41
  end
42
+ # rubocop: enable Lint/DuplicateBranch
41
43
  end # class
42
44
 
43
45
  # Basic tokenizer
@@ -46,6 +48,5 @@ class GrammarPBHelper
46
48
  tokenizer = PB_Tokenizer.new(aText)
47
49
  tokenizer.tokens
48
50
  end
49
-
50
51
  end # class
51
52
  # End of file
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Load the builder class
4
- require_relative '../../../lib/rley/syntax/grammar_builder'
4
+ require_relative '../../../lib/rley/syntax/base_grammar_builder'
5
5
 
6
6
 
7
7
  module GrammarSPPFHelper
@@ -10,8 +10,8 @@ module GrammarSPPFHelper
10
10
  # "SPPF-Style Parsing From Earley Recognizers" in
11
11
  # Notes in Theoretical Computer Science 203, (2008), pp. 53-67
12
12
  # contains a hidden left recursion and a cycle
13
- def grammar_sppf_builder()
14
- builder = Rley::Syntax::GrammarBuilder.new do
13
+ def grammar_sppf_builder
14
+ builder = Rley::Syntax::BaseGrammarBuilder.new do
15
15
  add_terminals('a', 'b')
16
16
  rule 'Phi' => 'S'
17
17
  rule 'S' => %w[A T]
@@ -3,14 +3,14 @@
3
3
  require_relative '../../spec_helper'
4
4
 
5
5
  # Load the class under test
6
- require_relative '../../../lib/rley/syntax/grammar_builder'
6
+ require_relative '../../../lib/rley/syntax/base_grammar_builder'
7
7
 
8
8
  module Rley # Open this namespace to avoid module qualifier prefixes
9
9
  module Syntax # Open this namespace to avoid module qualifier prefixes
10
- describe GrammarBuilder do
10
+ describe BaseGrammarBuilder do
11
11
  context 'Initialization without argument:' do
12
12
  it 'could be created without argument' do
13
- expect { GrammarBuilder.new }.not_to raise_error
13
+ expect { BaseGrammarBuilder.new }.not_to raise_error
14
14
  end
15
15
 
16
16
  it 'should have no grammar symbols at start' do
@@ -24,13 +24,13 @@ module Rley # Open this namespace to avoid module qualifier prefixes
24
24
 
25
25
  context 'Initialization with argument:' do
26
26
  it 'could be created with a block argument' do
27
- expect do
28
- GrammarBuilder.new { nil }
27
+ expect do
28
+ BaseGrammarBuilder.new { nil }
29
29
  end.not_to raise_error
30
30
  end
31
31
 
32
32
  it 'could have grammar symbols from block argument' do
33
- instance = GrammarBuilder.new do
33
+ instance = BaseGrammarBuilder.new do
34
34
  add_terminals('a', 'b', 'c')
35
35
  end
36
36
  expect(instance.symbols.size).to eq(3)
@@ -80,7 +80,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
80
80
 
81
81
  context 'Adding productions:' do
82
82
  subject do
83
- instance = GrammarBuilder.new
83
+ instance = BaseGrammarBuilder.new
84
84
  instance.add_terminals('a', 'b', 'c')
85
85
  instance
86
86
  end
@@ -99,27 +99,46 @@ module Rley # Open this namespace to avoid module qualifier prefixes
99
99
  expect(new_prod.lhs).to eq(subject['A'])
100
100
  expect_rhs = [subject['a'], subject['A'], subject['c']]
101
101
  expect(new_prod.rhs.members).to eq(expect_rhs)
102
-
102
+
103
103
  # Try another syntax
104
104
  subject.add_production('A' => 'a A c')
105
105
  expect(subject.productions.size).to eq(3)
106
106
  new_prod = subject.productions.last
107
107
  expect(new_prod.lhs).to eq(subject['A'])
108
108
  expect_rhs = [subject['a'], subject['A'], subject['c']]
109
- expect(new_prod.rhs.members).to eq(expect_rhs)
109
+ expect(new_prod.rhs.members).to eq(expect_rhs)
110
110
 
111
- # GrammarBuilder#rule is an alias of add_production
111
+ # BaseGrammarBuilder#rule is an alias of add_production
112
112
  subject.rule('A' => ['b'])
113
113
  expect(subject.productions.size).to eq(4)
114
114
  new_prod = subject.productions.last
115
115
  expect(new_prod.lhs).to eq(subject['A'])
116
116
  expect(new_prod.rhs[0]).to eq(subject['b'])
117
117
  end
118
+
119
+ it "should support Kleene's plus" do
120
+ instance = BaseGrammarBuilder.new
121
+ instance.add_terminals('plus', 'minus', 'digit')
122
+
123
+ instance.add_production('integer' => 'value')
124
+ instance.add_production('integer' => 'sign value')
125
+ instance.add_production('sign' => 'plus')
126
+ instance.add_production('sign' => 'minus')
127
+ expect(instance.productions.size).to eq(4)
128
+ instance.add_production('value' => 'digit+')
129
+ expect(instance.productions.size).to eq(7) # Two additional rules generated
130
+ prod_plus = instance.productions.select { |prod| prod.lhs.name == 'digit_plus' }
131
+ expect(prod_plus.size).to eq(2)
132
+ last_prod = instance.productions.last
133
+ expect(last_prod.lhs.name).to eq('value')
134
+ expect(last_prod.rhs.members[0].name).to eq('digit_plus')
135
+ end
136
+
118
137
  end # context
119
138
 
120
139
  context 'Building grammar:' do
121
140
  subject do
122
- instance = GrammarBuilder.new do
141
+ instance = BaseGrammarBuilder.new do
123
142
  add_terminals('a', 'b', 'c')
124
143
  add_production('S' => ['A'])
125
144
  add_production('A' => %w[a A c])
@@ -141,14 +160,14 @@ module Rley # Open this namespace to avoid module qualifier prefixes
141
160
  end
142
161
 
143
162
  it 'should complain in absence of symbols' do
144
- instance = GrammarBuilder.new
163
+ instance = BaseGrammarBuilder.new
145
164
  err = StandardError
146
165
  msg = 'No symbol found for grammar'
147
166
  expect { instance.grammar }.to raise_error(err, msg)
148
167
  end
149
168
 
150
169
  it 'should complain in absence of productions' do
151
- instance = GrammarBuilder.new
170
+ instance = BaseGrammarBuilder.new
152
171
  instance.add_terminals('a', 'b', 'c')
153
172
  err = StandardError
154
173
  msg = 'No production found for grammar'
@@ -162,11 +181,11 @@ module Rley # Open this namespace to avoid module qualifier prefixes
162
181
  err = StandardError
163
182
  msg = 'Useless terminal symbol(s): d.'
164
183
  expect { subject.grammar }.to raise_error(err, msg)
165
-
184
+
166
185
  # Add another useless terminal
167
186
  subject.add_terminals('e')
168
187
  msg = 'Useless terminal symbol(s): d, e.'
169
- expect { subject.grammar }.to raise_error(err, msg)
188
+ expect { subject.grammar }.to raise_error(err, msg)
170
189
  end
171
190
 
172
191
  it 'should build a grammar with nullable nonterminals' do
@@ -183,7 +202,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
183
202
  t_star = VerbatimSymbol.new('*')
184
203
  t_slash = VerbatimSymbol.new('/')
185
204
 
186
- builder = GrammarBuilder.new
205
+ builder = BaseGrammarBuilder.new
187
206
  builder.add_terminals(t_a, t_star, t_slash)
188
207
  builder.add_production('S' => 'E')
189
208
  builder.add_production('E' => %w[E Q F])
@@ -74,7 +74,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
74
74
  let(:nt_A) { NonTerminal.new('A') }
75
75
  let(:nt_B) { NonTerminal.new('B') }
76
76
  let(:nt_C) { NonTerminal.new('C') }
77
- let(:nt_D) { NonTerminal.new('D') }
77
+ let(:nt_D) { NonTerminal.new('D') }
78
78
  let(:a_) { VerbatimSymbol.new('a') }
79
79
  let(:b_) { VerbatimSymbol.new('b') }
80
80
  let(:c_) { VerbatimSymbol.new('c') }
@@ -161,7 +161,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
161
161
  expect(subject.name2symbol['b']).to eq(b_)
162
162
  expect(subject.name2symbol['c']).to eq(c_)
163
163
  end
164
-
164
+
165
165
  it 'should ensure that each production has a name' do
166
166
  subject.rules.each do |prod|
167
167
  expect(prod.name).to match(Regexp.new("#{prod.lhs.name}_\\d$"))
@@ -218,8 +218,8 @@ module Rley # Open this namespace to avoid module qualifier prefixes
218
218
  partitioning = instance.non_terminals.partition(&:generative?)
219
219
  expect(partitioning[0].size).to eq(2)
220
220
  expect(partitioning[0]).to eq([nt_S, nt_A])
221
- expect(partitioning[1]).to eq([nt_B, nt_C, nt_D])
222
-
221
+ expect(partitioning[1]).to eq([nt_B, nt_C, nt_D])
222
+
223
223
  undefined = instance.non_terminals.select(&:undefined?)
224
224
  expect(undefined).to be_empty
225
225
  end
@@ -248,13 +248,13 @@ module Rley # Open this namespace to avoid module qualifier prefixes
248
248
  expect(nterm).to be_nullable
249
249
  end
250
250
  end
251
-
251
+
252
252
  it 'should mark its nullable productions' do
253
253
  # Given the above productions, here are our expectations:
254
254
  expectations = [true, false, false, true]
255
255
  actuals = subject.rules.map(&:nullable?)
256
256
  expect(actuals).to eq(expectations)
257
- end
257
+ end
258
258
  end # context
259
259
  end # describe
260
260
  end # module
@@ -20,7 +20,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
20
20
  expect(subject.name).to eq(sample_name)
21
21
  end
22
22
  end # context
23
-
23
+
24
24
  context 'Provided services:' do
25
25
  it 'should give its text representation' do
26
26
  expect(subject.to_s).to eq(sample_name)
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../spec_helper'
4
+
5
+ require_relative '../../../lib/rley/syntax/terminal'
6
+ require_relative '../../../lib/rley/syntax/non_terminal'
7
+ require_relative '../../../lib/rley/syntax/symbol_seq'
8
+
9
+ # Load the class under test
10
+ require_relative '../../../lib/rley/syntax/production'
11
+
12
+ # Load the class under test
13
+ require_relative '../../../lib/rley/syntax/match_closest'
14
+
15
+ module Rley # Open this namespace to avoid module qualifier prefixes
16
+ module Syntax # Open this namespace to avoid module qualifier prefixes
17
+ describe MatchClosest do
18
+ # 'stmt' => 'IF boolean THEN stmt ELSE stmt'
19
+ let(:boolean) { NonTerminal.new('boolean') }
20
+ let(:stmt) { NonTerminal.new('stmt') }
21
+ let(:if_t) { Terminal.new('IF') }
22
+ let(:then_t) { Terminal.new('THEN') }
23
+ let(:else_t) { Terminal.new('ELSE') }
24
+ let(:sequence) { [if_t, boolean, then_t, stmt, else_t, stmt] }
25
+ let(:prod) { Production.new(stmt, sequence) }
26
+
27
+ subject{ MatchClosest.new(prod.rhs.members, 4, 'IF') }
28
+
29
+ context 'Initialization:' do
30
+ it 'should be created with an symbol seq., an indice and a name' do
31
+ expect { MatchClosest.new(prod.rhs.members, 4, 'IF') }.not_to raise_error
32
+ end
33
+
34
+ it 'should know the index argument' do
35
+ expect(subject.idx_symbol).to eq(4) # ELSE at position 4
36
+ end
37
+
38
+ it 'should know the name of preceding symbol to pair with' do
39
+ expect(subject.closest_symb).to eq('IF')
40
+ end
41
+ end # context
42
+ end # describe
43
+ end # module
44
+ end # module
45
+
46
+ # End of file
@@ -19,28 +19,28 @@ module Rley # Open this namespace to avoid module qualifier prefixes
19
19
  it 'should know its name' do
20
20
  expect(subject.name).to eq(sample_name)
21
21
  end
22
-
22
+
23
23
  it 'should know that is a not a terminal' do
24
24
  expect(subject).not_to be_terminal
25
25
  end
26
26
  end # context
27
27
 
28
-
29
- context 'Provided services:' do
28
+
29
+ context 'Provided services:' do
30
30
  it 'should know whether it is nullable' do
31
31
  expect(subject.nullable?).to be_nil
32
32
  subject.nullable = true
33
33
  expect(subject).to be_nullable
34
34
  subject.nullable = false
35
- expect(subject).not_to be_nullable
35
+ expect(subject).not_to be_nullable
36
36
  end
37
-
37
+
38
38
  it 'should know whether it is defined' do
39
39
  expect(subject.undefined?).to be_nil
40
40
  subject.undefined = true
41
41
  expect(subject).to be_undefined
42
42
  subject.undefined = false
43
- expect(subject).not_to be_undefined
43
+ expect(subject).not_to be_undefined
44
44
  end
45
45
 
46
46
  it 'should know whether it is generative' do
@@ -48,8 +48,8 @@ module Rley # Open this namespace to avoid module qualifier prefixes
48
48
  subject.generative = true
49
49
  expect(subject).to be_generative
50
50
  subject.generative = false
51
- expect(subject).not_to be_generative
52
- end
51
+ expect(subject).not_to be_generative
52
+ end
53
53
  end # context
54
54
  end # describe
55
55
  end # module
@@ -24,11 +24,11 @@ module Rley # Open this namespace to avoid module qualifier prefixes
24
24
  it 'should be created with a non-terminal and a symbol sequence' do
25
25
  expect { Production.new(sentence, sequence) }.not_to raise_error
26
26
  end
27
-
27
+
28
28
  it 'should complain when its rhs is nil' do
29
29
  err = StandardError
30
30
  msg_prefix = 'Right side of a production of the kind '
31
- msg_suffix = "'Sentence' => ... is nil."
31
+ msg_suffix = "'Sentence' => ... is nil."
32
32
  msg = msg_prefix + msg_suffix
33
33
  expect { Production.new(sentence, nil) }.to raise_error(err, msg)
34
34
  end
@@ -43,48 +43,52 @@ module Rley # Open this namespace to avoid module qualifier prefixes
43
43
  expect(subject.body).to eq(sequence)
44
44
  end
45
45
 
46
+ it 'should be free from constraints at start' do
47
+ expect(subject.constraints).to be_empty
48
+ end
49
+
46
50
  it 'should know whether its rhs is empty' do
47
51
  expect(subject).not_to be_empty
48
52
 
49
53
  instance = Production.new(sentence, [])
50
54
  expect(instance).to be_empty
51
55
  end
52
-
56
+
53
57
  it 'should be anonymous at creation' do
54
58
  expect(subject.name).to be_nil
55
59
  end
56
-
60
+
57
61
  it 'should complain if its lhs is not a non-terminal' do
58
62
  err = StandardError
59
63
  msg_prefix = 'Left side of production must be a non-terminal symbol'
60
- msg_suffix = ", found a #{String} instead."
64
+ msg_suffix = ", found a #{String} instead."
61
65
  msg = msg_prefix + msg_suffix
62
66
  expect { Production.new('wrong', sequence) }.to raise_error(err, msg)
63
67
  end
64
68
  end # context
65
-
69
+
66
70
  context 'Provided services:' do
67
71
  it 'should accept a name (i)' do
68
72
  a_name = 'nominem'
69
73
  subject.name = a_name
70
74
  expect(subject.name).to eq(a_name)
71
75
  end
72
-
76
+
73
77
  it 'should accept a name (ii)' do
74
78
  a_name = 'nominem'
75
79
  subject.as(a_name)
76
- expect(subject.name).to eq(a_name)
80
+ expect(subject.name).to eq(a_name)
77
81
  end
78
-
82
+
79
83
  it 'should provide human-readable representation of itself' do
80
84
  subject.name = 'some name'
81
85
  prefix = /^#<Rley::Syntax::Production:\d+ @name="some name"/
82
86
  expect(subject.inspect).to match(prefix)
83
- pattern = /@lhs=Sentence @rhs=#<Rley::Syntax::SymbolSeq/
87
+ pattern = /@lhs=Sentence @rhs=#<Rley::Syntax::SymbolSeq/
84
88
  expect(subject.inspect).to match(pattern)
85
- suffix = /> @generative=>$/
86
- expect(subject.inspect).to match(suffix)
87
- end
89
+ suffix = /> @generative=>$/
90
+ expect(subject.inspect).to match(suffix)
91
+ end
88
92
  end # context
89
93
  end # describe
90
94
  end # module
@@ -57,13 +57,13 @@ module Rley # Open this namespace to avoid module qualifier prefixes
57
57
  unequal_one = SymbolSeq.new([verb, pp, np])
58
58
  expect(subject == unequal_one).not_to eq(true)
59
59
  end
60
-
60
+
61
61
  it 'should complain when unable to compare' do
62
62
  err = StandardError
63
63
  msg = 'Cannot compare a SymbolSeq with a String'
64
64
  expect { subject == 'dummy-text' }.to raise_error(err, msg)
65
65
  end
66
-
66
+
67
67
  it 'should provide human-readable representation of itself' do
68
68
  suffix = /::SymbolSeq:\d+ @members=\["Verb", "NP", "PP"\]>$/
69
69
  expect(subject.inspect).to match(suffix)