rley 0.8.14 → 0.8.15

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 (76) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +20 -2
  3. data/CHANGELOG.md +3 -0
  4. data/examples/general/calc_iter1/spec/calculator_spec.rb +9 -9
  5. data/examples/general/calc_iter2/spec/calculator_spec.rb +39 -39
  6. data/examples/general/recursive_right.rb +2 -2
  7. data/lib/rley/constants.rb +1 -1
  8. data/lib/rley/gfg/grm_flow_graph.rb +0 -1
  9. data/lib/rley/parser/parse_entry_set.rb +0 -1
  10. data/lib/rley/parser/parse_walker_factory.rb +0 -1
  11. data/lib/rley/rgn/grammar_builder.rb +0 -2
  12. data/lib/rley/rgn/tokenizer.rb +1 -1
  13. data/lib/rley/syntax/base_grammar_builder.rb +0 -1
  14. data/lib/rley/syntax/grammar.rb +0 -1
  15. data/spec/rley/base/dotted_item_spec.rb +46 -46
  16. data/spec/rley/base/grm_items_builder_spec.rb +1 -1
  17. data/spec/rley/engine_spec.rb +50 -50
  18. data/spec/rley/formatter/asciitree_spec.rb +8 -8
  19. data/spec/rley/formatter/bracket_notation_spec.rb +10 -10
  20. data/spec/rley/formatter/debug_spec.rb +10 -10
  21. data/spec/rley/formatter/json_spec.rb +6 -7
  22. data/spec/rley/gfg/call_edge_spec.rb +6 -6
  23. data/spec/rley/gfg/edge_spec.rb +8 -7
  24. data/spec/rley/gfg/end_vertex_spec.rb +8 -7
  25. data/spec/rley/gfg/epsilon_edge_spec.rb +5 -4
  26. data/spec/rley/gfg/grm_flow_graph_spec.rb +33 -34
  27. data/spec/rley/gfg/item_vertex_spec.rb +34 -36
  28. data/spec/rley/gfg/non_terminal_vertex_spec.rb +12 -12
  29. data/spec/rley/gfg/return_edge_spec.rb +6 -6
  30. data/spec/rley/gfg/scan_edge_spec.rb +7 -6
  31. data/spec/rley/gfg/shortcut_edge_spec.rb +15 -15
  32. data/spec/rley/gfg/start_vertex_spec.rb +8 -8
  33. data/spec/rley/gfg/vertex_spec.rb +18 -18
  34. data/spec/rley/lexical/literal_spec.rb +5 -5
  35. data/spec/rley/lexical/token_range_spec.rb +55 -55
  36. data/spec/rley/lexical/token_spec.rb +17 -16
  37. data/spec/rley/parse_forest_visitor_spec.rb +30 -32
  38. data/spec/rley/parse_rep/ambiguous_parse_spec.rb +2 -2
  39. data/spec/rley/parse_rep/ast_builder_spec.rb +30 -30
  40. data/spec/rley/parse_rep/cst_builder_spec.rb +85 -85
  41. data/spec/rley/parse_rep/groucho_spec.rb +23 -23
  42. data/spec/rley/parse_rep/parse_forest_builder_spec.rb +42 -42
  43. data/spec/rley/parse_rep/parse_forest_factory_spec.rb +10 -12
  44. data/spec/rley/parse_rep/parse_tree_factory_spec.rb +10 -15
  45. data/spec/rley/parse_tree_visitor_spec.rb +43 -46
  46. data/spec/rley/parser/dangling_else_spec.rb +12 -12
  47. data/spec/rley/parser/error_reason_spec.rb +37 -37
  48. data/spec/rley/parser/gfg_chart_spec.rb +27 -29
  49. data/spec/rley/parser/gfg_earley_parser_spec.rb +55 -56
  50. data/spec/rley/parser/gfg_parsing_spec.rb +106 -103
  51. data/spec/rley/parser/parse_entry_set_spec.rb +63 -61
  52. data/spec/rley/parser/parse_entry_spec.rb +73 -71
  53. data/spec/rley/parser/parse_walker_factory_spec.rb +14 -15
  54. data/spec/rley/ptree/non_terminal_node_spec.rb +16 -16
  55. data/spec/rley/ptree/parse_tree_node_spec.rb +11 -11
  56. data/spec/rley/ptree/parse_tree_spec.rb +6 -8
  57. data/spec/rley/ptree/terminal_node_spec.rb +6 -6
  58. data/spec/rley/rgn/grammar_builder_spec.rb +69 -67
  59. data/spec/rley/rgn/parser_spec.rb +63 -63
  60. data/spec/rley/rgn/repetition_node_spec.rb +15 -15
  61. data/spec/rley/rgn/sequence_node_spec.rb +10 -10
  62. data/spec/rley/rgn/symbol_node_spec.rb +5 -6
  63. data/spec/rley/rgn/tokenizer_spec.rb +68 -67
  64. data/spec/rley/sppf/alternative_node_spec.rb +16 -16
  65. data/spec/rley/sppf/non_terminal_node_spec.rb +20 -20
  66. data/spec/rley/sppf/token_node_spec.rb +13 -13
  67. data/spec/rley/syntax/base_grammar_builder_spec.rb +76 -86
  68. data/spec/rley/syntax/grammar_spec.rb +40 -78
  69. data/spec/rley/syntax/grm_symbol_spec.rb +7 -7
  70. data/spec/rley/syntax/match_closest_spec.rb +8 -8
  71. data/spec/rley/syntax/non_terminal_spec.rb +25 -25
  72. data/spec/rley/syntax/production_spec.rb +33 -33
  73. data/spec/rley/syntax/symbol_seq_spec.rb +27 -27
  74. data/spec/rley/syntax/terminal_spec.rb +12 -11
  75. data/spec/support/base_tokenizer_spec.rb +9 -8
  76. metadata +2 -2
