rley 0.3.04 → 0.3.05

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +7 -3
  3. data/CHANGELOG.md +3 -0
  4. data/Rakefile +30 -30
  5. data/examples/parsers/parsing_L0.rb +1 -1
  6. data/examples/parsers/parsing_L1.rb +1 -1
  7. data/examples/parsers/parsing_abc.rb +1 -1
  8. data/examples/parsers/parsing_ambig.rb +1 -1
  9. data/examples/parsers/parsing_another.rb +1 -1
  10. data/examples/parsers/parsing_b_expr.rb +1 -1
  11. data/examples/parsers/parsing_err_expr.rb +1 -1
  12. data/examples/parsers/parsing_groucho.rb +1 -1
  13. data/examples/parsers/parsing_right_recursive.rb +1 -1
  14. data/examples/parsers/parsing_tricky.rb +1 -1
  15. data/lib/rley/constants.rb +2 -2
  16. data/lib/rley/formatter/base_formatter.rb +0 -2
  17. data/lib/rley/formatter/debug.rb +0 -2
  18. data/lib/rley/formatter/json.rb +1 -3
  19. data/lib/rley/gfg/call_edge.rb +31 -30
  20. data/lib/rley/gfg/edge.rb +22 -23
  21. data/lib/rley/gfg/end_vertex.rb +22 -24
  22. data/lib/rley/gfg/epsilon_edge.rb +20 -21
  23. data/lib/rley/gfg/grm_flow_graph.rb +39 -39
  24. data/lib/rley/gfg/item_vertex.rb +16 -17
  25. data/lib/rley/gfg/non_terminal_vertex.rb +3 -4
  26. data/lib/rley/gfg/return_edge.rb +32 -31
  27. data/lib/rley/gfg/scan_edge.rb +25 -26
  28. data/lib/rley/gfg/shortcut_edge.rb +25 -26
  29. data/lib/rley/gfg/start_vertex.rb +0 -2
  30. data/lib/rley/gfg/vertex.rb +8 -8
  31. data/lib/rley/parse_forest_visitor.rb +113 -115
  32. data/lib/rley/parse_tree_visitor.rb +0 -2
  33. data/lib/rley/parser/base_parser.rb +27 -27
  34. data/lib/rley/parser/chart.rb +14 -14
  35. data/lib/rley/parser/dotted_item.rb +33 -33
  36. data/lib/rley/parser/earley_parser.rb +6 -6
  37. data/lib/rley/parser/gfg_chart.rb +8 -15
  38. data/lib/rley/parser/gfg_earley_parser.rb +15 -13
  39. data/lib/rley/parser/gfg_parsing.rb +26 -22
  40. data/lib/rley/parser/grm_items_builder.rb +3 -2
  41. data/lib/rley/parser/parse_entry.rb +3 -9
  42. data/lib/rley/parser/parse_entry_set.rb +14 -19
  43. data/lib/rley/parser/parse_entry_tracker.rb +56 -56
  44. data/lib/rley/parser/parse_forest_builder.rb +215 -214
  45. data/lib/rley/parser/parse_forest_factory.rb +57 -56
  46. data/lib/rley/parser/parse_state.rb +8 -11
  47. data/lib/rley/parser/parse_state_tracker.rb +56 -56
  48. data/lib/rley/parser/parse_tracer.rb +3 -3
  49. data/lib/rley/parser/parse_tree_builder.rb +10 -10
  50. data/lib/rley/parser/parse_walker_factory.rb +30 -33
  51. data/lib/rley/parser/parsing.rb +8 -8
  52. data/lib/rley/parser/state_set.rb +23 -26
  53. data/lib/rley/ptree/non_terminal_node.rb +1 -1
  54. data/lib/rley/ptree/token_range.rb +2 -2
  55. data/lib/rley/sppf/alternative_node.rb +32 -34
  56. data/lib/rley/sppf/composite_node.rb +27 -27
  57. data/lib/rley/sppf/epsilon_node.rb +26 -27
  58. data/lib/rley/sppf/leaf_node.rb +11 -12
  59. data/lib/rley/sppf/non_terminal_node.rb +37 -38
  60. data/lib/rley/sppf/sppf_node.rb +1 -1
  61. data/lib/rley/sppf/token_node.rb +29 -29
  62. data/lib/rley/syntax/grammar.rb +1 -3
  63. data/lib/rley/syntax/grammar_builder.rb +8 -8
  64. data/lib/rley/syntax/non_terminal.rb +2 -4
  65. data/lib/rley/syntax/production.rb +3 -3
  66. data/lib/rley/syntax/symbol_seq.rb +1 -1
  67. data/spec/rley/gfg/call_edge_spec.rb +50 -51
  68. data/spec/rley/gfg/edge_spec.rb +33 -33
  69. data/spec/rley/gfg/end_vertex_spec.rb +26 -27
  70. data/spec/rley/gfg/epsilon_edge_spec.rb +25 -25
  71. data/spec/rley/gfg/grm_flow_graph_spec.rb +1 -1
  72. data/spec/rley/gfg/item_vertex_spec.rb +3 -4
  73. data/spec/rley/gfg/return_edge_spec.rb +51 -51
  74. data/spec/rley/gfg/scan_edge_spec.rb +32 -30
  75. data/spec/rley/gfg/shortcut_edge_spec.rb +1 -1
  76. data/spec/rley/gfg/vertex_spec.rb +3 -3
  77. data/spec/rley/parse_forest_visitor_spec.rb +239 -238
  78. data/spec/rley/parser/dotted_item_spec.rb +1 -1
  79. data/spec/rley/parser/earley_parser_spec.rb +16 -16
  80. data/spec/rley/parser/gfg_earley_parser_spec.rb +30 -31
  81. data/spec/rley/parser/gfg_parsing_spec.rb +11 -10
  82. data/spec/rley/parser/grm_items_builder_spec.rb +2 -2
  83. data/spec/rley/parser/parse_entry_set_spec.rb +4 -4
  84. data/spec/rley/parser/parse_entry_spec.rb +0 -2
  85. data/spec/rley/parser/parse_forest_builder_spec.rb +82 -57
  86. data/spec/rley/parser/parse_forest_factory_spec.rb +84 -82
  87. data/spec/rley/parser/parse_walker_factory_spec.rb +10 -9
  88. data/spec/rley/parser/parsing_spec.rb +0 -1
  89. data/spec/rley/sppf/alternative_node_spec.rb +2 -2
  90. data/spec/rley/sppf/non_terminal_node_spec.rb +0 -1
  91. data/spec/rley/support/ambiguous_grammar_helper.rb +1 -1
  92. data/spec/rley/support/expectation_helper.rb +37 -36
  93. data/spec/rley/support/grammar_abc_helper.rb +17 -17
  94. data/spec/rley/support/grammar_b_expr_helper.rb +40 -39
  95. data/spec/rley/support/grammar_helper.rb +2 -1
  96. data/spec/rley/support/{grammar_L0_helper.rb → grammar_l0_helper.rb} +82 -81
  97. data/spec/rley/support/grammar_sppf_helper.rb +24 -25
  98. data/spec/rley/syntax/grammar_spec.rb +1 -1
  99. metadata +2 -2
