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.
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