@@ -8,116 +8,106 @@ require_relative '../../../lib/rley/syntax/base_grammar_builder'
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
10
  describe BaseGrammarBuilder do
11
+ subject(:a_builder) { described_class.new }
12
+
11
13
  context 'Initialization without argument:' do
12
- it 'could be created without argument' do
13
- expect { BaseGrammarBuilder.new }.not_to raise_error
14
+ it 'is created without argument' do
15
+ expect { described_class.new }.not_to raise_error
14
16
  end
15
17
 
16
- it 'should have no grammar symbols at start' do
17
- expect(subject.symbols).to be_empty
18
+ it 'has no grammar symbols at start' do
19
+ expect(a_builder.symbols).to be_empty
18
20
  end
19
21
 
20
- it 'should have no productions at start' do
21
- expect(subject.productions).to be_empty
22
+ it 'has no productions at start' do
23
+ expect(a_builder.productions).to be_empty
22
24
  end
23
25
  end # context
24
26
 
25
27
  context 'Initialization with argument:' do
26
- it 'could be created with a block argument' do
28
+ it 'is created with a block argument' do
27
29
  expect do
28
- BaseGrammarBuilder.new { nil }
30
+ described_class.new { nil }
29
31
  end.not_to raise_error
30
32
  end
31
33
 
32
- it 'could have grammar symbols from block argument' do
33
- instance = BaseGrammarBuilder.new do
34
+ it 'has grammar symbols from block argument' do
35
+ instance = described_class.new do
34
36
  add_terminals('a', 'b', 'c')
35
37
  end
36
38
  expect(instance.symbols.size).to eq(3)
37
39
  end
38
40
 
39
- it 'should have no productions at start' do
40
- expect(subject.productions).to be_empty
41
+ it 'has no productions at start' do
42
+ expect(a_builder.productions).to be_empty
41
43
  end
42
44
  end # context
43
45
 
44
46
  context 'Adding symbols:' do
