rley 0.7.06 → 0.8.01
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.
- 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)
|