@@ -1,214 +1,215 @@
1
- require_relative '../syntax/terminal'
2
- require_relative '../syntax/non_terminal'
3
- require_relative '../gfg/end_vertex'
4
- require_relative '../gfg/item_vertex'
5
- require_relative '../gfg/start_vertex'
6
- require_relative '../sppf/epsilon_node'
7
- require_relative '../sppf/non_terminal_node'
8
- require_relative '../sppf/alternative_node'
9
- require_relative '../sppf/parse_forest'
10
-
11
- module Rley # This module is used as a namespace
12
- module Parser # This module is used as a namespace
13
- # Builder GoF pattern. Builder pattern builds a complex object
14
- # (say, a parse forest) from simpler objects (terminal and non-terminal
15
- # nodes) and using a step by step approach.
16
- class ParseForestBuilder
17
- # The sequence of input tokens
18
- attr_reader(:tokens)
19
-
20
- # Link to forest object
21
- attr_reader(:forest)
22
-
23
- # Link to current path
24
- attr_reader(:curr_path)
25
-
26
- # The last parse entry visited
27
- attr_reader(:last_visitee)
28
-
29
- # A hash with pairs of the form: visited parse entry => forest node
30
- attr_reader(:entry2node)
31
-
32
- # A hash with pairs of the form: parent end entry => path to alternative node
33
- # This is needed for synchronizing backtracking
34
- attr_reader(:entry2path_to_alt)
35
-
36
- def initialize(theTokens)
37
- @tokens = theTokens
38
- @curr_path = []
39
- @entry2node = {}
40
- @entry2path_to_alt = {}
41
- end
42
-
43
- def receive_event(anEvent, anEntry, anIndex)
44
- # puts "Event: #{anEvent} #{anEntry} #{anIndex}"
45
- if anEntry.dotted_entry?
46
- process_item_entry(anEvent, anEntry, anIndex)
47
- elsif anEntry.start_entry?
48
- process_start_entry(anEvent, anEntry, anIndex)
49
- elsif anEntry.end_entry?
50
- process_end_entry(anEvent, anEntry, anIndex)
51
- else
52
- fail NotImplementedError
53
- end
54
-
55
- @last_visitee = anEntry
56
- end
57
-
58
- # Return the current_parent node
59
- def curr_parent()
60
- return self.curr_path.last
61
- end
62
-
63
- private
64
-
65
- def process_start_entry(anEvent, anEntry, anIndex)
66
- self.curr_path.pop
67
- end
68
-
69
- def process_end_entry(anEvent, anEntry, anIndex)
70
- case anEvent
71
- when :visit
72
- # create a node with the non-terminal
73
- # with same right extent as curr_entry_set_index
74
- # add the new node as first child of current_parent
75
- # append the new node to the curr_path
76
- range = { low: anEntry.origin, high: anIndex }
77
- non_terminal = anEntry.vertex.non_terminal
78
- create_non_terminal_node(anEntry, range, non_terminal)
79
- @forest = create_forest(curr_parent) unless @last_visitee
80
-
81
- when :backtrack
82
- # Restore path
83
- @curr_path = self.entry2path_to_alt[anEntry].dup
84
- # puts "Restore path #{curr_path.join(', ')}]"
85
- antecedent_index = curr_parent.subnodes.size
86
- # puts "Current parent #{curr_parent.to_string(0)}"
87
- # puts "Antecedent index #{antecedent_index}"
88
-
89
-
90
- when :revisit
91
- # Retrieve the already existing node corresponding to re-visited entry
92
- popular = @entry2node[anEntry]
93
-
94
- # Share with parent
95
- curr_parent.add_subnode(popular)
96
-
97
- else
98
- fail NotImplementedError
99
- end
100
- end
101
-
102
-
103
- def process_item_entry(anEvent, anEntry, anIndex)
104
- if anEntry.exit_entry?
105
- # Previous entry was an end entry (X. pattern)
106
- # Does the previous entry have multiple antecedent?
107
- if last_visitee.end_entry? && last_visitee.antecedents.size > 1
108
- # Store current path for later backtracking
109
- # puts "Store backtrack context #{last_visitee}"
110
- # puts "path [#{curr_path.join(', ')}]"
111
- self.entry2path_to_alt[last_visitee] = curr_path.dup
112
- curr_parent.refinement = :or
113
-
114
- create_alternative_node(anEntry)
115
- end
116
- end
117
-
118
- # Retrieve the grammar symbol before the dot (if any)
119
- prev_symbol = anEntry.prev_symbol
120
- case prev_symbol
121
- when Syntax::Terminal
122
- # Add node without changing current path
123
- create_token_node(anEntry, anIndex)
124
-
125
- when Syntax::NonTerminal
126
- # Do nothing
127
-
128
- when NilClass # Dot at the beginning of production
129
- if anEntry.vertex.dotted_item.production.empty?
130
- # Empty rhs => create an epsilon node ...
131
- # ... without changing current path
132
- create_epsilon_node(anEntry, anIndex)
133
- end
134
- self.curr_path.pop if curr_parent.kind_of?(SPPF::AlternativeNode)
135
- end
136
- end
137
-
138
- # Create an empty parse forest
139
- def create_forest(aRootNode)
140
- return Rley::SPPF::ParseForest.new(aRootNode)
141
- end
142
-
143
-
144
- # Factory method. Build and return an SPPF non-terminal node.
145
- def create_non_terminal_node(anEntry, aRange, nonTSymb = nil)
146
- non_terminal = nonTSymb.nil? ? anEntry.vertex.non_terminal : nonTSymb
147
- new_node = Rley::SPPF::NonTerminalNode.new(non_terminal, aRange)
148
- entry2node[anEntry] = new_node
149
- # puts "FOREST ADD #{curr_parent.key if curr_parent}/#{new_node.key}"
150
- add_subnode(new_node)
151
-
152
- return new_node
153
- end
154
-
155
-
156
- # Add an alternative node to the forest
157
- def create_alternative_node(anEntry)
158
- alternative = Rley::SPPF::AlternativeNode.new(anEntry.vertex, curr_parent.range)
159
- add_subnode(alternative)
160
- # puts "FOREST ADD #{alternative.key}"
161
-
162
- return alternative
163
- end
164
-
165
- # create a token node,
166
- # with same origin as token,
167
- # with same right extent = origin + 1
168
- # add the new node as first child of current_parent
169
- def create_token_node(anEntry, anIndex)
170
- token_position = anIndex - 1
171
- curr_token = tokens[token_position]
172
- new_node = SPPF::TokenNode.new(curr_token, token_position)
173
- candidate = add_node_to_forest(new_node)
174
- entry2node[anEntry] = candidate
175
-
176
- return candidate
177
- end
178
-
179
-
180
- def create_epsilon_node(anEntry, anIndex)
181
- new_node = SPPF::EpsilonNode.new(anIndex)
182
- candidate = add_node_to_forest(new_node)
183
- entry2node[anEntry] = candidate
184
-
185
- return candidate
186
- end
187
-
188
- # Add the given node if not yet present in parse forest
189
- def add_node_to_forest(aNode)
190
- key_node = aNode.key
191
- if forest.include?(key_node)
192
- new_node = forest.key2node[key_node]
193
- else
194
- new_node = aNode
195
- forest.key2node[key_node] = new_node
196
- # puts "FOREST ADD #{key_node}"
197
- end
198
- add_subnode(new_node, false)
199
-
200
- return new_node
201
- end
202
-
203
-
204
- # Add the given node as sub-node of current parent node
205
- # Optionally add the node to the current path
206
- def add_subnode(aNode, addToPath = true)
207
- curr_parent.add_subnode(aNode) unless curr_path.empty?
208
- self.curr_path << aNode if addToPath
209
- end
210
- end # class
211
- end # module
212
- end # module
213
-
214
- # End of file
1
+ require_relative '../syntax/terminal'
2
+ require_relative '../syntax/non_terminal'
3
+ require_relative '../gfg/end_vertex'
4
+ require_relative '../gfg/item_vertex'
5
+ require_relative '../gfg/start_vertex'
6
+ require_relative '../sppf/epsilon_node'
7
+ require_relative '../sppf/non_terminal_node'
8
+ require_relative '../sppf/alternative_node'
9
+ require_relative '../sppf/parse_forest'
10
+
11
+ module Rley # This module is used as a namespace
12
+ module Parser # This module is used as a namespace
13
+ # Builder GoF pattern. Builder pattern builds a complex object
14
+ # (say, a parse forest) from simpler objects (terminal and non-terminal
15
+ # nodes) and using a step by step approach.
16
+ class ParseForestBuilder
17
+ # The sequence of input tokens
18
+ attr_reader(:tokens)
19
+
20
+ # Link to forest object
21
+ attr_reader(:forest)
22
+
23
+ # Link to current path
24
+ attr_reader(:curr_path)
25
+
26
+ # The last parse entry visited
27
+ attr_reader(:last_visitee)
28
+
29
+ # A hash with pairs of the form: visited parse entry => forest node
30
+ attr_reader(:entry2node)
31
+
32
+ # A hash with pairs of the form:
33
+ # parent end entry => path to alternative node
34
+ # This is needed for synchronizing backtracking
35
+ attr_reader(:entry2path_to_alt)
36
+
37
+ def initialize(theTokens)
38
+ @tokens = theTokens
39
+ @curr_path = []
40
+ @entry2node = {}
41
+ @entry2path_to_alt = {}
42
+ end
43
+
44
+ def receive_event(anEvent, anEntry, anIndex)
45
+ # puts "Event: #{anEvent} #{anEntry} #{anIndex}"
46
+ if anEntry.dotted_entry?
47
+ process_item_entry(anEvent, anEntry, anIndex)
48
+ elsif anEntry.start_entry?
49
+ process_start_entry(anEvent, anEntry, anIndex)
50
+ elsif anEntry.end_entry?
51
+ process_end_entry(anEvent, anEntry, anIndex)
52
+ else
53
+ raise NotImplementedError
54
+ end
55
+
56
+ @last_visitee = anEntry
57
+ end
58
+
59
+ # Return the current_parent node
60
+ def curr_parent()
61
+ return curr_path.last
62
+ end
63
+
64
+ private
65
+
66
+ def process_start_entry(_anEvent, _anEntry, _anIndex)
67
+ curr_path.pop
68
+ end
69
+
70
+ def process_end_entry(anEvent, anEntry, anIndex)
71
+ case anEvent
72
+ when :visit
73
+ # create a node with the non-terminal
74
+ # with same right extent as curr_entry_set_index
75
+ # add the new node as first child of current_parent
76
+ # append the new node to the curr_path
77
+ range = { low: anEntry.origin, high: anIndex }
78
+ non_terminal = anEntry.vertex.non_terminal
79
+ create_non_terminal_node(anEntry, range, non_terminal)
80
+ @forest = create_forest(curr_parent) unless @last_visitee
81
+
82
+ when :backtrack
83
+ # Restore path
84
+ @curr_path = entry2path_to_alt[anEntry].dup
85
+ # puts "Restore path #{curr_path.join(', ')}]"
86
+ antecedent_index = curr_parent.subnodes.size
87
+ # puts "Current parent #{curr_parent.to_string(0)}"
88
+ # puts "Antecedent index #{antecedent_index}"
89
+
90
+
91
+ when :revisit
92
+ # Retrieve the already existing node corresponding
93
+ # to re-visited entry
94
+ popular = @entry2node[anEntry]
95
+
96
+ # Share with parent
97
+ curr_parent.add_subnode(popular)
98
+
99
+ else
100
+ raise NotImplementedError
101
+ end
102
+ end
103
+
104
+
105
+ def process_item_entry(_anEvent, anEntry, anIndex)
106
+ if anEntry.exit_entry?
107
+ # Previous entry was an end entry (X. pattern)
108
+ # Does the previous entry have multiple antecedent?
109
+ if last_visitee.end_entry? && last_visitee.antecedents.size > 1
110
+ # Store current path for later backtracking
111
+ # puts "Store backtrack context #{last_visitee}"
112
+ # puts "path [#{curr_path.join(', ')}]"
113
+ entry2path_to_alt[last_visitee] = curr_path.dup
114
+ curr_parent.refinement = :or
115
+
116
+ create_alternative_node(anEntry)
117
+ end
118
+ end
119
+
120
+ # Retrieve the grammar symbol before the dot (if any)
121
+ prev_symbol = anEntry.prev_symbol
122
+ case prev_symbol
123
+ when Syntax::Terminal
124
+ # Add node without changing current path
125
+ create_token_node(anEntry, anIndex)
126
+
127
+ when NilClass # Dot at the beginning of production
128
+ if anEntry.vertex.dotted_item.production.empty?
129
+ # Empty rhs => create an epsilon node ...
130
+ # ... without changing current path
131
+ create_epsilon_node(anEntry, anIndex)
132
+ end
133
+ curr_path.pop if curr_parent.kind_of?(SPPF::AlternativeNode)
134
+ end
135
+ end
136
+
137
+ # Create an empty parse forest
138
+ def create_forest(aRootNode)
139
+ return Rley::SPPF::ParseForest.new(aRootNode)
140
+ end
141
+
142
+
143
+ # Factory method. Build and return an SPPF non-terminal node.
144
+ def create_non_terminal_node(anEntry, aRange, nonTSymb = nil)
145
+ non_terminal = nonTSymb.nil? ? anEntry.vertex.non_terminal : nonTSymb
146
+ new_node = Rley::SPPF::NonTerminalNode.new(non_terminal, aRange)
147
+ entry2node[anEntry] = new_node
148
+ # puts "FOREST ADD #{curr_parent.key if curr_parent}/#{new_node.key}"
149
+ add_subnode(new_node)
150
+
151
+ return new_node
152
+ end
153
+
154
+
155
+ # Add an alternative node to the forest
156
+ def create_alternative_node(anEntry)
157
+ vertex = anEntry.vertex
158
+ range = curr_parent.range
159
+ alternative = Rley::SPPF::AlternativeNode.new(vertex, range)
160
+ add_subnode(alternative)
161
+ # puts "FOREST ADD #{alternative.key}"
162
+
163
+ return alternative
164
+ end
165
+
166
+ # create a token node,
167
+ # with same origin as token,
168
+ # with same right extent = origin + 1
169
+ # add the new node as first child of current_parent
170
+ def create_token_node(anEntry, anIndex)
171
+ token_position = anIndex - 1
172
+ curr_token = tokens[token_position]
173
+ new_node = SPPF::TokenNode.new(curr_token, token_position)
174
+ candidate = add_node_to_forest(new_node)
175
+ entry2node[anEntry] = candidate
176
+
177
+ return candidate
178
+ end
179
+
180
+
181
+ def create_epsilon_node(anEntry, anIndex)
182
+ new_node = SPPF::EpsilonNode.new(anIndex)
183
+ candidate = add_node_to_forest(new_node)
184
+ entry2node[anEntry] = candidate
185
+
186
+ return candidate
187
+ end
188
+
189
+ # Add the given node if not yet present in parse forest
190
+ def add_node_to_forest(aNode)
191
+ key_node = aNode.key
192
+ if forest.include?(key_node)
193
+ new_node = forest.key2node[key_node]
194
+ else
195
+ new_node = aNode
196
+ forest.key2node[key_node] = new_node
197
+ # puts "FOREST ADD #{key_node}"
198
+ end
199
+ add_subnode(new_node, false)
200
+
201
+ return new_node
202
+ end
203
+
204
+
205
+ # Add the given node as sub-node of current parent node
206
+ # Optionally add the node to the current path
207
+ def add_subnode(aNode, addToPath = true)
208
+ curr_parent.add_subnode(aNode) unless curr_path.empty?
209
+ curr_path << aNode if addToPath
210
+ end
211
+ end # class
212
+ end # module
213
+ end # module
214
+
215
+ # End of file
@@ -1,56 +1,57 @@
1
- require_relative 'parse_walker_factory'
2
- require_relative 'parse_forest_builder'
3
-
4
- module Rley # This module is used as a namespace
5
- module Parser # This module is used as a namespace
6
- # Utility class that helps to create a ParseForest from
7
- # a given Parsing object.
8
- class ParseForestFactory
9
- # Link to Parsing object (= results of recognizer)
10
- attr_reader(:parsing)
11
-
12
-
13
- def initialize(aParsingResult)
14
- @parsing = aParsingResult
15
- end
16
-
17
- # Factory that produces the parse forest
18
- def build_parse_forest()
19
- a_walker = walker(parsing)
20
- a_builder = builder(parsing)
21
-
22
- begin
23
- loop do
24
- event = a_walker.next
25
- # puts "EVENT #{event[0]} #{event[1]}"
26
- a_builder.receive_event(*event)
27
- end
28
- rescue StopIteration
29
- # Do nothing
30
- end
31
-
32
- return a_builder.forest
33
- end
34
-
35
-
36
- private
37
- # Create a Parsing walker, that is, an object
38
- # that will iterate over the relevant nodes (= parsing entries)
39
- # of a GFGParsing
40
- def walker(aParseResult)
41
- walker_factory = ParseWalkerFactory.new
42
- accept_entry = aParseResult.accepting_entry
43
- accept_index = aParseResult.chart.last_index
44
- walker = walker_factory.build_walker(accept_entry, accept_index)
45
- end
46
-
47
- # Create a Builder, that is, an object
48
- # that will create piece by piece the forest
49
- def builder(aParseResult)
50
- ParseForestBuilder.new(aParseResult.tokens)
51
- end
52
- end # class
53
- end # module
54
- end # module
55
-
56
- # End of file
1
+ require_relative 'parse_walker_factory'
2
+ require_relative 'parse_forest_builder'
3
+
4
+ module Rley # This module is used as a namespace
5
+ module Parser # This module is used as a namespace
6
+ # Utility class that helps to create a ParseForest from
7
+ # a given Parsing object.
8
+ class ParseForestFactory
9
+ # Link to Parsing object (= results of recognizer)
10
+ attr_reader(:parsing)
11
+
12
+
13
+ def initialize(aParsingResult)
14
+ @parsing = aParsingResult
15
+ end
16
+
17
+ # Factory that produces the parse forest
18
+ def build_parse_forest()
19
+ a_walker = walker(parsing)
20
+ a_builder = builder(parsing)
21
+
22
+ begin
23
+ loop do
24
+ event = a_walker.next
25
+ # puts "EVENT #{event[0]} #{event[1]}"
26
+ a_builder.receive_event(*event)
27
+ end
28
+ rescue StopIteration
29
+ # Do nothing
30
+ end
31
+
32
+ return a_builder.forest
33
+ end
34
+
35
+
36
+ private
37
+
38
+ # Create a Parsing walker, that is, an object
39
+ # that will iterate over the relevant nodes (= parsing entries)
40
+ # of a GFGParsing
41
+ def walker(aParseResult)
42
+ walker_factory = ParseWalkerFactory.new
43
+ accept_entry = aParseResult.accepting_entry
44
+ accept_index = aParseResult.chart.last_index
45
+ walker_factory.build_walker(accept_entry, accept_index)
46
+ end
47
+
48
+ # Create a Builder, that is, an object
49
+ # that will create piece by piece the forest
50
+ def builder(aParseResult)
51
+ ParseForestBuilder.new(aParseResult.tokens)
52
+ end
53
+ end # class
54
+ end # module
55
+ end # module
56
+
57
+ # End of file