45
- it 'should build terminals from their names' do
46
- subject.add_terminals('a', 'b', 'c')
47
- expect(subject.symbols.size).to eq(3)
48
- expect(subject.symbols['a']).to be_kind_of(Terminal)
49
- expect(subject.symbols['a'].name).to eq('a')
50
- expect(subject.symbols['b']).to be_kind_of(Terminal)
51
- expect(subject.symbols['b'].name).to eq('b')
52
- expect(subject.symbols['c']).to be_kind_of(Terminal)
53
- expect(subject.symbols['c'].name).to eq('c')
54
- end
55
-
56
- it 'should accept already built terminals' do
57
- a = Terminal.new('a')
58
- b = Terminal.new('b')
59
- c = Terminal.new('c')
60
-
61
- subject.add_terminals(a, b, c)
62
- expect(subject.symbols.size).to eq(3)
63
- expect(subject.symbols['a']).to eq(a)
64
- expect(subject.symbols['b']).to eq(b)
65
- expect(subject.symbols['c']).to eq(c)
66
- end
67
-
68
- it 'should accept already built terminals' do
47
+ it 'builds terminals from their names' do
48
+ a_builder.add_terminals('a', 'b', 'c')
49
+ expect(a_builder.symbols.size).to eq(3)
50
+ expect(a_builder.symbols['a']).to be_a(Terminal)
51
+ expect(a_builder.symbols['a'].name).to eq('a')
52
+ expect(a_builder.symbols['b']).to be_a(Terminal)
53
+ expect(a_builder.symbols['b'].name).to eq('b')
54
+ expect(a_builder.symbols['c']).to be_a(Terminal)
55
+ expect(a_builder.symbols['c'].name).to eq('c')
56
+ end
57
+
58
+ it 'accepts already built terminals' do
69
59
  a = Terminal.new('a')
70
60
  b = Terminal.new('b')
71
61
  c = Terminal.new('c')
72
62
 
73
- subject.add_terminals(a, b, c)
74
- expect(subject.symbols.size).to eq(3)
75
- expect(subject.symbols['a']).to eq(a)
76
- expect(subject.symbols['b']).to eq(b)
77
- expect(subject.symbols['c']).to eq(c)
63
+ a_builder.add_terminals(a, b, c)
64
+ expect(a_builder.symbols.size).to eq(3)
65
+ expect(a_builder.symbols['a']).to eq(a)
66
+ expect(a_builder.symbols['b']).to eq(b)
67
+ expect(a_builder.symbols['c']).to eq(c)
78
68
  end
79
69
  end # context
80
70
 
81
71
  context 'Adding productions:' do
82
- subject do
83
- instance = BaseGrammarBuilder.new
72
+ subject(:a_builder) do
73
+ instance = described_class.new
84
74
  instance.add_terminals('a', 'b', 'c')
85
75
  instance
86
76
  end
87
77
 
88
- it 'should add a valid production' do
78
+ it 'adds a valid production' do
89
79
  # case of a rhs representation that consists of one name
90
- expect { subject.add_production('S' => 'A') }.not_to raise_error
91
- expect(subject.productions.size).to eq(1)
92
- new_prod = subject.productions[0]
93
- expect(new_prod.lhs).to eq(subject['S'])
94
- expect(new_prod.rhs[0]).to eq(subject['A'])
95
-
96
- subject.add_production('A' => %w[a A c])
97
- expect(subject.productions.size).to eq(2)
98
- new_prod = subject.productions.last
99
- expect(new_prod.lhs).to eq(subject['A'])
100
- expect_rhs = [subject['a'], subject['A'], subject['c']]
80
+ expect { a_builder.add_production('S' => 'A') }.not_to raise_error
81
+ expect(a_builder.productions.size).to eq(1)
82
+ new_prod = a_builder.productions[0]
83
+ expect(new_prod.lhs).to eq(a_builder['S'])
84
+ expect(new_prod.rhs[0]).to eq(a_builder['A'])
85
+
86
+ a_builder.add_production('A' => %w[a A c])
87
+ expect(a_builder.productions.size).to eq(2)
88
+ new_prod = a_builder.productions.last
89
+ expect(new_prod.lhs).to eq(a_builder['A'])
90
+ expect_rhs = [a_builder['a'], a_builder['A'], a_builder['c']]
101
91
  expect(new_prod.rhs.members).to eq(expect_rhs)
102
92
 
103
93
  # Try another syntax
104
- subject.add_production('A' => 'a A c')
105
- expect(subject.productions.size).to eq(3)
106
- new_prod = subject.productions.last
107
- expect(new_prod.lhs).to eq(subject['A'])
108
- expect_rhs = [subject['a'], subject['A'], subject['c']]
94
+ a_builder.add_production('A' => 'a A c')
95
+ expect(a_builder.productions.size).to eq(3)
96
+ new_prod = a_builder.productions.last
97
+ expect(new_prod.lhs).to eq(a_builder['A'])
98
+ expect_rhs = [a_builder['a'], a_builder['A'], a_builder['c']]
109
99
  expect(new_prod.rhs.members).to eq(expect_rhs)
110
100
 
111
101
  # BaseGrammarBuilder#rule is an alias of add_production
