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,59 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Rley # This module is used as a namespace
4
- module Parser # This module is used as a namespace
5
- # Helper class that keeps track of the parse states used
6
- # while a Parsing instance is constructing a parse tree.
7
- class ParseStateTracker
8
- # The index of the current state set
9
- attr_reader(:state_set_index)
10
-
11
- # The current parse state
12
- attr_reader(:parse_state)
13
-
14
- # The already processed states from current state set
15
- attr_reader(:processed_states)
16
-
17
- # Constructor. Refined variant of the inherited constructor.
18
- def initialize(aStateSetIndex)
19
- self.state_set_index = aStateSetIndex
20
- end
21
-
22
- # Write accessor. Sets the value of the state set index
23
- def state_set_index=(anIndex)
24
- @state_set_index = anIndex
25
- @processed_states = {}
26
- end
27
-
28
- # Write accessor. Set the given parse state as the current one.
29
- def parse_state=(aParseState)
30
- raise StandardError, 'Nil parse state' if aParseState.nil?
31
-
32
- @parse_state = aParseState
33
- processed_states[parse_state] = true
34
- end
35
-
36
- # Take the first provided state that wasn't processed yet.
37
- def select_state(theStates)
38
- a_state = theStates.find { |st| !processed_states.include?(st) }
39
- self.parse_state = a_state
40
- end
41
-
42
- # The dotted item for the current parse state.
43
- def curr_dotted_item()
44
- parse_state.dotted_rule
45
- end
46
-
47
- def symbol_on_left()
48
- return curr_dotted_item.prev_symbol
49
- end
50
-
51
- # Notification that one begins with the previous state set
52
- def to_prev_state_set()
53
- self.state_set_index = state_set_index - 1
54
- end
55
- end # class
56
- end # module
57
- end # module
58
-
59
- # End of file
@@ -1,101 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'forwardable' # Delegation
4
-
5
- module Rley # This module is used as a namespace
6
- module Parser # This module is used as a namespace
7
- class StateSet
8
- extend Forwardable
9
- def_delegators :states, :empty?, :size, :first, :each
10
-
11
- # The set of parse states
12
- attr_reader(:states)
13
-
14
- def initialize()
15
- @states = []
16
- end
17
-
18
- # Append the given state (if it isn't yet in the set)
19
- # to the list of states
20
- # @param aState [ParseState] the state to push.
21
- # @return [TrueClass/FalseClass] true when the state is really added
22
- def push_state(aState)
23
- if include?(aState)
24
- result = false
25
- else
26
- @states << aState
27
- result = true
28
- end
29
-
30
- return result
31
- end
32
-
33
- # The list of ParseState that expect the given symbol.
34
- # @param aSymbol [GrmSymbol] the expected symbol
35
- # (=on the right of the dot)
36
- def states_expecting(aSymbol)
37
- return states.select { |s| s.dotted_rule.next_symbol == aSymbol }
38
- end
39
-
40
- # The list of complete ParseState that have the given non-terminal
41
- # symbol as the lhs of their production.
42
- def states_rewriting(aNonTerm)
43
- return states.select do |s|
44
- (s.dotted_rule.production.lhs == aNonTerm) && s.complete?
45
- end
46
- end
47
-
48
- # The list of ParseState that involve the given production
49
- def states_for(aProduction)
50
- return states.select { |s| s.dotted_rule.production == aProduction }
51
- end
52
-
53
- # Retrieve the parse state that is the predecessor of the given one.
54
- def predecessor_state(aPState)
55
- dotted_rule = aPState.dotted_rule
56
- raise StandardError, aPState.to_s unless dotted_rule.prev_position
57
-
58
- candidate = states.find { |s| s.precedes?(aPState) }
59
- return candidate
60
- end
61
-
62
- # The list of distinct expected terminal symbols. An expected symbol
63
- # is on the left of a dot in a parse state of the parse set.
64
- def expected_terminals()
65
- expecting_terminals = states.select do |s|
66
- s.dotted_rule.next_symbol.kind_of?(Rley::Syntax::Terminal)
67
- end
68
-
69
- terminals = expecting_terminals.map { |s| s.dotted_rule.next_symbol }
70
- return terminals.uniq
71
- end
72
-
73
- # Return an Array of Arrays of ambiguous parse states.
74
- def ambiguities()
75
- complete_states = states.select(&:complete?)
76
- return [] if complete_states.size <= 1
77
-
78
- # Group parse state by lhs symbol and origin
79
- groupings = complete_states.group_by do |st|
80
- st.dotted_rule.lhs.object_id.to_s
81
- end
82
-
83
- # Retain the groups having more than one element.
84
- ambiguous_groups = []
85
- groupings.each_value do |a_group|
86
- ambiguous_groups << a_group if a_group.size > 1
87
- end
88
-
89
- return ambiguous_groups
90
- end
91
-
92
- private
93
-
94
- def include?(aState)
95
- # TODO: make it better than linear search
96
- return states.include?(aState)
97
- end
98
- end # class
99
- end # module
100
- end # module
101
- # End of file
@@ -1,125 +0,0 @@
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/production'
8
- require_relative '../../../lib/rley/base/dotted_item'
9
-
10
- # Load the class under test
11
- require_relative '../../../lib/rley/parser/parse_state'
12
-
13
- module Rley # Open this namespace to avoid module qualifier prefixes
14
- module Parser # Open this namespace to avoid module qualifier prefixes
15
- describe ParseState do
16
- let(:t_a) { Syntax::Terminal.new('A') }
17
- let(:t_b) { Syntax::Terminal.new('B') }
18
- let(:t_c) { Syntax::Terminal.new('C') }
19
- let(:nt_sentence) { Syntax::NonTerminal.new('sentence') }
20
-
21
- let(:sample_prod) do
22
- Syntax::Production.new(nt_sentence, [t_a, t_b, t_c])
23
- end
24
-
25
- let(:other_prod) do
26
- Syntax::Production.new(nt_sentence, [t_a])
27
- end
28
-
29
- let(:empty_prod) do
30
- Syntax::Production.new(nt_sentence, [])
31
- end
32
-
33
- let(:origin_val) { 3 }
34
- let(:dotted_rule) { Base::DottedItem.new(sample_prod, 2) }
35
- let(:other_dotted_rule) { double('mock-dotted-item') }
36
-
37
- # Default instantiation rule
38
- subject { ParseState.new(dotted_rule, origin_val) }
39
-
40
- context 'Initialization:' do
41
- it 'should be created with a dotted item and a origin position' do
42
- args = [dotted_rule, origin_val]
43
- expect { ParseState.new(*args) }.not_to raise_error
44
- end
45
-
46
- it 'should complain when the dotted rule is nil' do
47
- err = StandardError
48
- msg = 'Dotted item cannot be nil'
49
- expect { ParseState.new(nil, 2) }.to raise_error(err, msg)
50
- end
51
-
52
- it 'should know the related dotted rule' do
53
- expect(subject.dotted_rule).to eq(dotted_rule)
54
- end
55
-
56
- it 'should know the origin value' do
57
- expect(subject.origin).to eq(origin_val)
58
- end
59
- end # context
60
-
61
- context 'Provided services:' do
62
- def new_parse_state(aProd, aRank, aVal)
63
- item = Base::DottedItem.new(aProd, aRank)
64
- ParseState.new(item, aVal)
65
- end
66
-
67
- it 'should compare with itself' do
68
- synonym = subject # Fool Rubocop
69
- expect(subject == synonym).to eq(true)
70
- end
71
-
72
- it 'should compare with another' do
73
- equal = ParseState.new(dotted_rule, origin_val)
74
- expect(subject == equal).to eq(true)
75
-
76
- # Same dotted_rule, different origin
77
- diff_origin = ParseState.new(dotted_rule, 2)
78
- expect(subject == diff_origin).to eq(false)
79
-
80
- # Different dotted item, same origin
81
- diff_rule = ParseState.new(other_dotted_rule, 3)
82
- expect(subject == diff_rule).to eq(false)
83
- end
84
-
85
- it 'should know if the parsing is at the start of the production' do
86
- expect(subject).not_to be_predicted
87
- at_start = Base::DottedItem.new(sample_prod, 0)
88
-
89
- instance = ParseState.new(at_start, 0)
90
- expect(instance).to be_predicted
91
- end
92
-
93
- it 'should know if the parsing reached the end of the production' do
94
- expect(subject).not_to be_complete
95
- at_end = Base::DottedItem.new(sample_prod, 3)
96
-
97
- instance = ParseState.new(at_end, 2)
98
- expect(instance).to be_complete
99
- end
100
-
101
- it 'should know the next expected symbol' do
102
- expect(subject.next_symbol).to eq(t_c)
103
- end
104
-
105
- it 'should know whether another instance follows this one' do
106
- expect(subject.precedes?(subject)).to eq(false)
107
- state1 = new_parse_state(sample_prod, 1, origin_val)
108
- expect(state1.precedes?(subject)).to eq(true)
109
- state0 = new_parse_state(sample_prod, 0, origin_val)
110
- expect(state0.precedes?(state1)).to eq(true)
111
- expect(state0.precedes?(subject)).to eq(false)
112
- state3 = new_parse_state(sample_prod, 3, origin_val)
113
- expect(state3.precedes?(state0)).to eq(false)
114
- end
115
-
116
- it 'should know its text representation' do
117
- expected = 'sentence => A B . C | 3'
118
- expect(subject.to_s).to eq(expected)
119
- end
120
- end # context
121
- end # describe
122
- end # module
123
- end # module
124
-
125
- # End of file
@@ -1,200 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../../spec_helper'
4
- require 'stringio'
5
-
6
- require_relative '../../../lib/rley/syntax/terminal'
7
- require_relative '../../../lib/rley/syntax/non_terminal'
8
- require_relative '../../../lib/rley/syntax/production'
9
- require_relative '../../../lib/rley/base/dotted_item'
10
- require_relative '../../../lib/rley/parser/parse_state'
11
- require_relative '../../../lib/rley/lexical/token'
12
-
13
- # Load the class under test
14
- require_relative '../../../lib/rley/parser/parse_tracer'
15
-
16
- module Rley # Open this namespace to avoid module qualifier prefixes
17
- module Parser # Open this namespace to avoid module qualifier prefixes
18
- describe ParseTracer do
19
- let(:output) { StringIO.new(+'', 'w') }
20
- let(:tpos) { Lexical::Position.new(3, 4) }
21
-
22
- let(:token_seq) do
23
- literals = %w[I saw John with a dog]
24
- literals.map do |lexeme|
25
- Lexical::Token.new(lexeme, double('fake-terminal'), tpos)
26
- end
27
- end
28
-
29
- subject { ParseTracer.new(1, output, token_seq) }
30
-
31
- context 'Creation & initialization:' do
32
- it 'should accept trace level 0' do
33
- expect { ParseTracer.new(0, output, token_seq) }.not_to raise_error
34
- expect(output.string).to eq('')
35
- end
36
-
37
-
38
- it 'should accept trace level 1' do
39
- expect { ParseTracer.new(1, output, token_seq) }.not_to raise_error
40
- expectations = <<-SNIPPET
41
- ['I', 'saw', 'John', 'with', 'a', 'dog']
42
- |. I . saw . John . with . a . dog .|
43
- SNIPPET
44
- expect(output.string).to eq(expectations)
45
- end
46
-
47
- it 'should accept trace level 2' do
48
- expect { ParseTracer.new(2, output, token_seq) }.not_to raise_error
49
- expectations = <<-SNIPPET
50
- ['I', 'saw', 'John', 'with', 'a', 'dog']
51
- |. I . saw . John . with . a . dog .|
52
- SNIPPET
53
- expect(output.string).to eq(expectations)
54
- end
55
-
56
- it 'should know the trace level' do
57
- expect(subject.level).to eq(1)
58
- end
59
-
60
- it 'should know the output stream' do
61
- expect(subject.ostream).to eq(output)
62
- end
63
- end # context
64
-
65
- context 'Provided services:' do
66
- let(:t_a) { Syntax::Terminal.new('A') }
67
- let(:t_b) { Syntax::Terminal.new('B') }
68
- let(:t_c) { Syntax::Terminal.new('C') }
69
- let(:nt_sentence) { Syntax::NonTerminal.new('sentence') }
70
-
71
- let(:sample_prod) do
72
- Syntax::Production.new(nt_sentence, [t_a, t_b, t_c])
73
- end
74
-
75
- let(:origin_val) { 3 }
76
- let(:dotted_rule) { Base::DottedItem.new(sample_prod, 2) }
77
- let(:complete_rule) { Base::DottedItem.new(sample_prod, 3) }
78
- let(:sample_parse_state) { ParseState.new(dotted_rule, origin_val) }
79
-
80
- # Factory method.
81
- def parse_state(origin, aDottedRule)
82
- ParseState.new(aDottedRule, origin)
83
- end
84
-
85
- it 'should render a scanning step' do
86
- # Case: token at the beginning
87
- subject.ostream.string = +''
88
- subject.trace_scanning(1, parse_state(0, dotted_rule))
89
- expectations = <<-SNIPPET
90
- |[------] . . . . .| [0:1] sentence => A B . C
91
- SNIPPET
92
- expect(output.string).to eq(expectations)
93
-
94
- # Case: token in the middle
95
- subject.ostream.string = +''
96
- subject.trace_scanning(4, sample_parse_state)
97
- expectations = <<-SNIPPET
98
- |. . . [------] . .| [3:4] sentence => A B . C
99
- SNIPPET
100
- expect(output.string).to eq(expectations)
101
-
102
- # Case: token at the end
103
- subject.ostream.string = +''
104
- subject.trace_scanning(6, parse_state(5, dotted_rule))
105
- expectations = <<-SNIPPET
106
- |. . . . . [------]| [5:6] sentence => A B . C
107
- SNIPPET
108
- expect(output.string).to eq(expectations)
109
- end
110
-
111
-
112
- it 'should render a prediction step' do
113
- # Case: initial stateset
114
- subject.ostream.string = +''
115
- subject.trace_prediction(0, parse_state(0, dotted_rule))
116
- expectations = <<-SNIPPET
117
- |> . . . . . .| [0:0] sentence => A B . C
118
- SNIPPET
119
- expect(output.string).to eq(expectations)
120
-
121
- # Case: stateset in the middle
122
- subject.ostream.string = +''
123
- subject.trace_prediction(3, sample_parse_state)
124
- expectations = <<-SNIPPET
125
- |. . . > . . .| [3:3] sentence => A B . C
126
- SNIPPET
127
- expect(output.string).to eq(expectations)
128
-
129
- # Case: final stateset
130
- subject.ostream.string = +''
131
- subject.trace_prediction(6, parse_state(6, dotted_rule))
132
- expectations = <<-SNIPPET
133
- |. . . . . . >| [6:6] sentence => A B . C
134
- SNIPPET
135
- expect(output.string).to eq(expectations)
136
- end
137
-
138
- it 'should render a completion step' do
139
- # Case: full parse completed
140
- subject.ostream.string = +''
141
- subject.trace_completion(6, parse_state(0, complete_rule))
142
- expectations = <<-SNIPPET
143
- |[=========================================]| [0:6] sentence => A B C .
144
- SNIPPET
145
- expect(output.string).to eq(expectations)
146
-
147
- # Case: step at the start (complete)
148
- subject.ostream.string = +''
149
- subject.trace_completion(1, parse_state(0, complete_rule))
150
- expectations = <<-SNIPPET
151
- |[------] . . . . .| [0:1] sentence => A B C .
152
- SNIPPET
153
- expect(output.string).to eq(expectations)
154
-
155
- # Case: step at the start (not complete)
156
- subject.ostream.string = +''
157
- subject.trace_completion(1, parse_state(0, dotted_rule))
158
- expectations = <<-SNIPPET
159
- |[------> . . . . .| [0:1] sentence => A B . C
160
- SNIPPET
161
- expect(output.string).to eq(expectations)
162
-
163
- # Case: step at the middle (complete)
164
- subject.ostream.string = +''
165
- subject.trace_completion(4, parse_state(2, complete_rule))
166
- expectations = <<-SNIPPET
167
- |. . [-------------] . .| [2:4] sentence => A B C .
168
- SNIPPET
169
- expect(output.string).to eq(expectations)
170
-
171
- # Case: step at the middle (not complete)
172
- subject.ostream.string = +''
173
- subject.trace_completion(4, parse_state(2, dotted_rule))
174
- expectations = <<-SNIPPET
175
- |. . [-------------> . .| [2:4] sentence => A B . C
176
- SNIPPET
177
- expect(output.string).to eq(expectations)
178
-
179
- # Case: step at the end (complete)
180
- subject.ostream.string = +''
181
- subject.trace_completion(6, parse_state(3, complete_rule))
182
- expectations = <<-SNIPPET
183
- |. . . [--------------------]| [3:6] sentence => A B C .
184
- SNIPPET
185
- expect(output.string).to eq(expectations)
186
-
187
- # Case: step at the end (not complete)
188
- subject.ostream.string = +''
189
- subject.trace_completion(6, parse_state(3, dotted_rule))
190
- expectations = <<-SNIPPET
191
- |. . . [-------------------->| [3:6] sentence => A B . C
192
- SNIPPET
193
- expect(output.string).to eq(expectations)
194
- end
195
- end # context
196
- end # describe
197
- end # module
198
- end # module
199
-
200
- # End of file