rley 0.7.06 → 0.8.01
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +362 -62
- data/.travis.yml +6 -6
- data/CHANGELOG.md +20 -4
- data/LICENSE.txt +1 -1
- data/README.md +7 -7
- data/examples/NLP/engtagger.rb +193 -190
- data/examples/NLP/nano_eng/nano_en_demo.rb +7 -11
- data/examples/NLP/nano_eng/nano_grammar.rb +21 -21
- data/examples/NLP/pico_en_demo.rb +2 -2
- data/examples/data_formats/JSON/cli_options.rb +1 -1
- data/examples/data_formats/JSON/json_ast_builder.rb +21 -27
- data/examples/data_formats/JSON/json_ast_nodes.rb +12 -21
- data/examples/data_formats/JSON/json_demo.rb +1 -2
- data/examples/data_formats/JSON/json_grammar.rb +13 -13
- data/examples/data_formats/JSON/json_lexer.rb +8 -8
- data/examples/data_formats/JSON/json_minifier.rb +1 -1
- data/examples/general/calc_iter1/calc_ast_builder.rb +13 -10
- data/examples/general/calc_iter1/calc_ast_nodes.rb +23 -37
- data/examples/general/calc_iter1/calc_grammar.rb +7 -6
- data/examples/general/calc_iter1/calc_lexer.rb +6 -4
- data/examples/general/calc_iter1/spec/calculator_spec.rb +5 -5
- data/examples/general/calc_iter2/calc_ast_builder.rb +5 -3
- data/examples/general/calc_iter2/calc_ast_nodes.rb +27 -43
- data/examples/general/calc_iter2/calc_grammar.rb +12 -12
- data/examples/general/calc_iter2/calc_lexer.rb +11 -10
- data/examples/general/calc_iter2/spec/calculator_spec.rb +26 -26
- data/examples/general/left.rb +2 -2
- data/examples/general/right.rb +2 -2
- data/lib/rley.rb +1 -1
- data/lib/rley/base/dotted_item.rb +28 -31
- data/lib/rley/base/grm_items_builder.rb +6 -0
- data/lib/rley/constants.rb +2 -2
- data/lib/rley/engine.rb +22 -25
- data/lib/rley/formatter/asciitree.rb +3 -3
- data/lib/rley/formatter/bracket_notation.rb +1 -8
- data/lib/rley/formatter/debug.rb +6 -6
- data/lib/rley/formatter/json.rb +2 -2
- data/lib/rley/gfg/call_edge.rb +1 -1
- data/lib/rley/gfg/edge.rb +5 -5
- data/lib/rley/gfg/end_vertex.rb +2 -6
- data/lib/rley/gfg/epsilon_edge.rb +1 -5
- data/lib/rley/gfg/grm_flow_graph.rb +27 -23
- data/lib/rley/gfg/item_vertex.rb +10 -10
- data/lib/rley/gfg/non_terminal_vertex.rb +4 -4
- data/lib/rley/gfg/scan_edge.rb +1 -1
- data/lib/rley/gfg/shortcut_edge.rb +2 -2
- data/lib/rley/gfg/start_vertex.rb +4 -8
- data/lib/rley/gfg/vertex.rb +43 -39
- data/lib/rley/interface.rb +16 -0
- data/lib/rley/lexical/token_range.rb +6 -6
- data/lib/rley/notation/all_notation_nodes.rb +2 -0
- data/lib/rley/notation/ast_builder.rb +191 -0
- data/lib/rley/notation/ast_node.rb +44 -0
- data/lib/rley/notation/ast_visitor.rb +113 -0
- data/lib/rley/notation/grammar.rb +49 -0
- data/lib/rley/notation/grammar_builder.rb +504 -0
- data/lib/rley/notation/grouping_node.rb +23 -0
- data/lib/rley/notation/parser.rb +56 -0
- data/lib/rley/notation/sequence_node.rb +35 -0
- data/lib/rley/notation/symbol_node.rb +29 -0
- data/lib/rley/notation/tokenizer.rb +192 -0
- data/lib/rley/parse_forest_visitor.rb +5 -5
- data/lib/rley/parse_rep/ast_base_builder.rb +48 -11
- data/lib/rley/parse_rep/cst_builder.rb +5 -6
- data/lib/rley/parse_rep/parse_forest_builder.rb +22 -18
- data/lib/rley/parse_rep/parse_forest_factory.rb +3 -3
- data/lib/rley/parse_rep/parse_rep_creator.rb +14 -16
- data/lib/rley/parse_rep/parse_tree_builder.rb +4 -4
- data/lib/rley/parse_rep/parse_tree_factory.rb +27 -27
- data/lib/rley/parse_tree_visitor.rb +1 -1
- data/lib/rley/parser/error_reason.rb +4 -5
- data/lib/rley/parser/gfg_chart.rb +118 -26
- data/lib/rley/parser/gfg_parsing.rb +22 -33
- data/lib/rley/parser/parse_entry.rb +25 -31
- data/lib/rley/parser/parse_entry_set.rb +19 -16
- data/lib/rley/parser/parse_entry_tracker.rb +4 -4
- data/lib/rley/parser/parse_tracer.rb +13 -13
- data/lib/rley/parser/parse_walker_factory.rb +23 -28
- data/lib/rley/ptree/non_terminal_node.rb +7 -5
- data/lib/rley/ptree/parse_tree.rb +3 -3
- data/lib/rley/ptree/parse_tree_node.rb +5 -5
- data/lib/rley/ptree/terminal_node.rb +7 -7
- data/lib/rley/rley_error.rb +12 -12
- data/lib/rley/sppf/alternative_node.rb +6 -6
- data/lib/rley/sppf/composite_node.rb +7 -7
- data/lib/rley/sppf/epsilon_node.rb +3 -3
- data/lib/rley/sppf/leaf_node.rb +3 -3
- data/lib/rley/sppf/parse_forest.rb +16 -16
- data/lib/rley/sppf/sppf_node.rb +7 -8
- data/lib/rley/sppf/token_node.rb +3 -3
- data/lib/rley/syntax/{grammar_builder.rb → base_grammar_builder.rb} +61 -23
- data/lib/rley/syntax/grammar.rb +5 -5
- data/lib/rley/syntax/grm_symbol.rb +7 -7
- data/lib/rley/syntax/match_closest.rb +43 -0
- data/lib/rley/syntax/non_terminal.rb +9 -15
- data/lib/rley/syntax/production.rb +16 -10
- data/lib/rley/syntax/symbol_seq.rb +7 -9
- data/lib/rley/syntax/terminal.rb +4 -5
- data/lib/rley/syntax/verbatim_symbol.rb +3 -3
- data/lib/support/base_tokenizer.rb +19 -18
- data/spec/rley/base/dotted_item_spec.rb +2 -2
- data/spec/rley/engine_spec.rb +23 -21
- data/spec/rley/formatter/asciitree_spec.rb +7 -7
- data/spec/rley/formatter/bracket_notation_spec.rb +13 -13
- data/spec/rley/formatter/json_spec.rb +1 -1
- data/spec/rley/gfg/end_vertex_spec.rb +5 -5
- data/spec/rley/gfg/grm_flow_graph_spec.rb +2 -2
- data/spec/rley/gfg/item_vertex_spec.rb +10 -10
- data/spec/rley/gfg/non_terminal_vertex_spec.rb +3 -3
- data/spec/rley/gfg/shortcut_edge_spec.rb +1 -1
- data/spec/rley/gfg/start_vertex_spec.rb +5 -5
- data/spec/rley/gfg/vertex_spec.rb +3 -3
- data/spec/rley/lexical/token_range_spec.rb +16 -16
- data/spec/rley/lexical/token_spec.rb +2 -2
- data/spec/rley/notation/grammar_builder_spec.rb +302 -0
- data/spec/rley/notation/parser_spec.rb +184 -0
- data/spec/rley/notation/tokenizer_spec.rb +370 -0
- data/spec/rley/parse_forest_visitor_spec.rb +165 -163
- data/spec/rley/parse_rep/ambiguous_parse_spec.rb +44 -44
- data/spec/rley/parse_rep/ast_builder_spec.rb +6 -7
- data/spec/rley/parse_rep/cst_builder_spec.rb +5 -5
- data/spec/rley/parse_rep/groucho_spec.rb +24 -26
- data/spec/rley/parse_rep/parse_forest_builder_spec.rb +27 -27
- data/spec/rley/parse_rep/parse_forest_factory_spec.rb +8 -8
- data/spec/rley/parse_rep/parse_tree_factory_spec.rb +3 -3
- data/spec/rley/parse_tree_visitor_spec.rb +10 -8
- data/spec/rley/parser/dangling_else_spec.rb +445 -0
- data/spec/rley/parser/error_reason_spec.rb +6 -6
- data/spec/rley/parser/gfg_earley_parser_spec.rb +120 -12
- data/spec/rley/parser/gfg_parsing_spec.rb +6 -13
- data/spec/rley/parser/parse_entry_spec.rb +19 -19
- data/spec/rley/parser/parse_walker_factory_spec.rb +10 -10
- data/spec/rley/ptree/non_terminal_node_spec.rb +5 -3
- data/spec/rley/ptree/parse_tree_node_spec.rb +4 -4
- data/spec/rley/ptree/terminal_node_spec.rb +6 -6
- data/spec/rley/sppf/alternative_node_spec.rb +6 -6
- data/spec/rley/sppf/non_terminal_node_spec.rb +3 -3
- data/spec/rley/sppf/token_node_spec.rb +4 -4
- data/spec/rley/support/ambiguous_grammar_helper.rb +4 -5
- data/spec/rley/support/grammar_abc_helper.rb +3 -5
- data/spec/rley/support/grammar_ambig01_helper.rb +5 -6
- data/spec/rley/support/grammar_arr_int_helper.rb +5 -6
- data/spec/rley/support/grammar_b_expr_helper.rb +5 -6
- data/spec/rley/support/grammar_int_seq_helper.rb +51 -0
- data/spec/rley/support/grammar_l0_helper.rb +14 -17
- data/spec/rley/support/grammar_pb_helper.rb +8 -7
- data/spec/rley/support/grammar_sppf_helper.rb +3 -3
- data/spec/rley/syntax/{grammar_builder_spec.rb → base_grammar_builder_spec.rb} +35 -16
- data/spec/rley/syntax/grammar_spec.rb +6 -6
- data/spec/rley/syntax/grm_symbol_spec.rb +1 -1
- data/spec/rley/syntax/match_closest_spec.rb +46 -0
- data/spec/rley/syntax/non_terminal_spec.rb +8 -8
- data/spec/rley/syntax/production_spec.rb +17 -13
- data/spec/rley/syntax/symbol_seq_spec.rb +2 -2
- data/spec/rley/syntax/terminal_spec.rb +5 -5
- data/spec/rley/syntax/verbatim_symbol_spec.rb +1 -1
- data/spec/spec_helper.rb +0 -12
- data/spec/support/base_tokenizer_spec.rb +7 -2
- metadata +48 -74
- data/.simplecov +0 -7
- data/lib/rley/parser/parse_state.rb +0 -83
- data/lib/rley/parser/parse_state_tracker.rb +0 -59
- data/lib/rley/parser/state_set.rb +0 -101
- data/spec/rley/parser/parse_state_spec.rb +0 -125
- data/spec/rley/parser/parse_tracer_spec.rb +0 -200
- 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/
|
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::
|
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
|
-
|
32
|
-
|
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/
|
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::
|
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/
|
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
|
10
|
+
describe BaseGrammarBuilder do
|
11
11
|
context 'Initialization without argument:' do
|
12
12
|
it 'could be created without argument' do
|
13
|
-
expect {
|
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
|
-
|
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 =
|
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 =
|
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
|
-
#
|
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 =
|
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 =
|
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 =
|
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 =
|
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)
|