112
- subject.rule('A' => ['b'])
113
- expect(subject.productions.size).to eq(4)
114
- new_prod = subject.productions.last
115
- expect(new_prod.lhs).to eq(subject['A'])
116
- expect(new_prod.rhs[0]).to eq(subject['b'])
102
+ a_builder.rule('A' => ['b'])
103
+ expect(a_builder.productions.size).to eq(4)
104
+ new_prod = a_builder.productions.last
105
+ expect(new_prod.lhs).to eq(a_builder['A'])
106
+ expect(new_prod.rhs[0]).to eq(a_builder['b'])
117
107
  end
118
108
 
119
- it "should support Kleene's plus" do
120
- instance = BaseGrammarBuilder.new
109
+ it "supports Kleene's plus" do
110
+ instance = described_class.new
121
111
  instance.add_terminals('plus', 'minus', 'digit')
122
112
 
123
113
  instance.add_production('integer' => 'value')
@@ -136,8 +126,8 @@ module Rley # Open this namespace to avoid module qualifier prefixes
136
126
  end # context
137
127
 
138
128
  context 'Building grammar:' do
139
- subject do
140
- instance = BaseGrammarBuilder.new do
129
+ subject(:a_builder) do
130
+ instance = described_class.new do
141
131
  add_terminals('a', 'b', 'c')
142
132
  add_production('S' => ['A'])
143
133
  add_production('A' => %w[a A c])
@@ -147,47 +137,47 @@ module Rley # Open this namespace to avoid module qualifier prefixes
147
137
  instance
148
138
  end
149
139
 
150
- it 'should build a grammar' do
151
- expect(subject.grammar).to be_kind_of(Grammar)
152
- grm = subject.grammar
153
- expect(grm.rules).to eq(subject.productions)
140
+ it 'builds a grammar' do
141
+ expect(a_builder.grammar).to be_a(Grammar)
142
+ grm = a_builder.grammar
143
+ expect(grm.rules).to eq(a_builder.productions)
154
144
 
155
- # Invoking the factory method again should return
145
+ # Invoking the factory method again returns
156
146
  # the same grammar object
157
- second_time = subject.grammar
147
+ second_time = a_builder.grammar
158
148
  expect(second_time).to eq(grm)
159
149
  end
160
150
 
161
- it 'should complain in absence of symbols' do
162
- instance = BaseGrammarBuilder.new
151
+ it 'complains in absence of symbols' do
152
+ instance = described_class.new
163
153
  err = StandardError
164
154
  msg = 'No symbol found for grammar'
165
155
  expect { instance.grammar }.to raise_error(err, msg)
166
156
  end
167
157
 
168
- it 'should complain in absence of productions' do
169
- instance = BaseGrammarBuilder.new
158
+ it 'complains in absence of productions' do
159
+ instance = described_class.new
170
160
  instance.add_terminals('a', 'b', 'c')
171
161
  err = StandardError
172
162
  msg = 'No production found for grammar'
173
163
  expect { instance.grammar }.to raise_error(err, msg)
174
164
  end
175
165
 
176
- it 'should complain if one or more terminals are useless' do
166
+ it 'complains if one or more terminals are useless' do
177
167
  # Add one useless terminal symbol
178
- subject.add_terminals('d')
168
+ a_builder.add_terminals('d')
179
169
 
180
170
  err = StandardError
181
171
  msg = 'Useless terminal symbol(s): d.'
182
- expect { subject.grammar }.to raise_error(err, msg)
172
+ expect { a_builder.grammar }.to raise_error(err, msg)
183
173
 
184
174
  # Add another useless terminal
185
- subject.add_terminals('e')
175
+ a_builder.add_terminals('e')
186
176
  msg = 'Useless terminal symbol(s): d, e.'
187
- expect { subject.grammar }.to raise_error(err, msg)
177
+ expect { a_builder.grammar }.to raise_error(err, msg)
188
178
  end
189
179
 
190
- it 'should build a grammar with nullable nonterminals' do
180
+ it 'builds a grammar with nullable nonterminals' do
191
181
  # Grammar 4: A grammar with nullable nonterminal
192
182
  # based on example in "Parsing Techniques" book (D. Grune, C. Jabobs)
193
183
  # S ::= E.
@@ -201,7 +191,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
201
191
  t_star = Terminal.new('*')
202
192
  t_slash = Terminal.new('/')
203
193
 
204
- builder = BaseGrammarBuilder.new
194
+ builder = described_class.new
205
195
  builder.add_terminals(t_a, t_star, t_slash)
206
196
  builder.add_production('S' => 'E')
207
197
  builder.add_production('E' => %w[E Q F])
@@ -29,6 +29,11 @@ module Rley # Open this namespace to avoid module qualifier prefixes
29
29
  result
30
30
  end
31
31
 
32
+ subject(:a_grammar) do
33
+ productions = [prod_S, prod_A1, prod_A2]
34
+ described_class.new(productions)
35
+ end
36
+
32
37
  # Grammar 1: arithmetical expressions with integers
33
38
  let(:grm1_ops) do
34
39
  operators = %w[+ - * / ( )]
@@ -83,91 +88,50 @@ module Rley # Open this namespace to avoid module qualifier prefixes
83
88
  let(:prod_A2) { Production.new(nt_A, [b_]) }
84
89
  let(:prod_A3) { Production.new(nt_A, [c_, nt_C]) }
85
90
 
86
- =begin
87
- # Non-terminals that specify the lexicon of the language
88
- let(:noun) { NonTerminal.new('Noun') }
89
- let(:noun_list) { %w(flights breeze trip morning) }
90
- let(:verb) { NonTerminal.new('Verb') }
91
- let(:verb_list) { %w(is prefer like need want fly) }
92
- let(:adjective) { NonTerminal.new('Adjective') }
93
- let(:adjective_list) { %w(cheapest non-stop first latest other direct) }
94
- let(:pronoun) { NonTerminal.new('Pronoun') }
95
- let(:pronoun_list) { %w(me I you it) }
96
- let(:proper_noun) { NonTerminal.new('Proper_noun') }
97
- let(:proper_noun_list) do [ 'Alaska', 'Baltimore', 'Los Angeles',
98
- 'Chicago', 'United', 'American' ]
99
- end
100
- let(:determiner) { NonTerminal.new('Determiner') }
101
- let(:determiner_list) { %w(the a an this these that) }
102
- let(:preposition) { NonTerminal.new('Preposition') }
103
- let(:preposition_list) { %w(from to on near) }
104
- let(:conjunction) { NonTerminal.new('Conjunction') }
105
- let(:conjunction_list) { %w(and or but) }
106
-
107
- let(:noun_prods) { prods_for_list(noun, noun_list) }
108
- let(:verb_prods) { prods_for_list(verb, verb_list) }
109
- let(:adjective_prods) { prods_for_list(adjective, adjective_list) }
110
- let(:pronoun_prods) { prods_for_list(pronoun, pronoun_list) }
111
- let(:proper_pronoun_prods) do
112
- prods_for_list(proper_pronoun, proper_pronoun_list)
113
- end
114
- let(:determiner_prods) { prods_for_list(determiner, determiner_list) }
115
- let(:preposition_prods) { prods_for_list(preposition, preposition_list) }
116
- let(:conjunction_prods) { prods_for_list(conjunction, conjunction_list) }
117
-
118
- # Productions for the L0 language (from Jurafki & Martin)
119
- let(:nominal_prods) { Production}
120
- =end
121
-
122
- subject do
123
- productions = [prod_S, prod_A1, prod_A2]
124
- Grammar.new(productions)
125
- end
126
-
127
91
  context 'Initialization:' do
128
- it 'should be created with a list of productions' do
129
- expect { Grammar.new([prod_S, prod_A1, prod_A2]) }.not_to raise_error
92
+ it 'is created with a list of productions' do
93
+ expect { described_class.new([prod_S, prod_A1, prod_A2]) }.not_to raise_error
130
94
  end
131
95
 
132
- it 'should know its productions' do
133
- expect(subject.rules).to eq([prod_S, prod_A1, prod_A2])
96
+ it 'knows its productions' do
97
+ expect(a_grammar.rules).to eq([prod_S, prod_A1, prod_A2])
134
98
  end
135
99
 
136
- it 'should know its start symbol' do
137
- expect(subject.start_symbol).to eq(nt_S)
100
+ it 'knows its start symbol' do
101
+ expect(a_grammar.start_symbol).to eq(nt_S)
138
102
  end
139
103
 
140
- it 'should know all its symbols' do
141
- expect(subject.symbols).to eq([nt_S, nt_A, a_, c_, b_])
104
+ it 'knows all its symbols' do
105
+ expect(a_grammar.symbols).to eq([nt_S, nt_A, a_, c_, b_])
142
106
  end
143
107
 
144
- it 'should know all its non-terminal symbols' do
145
- expect(subject.non_terminals).to eq([nt_S, nt_A])
108
+ it 'knows all its non-terminal symbols' do
109
+ expect(a_grammar.non_terminals).to eq([nt_S, nt_A])
146
110
  end
147
111
 
148
- it 'should know its start production' do
149
- expect(subject.start_production).to eq(prod_S)
112
+ it 'knows its start production' do
113
+ expect(a_grammar.start_production).to eq(prod_S)
150
114
  end
151
115
  end # context
152
116
 
153
117
  context 'Provided services:' do
154
- it 'should retrieve its symbols from their name' do
155
- expect(subject.name2symbol['S']).to eq(nt_S)
156
- expect(subject.name2symbol['A']).to eq(nt_A)
157
- expect(subject.name2symbol['a']).to eq(a_)
158
- expect(subject.name2symbol['b']).to eq(b_)
159
- expect(subject.name2symbol['c']).to eq(c_)
118
+ it 'retrieves its symbols from their name' do
119
+ expect(a_grammar.name2symbol['S']).to eq(nt_S)
120
+ expect(a_grammar.name2symbol['A']).to eq(nt_A)
121
+ expect(a_grammar.name2symbol['a']).to eq(a_)
122
+ expect(a_grammar.name2symbol['b']).to eq(b_)
123
+ expect(a_grammar.name2symbol['c']).to eq(c_)
160
124
  end
161
125
 
162
- it 'should ensure that each production has a name' do
163
- subject.rules.each do |prod|
126
+ it 'ensures that each production has a name' do
127
+ a_grammar.rules.each do |prod|
164
128
  expect(prod.name).to match(Regexp.new("#{prod.lhs.name}_\\d$"))
165
129
  end
166
130
  end
167
131
  end # context
168
132
 
169
133
  context 'Grammar diagnosis:' do
170
- it 'should mark any non-terminal that has no production' do
134
+ it 'marks any non-terminal that has no production' do
171
135
  # S ::= A.
172
136
  # S ::= B.
173
137
  # A ::= "a" .
@@ -176,13 +140,13 @@ module Rley # Open this namespace to avoid module qualifier prefixes
176
140
  prod_S2 = Rley::Syntax::Production.new(nt_S, [nt_B])
177
141
  prod_A = Rley::Syntax::Production.new(nt_A, [a_])
178
142
  prod_B = Rley::Syntax::Production.new(nt_B, [nt_C, b_]) # C undefined
179
- instance = Grammar.new([prod_S1, prod_S2, prod_A, prod_B])
143
+ instance = described_class.new([prod_S1, prod_S2, prod_A, prod_B])
180
144
  undefineds = instance.non_terminals.select(&:undefined?)
181
145
  expect(undefineds.size).to eq(1)
182
146
  expect(undefineds.first).to eq(nt_C)
183
147
  end
184
148
 
185
- it 'should mark any non-terminal as generative or not' do
149
+ it 'marks any non-terminal as generative or not' do
186
150
  # S ::= A.
187
151
  # S ::= B.
188
152
  # A ::= "a" .
@@ -191,14 +155,14 @@ module Rley # Open this namespace to avoid module qualifier prefixes
191
155
  prod_S2 = Rley::Syntax::Production.new(nt_S, [nt_B])
192
156
  prod_A = Rley::Syntax::Production.new(nt_A, [a_])
193
157
  prod_B = Rley::Syntax::Production.new(nt_B, [nt_C, b_]) # C undefined
194
- instance = Grammar.new([prod_S1, prod_S2, prod_A, prod_B])
158
+ instance = described_class.new([prod_S1, prod_S2, prod_A, prod_B])
195
159
  partitioning = instance.non_terminals.partition(&:generative?)
196
160
  expect(partitioning[0].size).to eq(2)
197
161
  expect(partitioning[0]).to eq([nt_S, nt_A])
198
162
  expect(partitioning[1]).to eq([nt_B, nt_C])
199
163
  end
200
164
 
201
- it "should do a diagnosis even for 'loopy' grammars" do
165
+ it "does a diagnosis even for 'loopy' grammars" do
202
166
  # 'S' => 'A'
203
167
  # 'S' => 'B'
204
168
  # 'A' => 'a'
@@ -211,7 +175,7 @@ module Rley # Open this namespace to avoid module qualifier prefixes
211
175
  prd_B = Rley::Syntax::Production.new(nt_B, [nt_C])
212
176
  prd_C = Rley::Syntax::Production.new(nt_C, [nt_D])
213
177
  prd_D = Rley::Syntax::Production.new(nt_D, [nt_B])
214
- instance = Grammar.new([prd_S1, prd_S2, prd_A, prd_B, prd_C, prd_D])
178
+ instance = described_class.new([prd_S1, prd_S2, prd_A, prd_B, prd_C, prd_D])
215
179
  partitioning = instance.non_terminals.partition(&:generative?)
216
180
  expect(partitioning[0].size).to eq(2)
217
181
  expect(partitioning[0]).to eq([nt_S, nt_A])
@@ -223,8 +187,8 @@ module Rley # Open this namespace to avoid module qualifier prefixes
223
187
  end # context
224
188
 
225
189
  context 'Non-nullable grammar:' do
226
- it 'should mark all its nonterminals as non-nullable' do
227
- nonterms = subject.non_terminals
190
+ it 'marks all its nonterminals as non-nullable' do
191
+ nonterms = a_grammar.non_terminals
228
192
  nonterms.each do |nterm|
229
193
  expect(nterm).not_to be_nullable
230
194
  end
@@ -232,24 +196,22 @@ module Rley # Open this namespace to avoid module qualifier prefixes
232
196
  end # context
233
197
 
234
198
  context 'Nullable grammars:' do
235
- subject do
199
+ subject(:nullable_grammar) do
236
200
  prod_A4 = Production.new(nt_A, [])
237
201
  productions = [prod_S, prod_A1, prod_A2, prod_A4]
238
- Grammar.new(productions)
202
+ described_class.new(productions)
239
203
  end
240
204
 
241
- it 'should mark its nullable nonterminals' do
205
+ it 'marks its nullable nonterminals' do
242
206
  # In the default grammar, all nonterminals are nullable
243
- nonterms = subject.non_terminals
244
- nonterms.each do |nterm|
245
- expect(nterm).to be_nullable
246
- end
207
+ nonterms = nullable_grammar.non_terminals
208
+ expect(nonterms).to all(be_nullable)
247
209
  end
248
210
 
249
- it 'should mark its nullable productions' do
211
+ it 'marks its nullable productions' do
250
212
  # Given the above productions, here are our expectations:
251
213
  expectations = [true, false, false, true]
252
- actuals = subject.rules.map(&:nullable?)
214
+ actuals = nullable_grammar.rules.map(&:nullable?)
253
215
  expect(actuals).to eq(expectations)
254
216
  end
255
217
  end # context
@@ -8,22 +8,22 @@ require_relative '../../../lib/rley/syntax/grm_symbol'
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
10
  describe GrmSymbol do
11
+ subject(:grammar_symb) { described_class.new(sample_name) }
11
12
  let(:sample_name) { 'NP' }
12
- subject { GrmSymbol.new(sample_name) }
13
13
 
14
14
  context 'Initialization:' do
15
- it 'should be created with a name' do
16
- expect { GrmSymbol.new('NP') }.not_to raise_error
15
+ it 'is created with a name' do
16
+ expect { described_class.new('NP') }.not_to raise_error
17
17
  end
18
18
 
19
- it 'should know its name' do
20
- expect(subject.name).to eq(sample_name)
19
+ it 'knows its name' do
20
+ expect(grammar_symb.name).to eq(sample_name)
21
21
  end
22
22
  end # context
23
23
 
24
24
  context 'Provided services:' do
25
- it 'should give its text representation' do
26
- expect(subject.to_s).to eq(sample_name)
25
+ it 'gives its text representation' do
26
+ expect(grammar_symb.to_s).to eq(sample_name)
27
27
  end
28
28
  end # context
29
29
  end # describe
@@ -15,6 +15,8 @@ require_relative '../../../lib/rley/syntax/match_closest'
15
15
  module Rley # Open this namespace to avoid module qualifier prefixes
16
16
  module Syntax # Open this namespace to avoid module qualifier prefixes
17
17
  describe MatchClosest do
18
+ subject(:constraint) { described_class.new(prod.rhs.members, 4, 'IF') }
19
+
18
20
  # 'stmt' => 'IF boolean THEN stmt ELSE stmt'
19
21
  let(:boolean) { NonTerminal.new('boolean') }
20
22
  let(:stmt) { NonTerminal.new('stmt') }
@@ -24,19 +26,17 @@ module Rley # Open this namespace to avoid module qualifier prefixes
24
26
  let(:sequence) { [if_t, boolean, then_t, stmt, else_t, stmt] }
25
27
  let(:prod) { Production.new(stmt, sequence) }
26
28
 
27
- subject { MatchClosest.new(prod.rhs.members, 4, 'IF') }
28
-
29
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
30
+ it 'is created with an symbol seq., an indice and a name' do
31
+ expect { described_class.new(prod.rhs.members, 4, 'IF') }.not_to raise_error
32
32
  end
33
33
 
34
- it 'should know the index argument' do
35
- expect(subject.idx_symbol).to eq(4) # ELSE at position 4
34
+ it 'knows the index argument' do
35
+ expect(constraint.idx_symbol).to eq(4) # ELSE at position 4
36
36
  end
37
37
 
38
- it 'should know the name of preceding symbol to pair with' do
39
- expect(subject.closest_symb).to eq('IF')
38
+ it 'knows the name of preceding symbol to pair with' do
39
+ expect(constraint.closest_symb).to eq('IF')
40
40
  end
41
41
  end # context
42
42
  end # describe
@@ -8,47 +8,47 @@ require_relative '../../../lib/rley/syntax/non_terminal'
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
10
  describe NonTerminal do
11
+ subject(:a_nonterm) { described_class.new(sample_name) }
11
12
  let(:sample_name) { 'noun' }
12
- subject { NonTerminal.new(sample_name) }
13
13
 
14
14
  context 'Initialization:' do
15
- it 'should be created with a name' do
16
- expect { NonTerminal.new('noun') }.not_to raise_error
15
+ it 'is created with a name' do
16
+ expect { described_class.new('noun') }.not_to raise_error
17
17
  end
18
18
 
19
- it 'should know its name' do
20
- expect(subject.name).to eq(sample_name)
19
+ it 'knows its name' do
20
+ expect(a_nonterm.name).to eq(sample_name)
21
21
  end
22
22
 
23
- it 'should know that is a not a terminal' do
24
- expect(subject).not_to be_terminal
23
+ it 'knows that is a not a terminal' do
24
+ expect(a_nonterm).not_to be_terminal
25
25
  end
26
26
  end # context
27
27
 
28
28
 
29
29
  context 'Provided services:' do
30
- it 'should know whether it is nullable' do
31
- expect(subject.nullable?).to be_nil
32
- subject.nullable = true
33
- expect(subject).to be_nullable
34
- subject.nullable = false
35
- expect(subject).not_to be_nullable
30
+ it 'knows whether it is nullable' do
31
+ expect(a_nonterm.nullable?).to be_nil
32
+ a_nonterm.nullable = true
33
+ expect(a_nonterm).to be_nullable
34
+ a_nonterm.nullable = false
35
+ expect(a_nonterm).not_to be_nullable
36
36
  end
37
37
 
38
- it 'should know whether it is defined' do
39
- expect(subject.undefined?).to be_nil
40
- subject.undefined = true
41
- expect(subject).to be_undefined
42
- subject.undefined = false
43
- expect(subject).not_to be_undefined
38
+ it 'knows whether it is defined' do
39
+ expect(a_nonterm.undefined?).to be_nil
40
+ a_nonterm.undefined = true
41
+ expect(a_nonterm).to be_undefined
42
+ a_nonterm.undefined = false
43
+ expect(a_nonterm).not_to be_undefined
44
44
  end
45
45
 
46
- it 'should know whether it is generative' do
47
- expect(subject.generative?).to be_nil
48
- subject.generative = true
49
- expect(subject).to be_generative
50
- subject.generative = false
51
- expect(subject).not_to be_generative
46
+ it 'knows whether it is generative' do
47
+ expect(a_nonterm.generative?).to be_nil
48
+ a_nonterm.generative = true
49
+ expect(a_nonterm).to be_generative
50
+ a_nonterm.generative = false
51
+ expect(a_nonterm).not_to be_generative
52
52
  end
53
53
  end # context
54
54
  end # describe