rley 0.2.15 → 0.3.00
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/lib/rley/constants.rb +1 -1
- data/lib/rley/gfg/call_edge.rb +30 -0
- data/lib/rley/gfg/edge.rb +4 -0
- data/lib/rley/gfg/end_vertex.rb +1 -1
- data/lib/rley/gfg/epsilon_edge.rb +0 -4
- data/lib/rley/gfg/grm_flow_graph.rb +32 -7
- data/lib/rley/gfg/item_vertex.rb +71 -25
- data/lib/rley/gfg/non_terminal_vertex.rb +10 -1
- data/lib/rley/gfg/return_edge.rb +31 -0
- data/lib/rley/gfg/scan_edge.rb +2 -1
- data/lib/rley/gfg/shortcut_edge.rb +26 -0
- data/lib/rley/gfg/start_vertex.rb +2 -2
- data/lib/rley/gfg/vertex.rb +27 -1
- data/lib/rley/parse_forest_visitor.rb +115 -0
- data/lib/rley/parser/base_parser.rb +27 -0
- data/lib/rley/parser/dotted_item.rb +11 -0
- data/lib/rley/parser/earley_parser.rb +3 -15
- data/lib/rley/parser/gfg_chart.rb +106 -0
- data/lib/rley/parser/gfg_earley_parser.rb +139 -0
- data/lib/rley/parser/gfg_parsing.rb +384 -0
- data/lib/rley/parser/parse_entry.rb +148 -0
- data/lib/rley/parser/parse_entry_set.rb +104 -0
- data/lib/rley/parser/parse_entry_tracker.rb +56 -0
- data/lib/rley/parser/parse_forest_builder.rb +229 -0
- data/lib/rley/parser/parse_forest_factory.rb +54 -0
- data/lib/rley/parser/parse_walker_factory.rb +237 -0
- data/lib/rley/ptree/token_range.rb +14 -1
- data/lib/rley/sppf/alternative_node.rb +34 -0
- data/lib/rley/sppf/composite_node.rb +27 -0
- data/lib/rley/sppf/epsilon_node.rb +27 -0
- data/lib/rley/sppf/leaf_node.rb +12 -0
- data/lib/rley/sppf/non_terminal_node.rb +38 -0
- data/lib/rley/sppf/parse_forest.rb +48 -0
- data/lib/rley/sppf/sppf_node.rb +24 -0
- data/lib/rley/sppf/token_node.rb +29 -0
- data/lib/rley/syntax/grammar_builder.rb +16 -12
- data/lib/rley/syntax/grm_symbol.rb +6 -0
- data/lib/rley/syntax/terminal.rb +5 -0
- data/spec/rley/gfg/call_edge_spec.rb +51 -0
- data/spec/rley/gfg/end_vertex_spec.rb +1 -0
- data/spec/rley/gfg/grm_flow_graph_spec.rb +24 -2
- data/spec/rley/gfg/item_vertex_spec.rb +75 -6
- data/spec/rley/gfg/non_terminal_vertex_spec.rb +14 -0
- data/spec/rley/gfg/return_edge_spec.rb +51 -0
- data/spec/rley/gfg/shortcut_edge_spec.rb +43 -0
- data/spec/rley/gfg/vertex_spec.rb +52 -37
- data/spec/rley/parse_forest_visitor_spec.rb +238 -0
- data/spec/rley/parser/dotted_item_spec.rb +29 -8
- data/spec/rley/parser/gfg_chart_spec.rb +138 -0
- data/spec/rley/parser/gfg_earley_parser_spec.rb +918 -0
- data/spec/rley/parser/gfg_parsing_spec.rb +565 -0
- data/spec/rley/parser/parse_entry_set_spec.rb +179 -0
- data/spec/rley/parser/parse_entry_spec.rb +208 -0
- data/spec/rley/parser/parse_forest_builder_spec.rb +382 -0
- data/spec/rley/parser/parse_forest_factory_spec.rb +81 -0
- data/spec/rley/parser/parse_walker_factory_spec.rb +235 -0
- data/spec/rley/parser/state_set_spec.rb +4 -0
- data/spec/rley/sppf/alternative_node_spec.rb +72 -0
- data/spec/rley/sppf/antecedence_graph.rb +87 -0
- data/spec/rley/sppf/forest_representation.rb +136 -0
- data/spec/rley/sppf/gfg_representation.rb +111 -0
- data/spec/rley/sppf/non_terminal_node_spec.rb +64 -0
- data/spec/rley/support/ambiguous_grammar_helper.rb +36 -36
- data/spec/rley/support/expectation_helper.rb +36 -0
- data/spec/rley/support/grammar_helper.rb +28 -0
- data/spec/rley/support/grammar_sppf_helper.rb +25 -0
- data/spec/rley/syntax/grammar_builder_spec.rb +5 -0
- data/spec/rley/syntax/non_terminal_spec.rb +4 -0
- data/spec/rley/syntax/terminal_spec.rb +4 -0
- metadata +58 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5b7bad0d01ea1fbe0656bf1765843288c1521b26
|
4
|
+
data.tar.gz: d7b96f2d154b172c0847b3a96eaf0b6422439db1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 76fa3fcf95a3bb55ca2e13eb1b449032cb3030cf18c5ab114e2398aeec16401d8c2b738f9818831dd4360d143f24f1240ffd13b8f0c495dcb8f5c684675ec894
|
7
|
+
data.tar.gz: 52f7f640dfc96d9f78a9ee1a44da1fb81086d446b1196d9a422bb5f6e7312c0e6ea089ce595b78b3b4c1d51d4cf810b18cda26fefd2477f7b5190dc9dfb8bca3
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
### 0.3.00 / 2016-10-23
|
2
|
+
* [CHANGE] Many new classes. The gem bundles a second parser that copes with ambiguous grammars.
|
3
|
+
|
4
|
+
|
1
5
|
### 0.2.15 / 2016-02-14
|
2
6
|
* [CHANGE] A lot of internal changes. This is the last version before a Grammar Flow Graph-based parsing implementation.
|
3
7
|
|
data/lib/rley/constants.rb
CHANGED
@@ -0,0 +1,30 @@
|
|
1
|
+
require_relative 'edge'
|
2
|
+
|
3
|
+
module Rley # This module is used as a namespace
|
4
|
+
module GFG # This module is used as a namespace
|
5
|
+
# Specialization of an edge in a grammar flow graph
|
6
|
+
# that has a item vertex as its head (predecessor).
|
7
|
+
# and a start vertex (.X) as its tail (successor).
|
8
|
+
# Responsibilities:
|
9
|
+
# - To know the successor vertex (tail)
|
10
|
+
class CallEdge < Edge
|
11
|
+
attr_reader(:key)
|
12
|
+
|
13
|
+
# Pre-condition: thePredecessor is an ItemVertex
|
14
|
+
# Pre-condition: theSuccessor is an StartVertex
|
15
|
+
def initialize(thePredecessor, theSuccessor)
|
16
|
+
super(thePredecessor, theSuccessor)
|
17
|
+
do_set_key(thePredecessor, theSuccessor)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
def do_set_key(thePredecessor, theSuccessor)
|
22
|
+
tail_d_item = thePredecessor.dotted_item
|
23
|
+
@key = "CALL_#{tail_d_item.production.object_id}_#{tail_d_item.position}"
|
24
|
+
end
|
25
|
+
|
26
|
+
end # class
|
27
|
+
end # module
|
28
|
+
end # module
|
29
|
+
|
30
|
+
# End of file
|
data/lib/rley/gfg/edge.rb
CHANGED
data/lib/rley/gfg/end_vertex.rb
CHANGED
@@ -2,7 +2,10 @@ require_relative 'start_vertex'
|
|
2
2
|
require_relative 'end_vertex'
|
3
3
|
require_relative 'item_vertex'
|
4
4
|
require_relative 'epsilon_edge'
|
5
|
+
require_relative 'call_edge'
|
6
|
+
require_relative 'return_edge'
|
5
7
|
require_relative 'scan_edge'
|
8
|
+
require_relative 'shortcut_edge'
|
6
9
|
|
7
10
|
module Rley # This module is used as a namespace
|
8
11
|
module GFG # This module is used as a namespace
|
@@ -27,11 +30,18 @@ module Rley # This module is used as a namespace
|
|
27
30
|
|
28
31
|
build_graph(theDottedItems)
|
29
32
|
end
|
33
|
+
|
34
|
+
# Return the vertex with given vertex label.
|
35
|
+
def find_vertex(aVertexLabel)
|
36
|
+
vertices.find { |a_vertex| a_vertex.label == aVertexLabel }
|
37
|
+
end
|
30
38
|
|
31
39
|
private
|
32
40
|
def add_vertex(aVertex)
|
41
|
+
fail StandardError, 'GFG vertex cannot be nil' if aVertex.nil?
|
42
|
+
|
33
43
|
# TODO: make setting of start vertex more robust
|
34
|
-
start_vertex = aVertex if vertices.empty?
|
44
|
+
@start_vertex = aVertex if vertices.empty?
|
35
45
|
vertices << aVertex
|
36
46
|
end
|
37
47
|
|
@@ -54,7 +64,9 @@ private
|
|
54
64
|
end
|
55
65
|
end
|
56
66
|
end
|
57
|
-
|
67
|
+
|
68
|
+
# For each non-terminal from the grammar, say N
|
69
|
+
# Add the .N and N. vertices to the graph
|
58
70
|
def build_all_starts_ends(theDottedItems)
|
59
71
|
productions_raw = theDottedItems.map(&:production)
|
60
72
|
productions = productions_raw.uniq
|
@@ -98,9 +110,12 @@ private
|
|
98
110
|
# Rule 5
|
99
111
|
# add a call edge: N => α[1] .A α[n] -> .A
|
100
112
|
# add a return edge: A. -> N => α[1] A. α[n]
|
113
|
+
# add a shortcut edge: ( N => α[1] .A α[n] ) -> ( N => α[1] A. α[n] )
|
101
114
|
def augment_graph(theDottedItems, firstItemPos)
|
102
115
|
production = theDottedItems[firstItemPos].production
|
103
116
|
max_index = production.rhs.size + 1
|
117
|
+
prev_vertex = nil
|
118
|
+
|
104
119
|
(0...max_index).each do |index|
|
105
120
|
current_item = theDottedItems[firstItemPos+index]
|
106
121
|
new_vertex = ItemVertex.new(current_item)
|
@@ -119,6 +134,12 @@ private
|
|
119
134
|
build_call_return_edges(vertices[-2], new_vertex)
|
120
135
|
end
|
121
136
|
end
|
137
|
+
|
138
|
+
prev_symbol = current_item.prev_symbol
|
139
|
+
if prev_symbol && prev_symbol.kind_of?(Syntax::NonTerminal)
|
140
|
+
build_shortcut_edge(prev_vertex, new_vertex)
|
141
|
+
end
|
142
|
+
prev_vertex = new_vertex
|
122
143
|
end
|
123
144
|
end
|
124
145
|
|
@@ -147,18 +168,22 @@ private
|
|
147
168
|
ScanEdge.new(fromVertex, toVertex, fromVertex.dotted_item.next_symbol)
|
148
169
|
end
|
149
170
|
|
150
|
-
def build_call_return_edges(
|
151
|
-
nt_symbol =
|
171
|
+
def build_call_return_edges(calling_vertex, return_vertex)
|
172
|
+
nt_symbol = calling_vertex.dotted_item.next_symbol
|
152
173
|
|
153
174
|
# Retrieve corresponding start vertex
|
154
175
|
start_vertex = start_vertex_for[nt_symbol]
|
155
|
-
# Create an edge
|
156
|
-
|
176
|
+
# Create an edge 'calling' vertex -> start vertex
|
177
|
+
CallEdge.new(calling_vertex, start_vertex)
|
157
178
|
|
158
179
|
# Retrieve corresponding end vertex
|
159
180
|
end_vertex = end_vertex_for[nt_symbol]
|
160
181
|
# Create an edge end vertex -> return vertex
|
161
|
-
|
182
|
+
ReturnEdge.new(end_vertex, return_vertex)
|
183
|
+
end
|
184
|
+
|
185
|
+
def build_shortcut_edge(fromVertex, toVertex)
|
186
|
+
ShortcutEdge.new(fromVertex, toVertex)
|
162
187
|
end
|
163
188
|
end # class
|
164
189
|
end # module
|
data/lib/rley/gfg/item_vertex.rb
CHANGED
@@ -1,26 +1,72 @@
|
|
1
|
-
require_relative '
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
1
|
+
require_relative '../syntax/non_terminal'
|
2
|
+
require_relative 'vertex'
|
3
|
+
|
4
|
+
|
5
|
+
module Rley # This module is used as a namespace
|
6
|
+
module GFG # This module is used as a namespace
|
7
|
+
# TODO: modify definition
|
8
|
+
# Represents a specialized vertex in a grammar flow graph
|
9
|
+
# that is associated to a given dotted item.
|
10
|
+
# Responsibilities (in addition to inherited ones):
|
11
|
+
# - Know its related non-terminal symbol
|
12
|
+
class ItemVertex < Vertex
|
13
|
+
# Link to the dotted item object
|
14
|
+
attr_reader :dotted_item
|
15
|
+
|
16
|
+
# Optional link to a "shortcut" edge.
|
17
|
+
# Applicable only if the dotted expects a non-terminal symbol.
|
18
|
+
attr_reader :shortcut
|
19
|
+
|
20
|
+
def initialize(aDottedItem)
|
21
|
+
super()
|
22
|
+
@dotted_item = aDottedItem
|
23
|
+
end
|
24
|
+
|
25
|
+
# Set the "shortcut" edge.
|
26
|
+
def shortcut=(aShortcut)
|
27
|
+
unless aShortcut.kind_of?(ShortcutEdge)
|
28
|
+
fail StandardError, 'Invalid shortcut argument'
|
29
|
+
end
|
30
|
+
=begin
|
31
|
+
unless next_symbol && next_symbol.kind_of?(Syntax::NonTerminal)
|
32
|
+
fail StandardError, 'Invalid shortcut usage'
|
33
|
+
end
|
34
|
+
|
35
|
+
shortcut_d_item = aShortcut.successor.dotted_item
|
36
|
+
unless (dotted_item.production == shortcut_d_item.production) &&
|
37
|
+
(dotted_item.position == shortcut_d_item.prev_position)
|
38
|
+
fail StandardError, 'Shortcut refers to wrong vertex'
|
39
|
+
end
|
40
|
+
=end
|
41
|
+
@shortcut = aShortcut
|
42
|
+
end
|
43
|
+
|
44
|
+
def label()
|
45
|
+
return "#{dotted_item}"
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns true if the dotted item has a dot at the end of the production.
|
49
|
+
def complete?()
|
50
|
+
return dotted_item.reduce_item?
|
51
|
+
end
|
52
|
+
|
53
|
+
# Return the symbol before the dot else nil.
|
54
|
+
def prev_symbol()
|
55
|
+
return dotted_item.prev_symbol
|
56
|
+
end
|
57
|
+
|
58
|
+
# Return the symbol after the dot else nil.
|
59
|
+
def next_symbol()
|
60
|
+
return dotted_item.next_symbol
|
61
|
+
end
|
62
|
+
|
63
|
+
# Return the non-terminal symbol at the left-hand side of the production
|
64
|
+
def lhs()
|
65
|
+
return dotted_item.lhs
|
66
|
+
end
|
67
|
+
|
68
|
+
end # class
|
69
|
+
end # module
|
70
|
+
end # module
|
71
|
+
|
26
72
|
# End of file
|
@@ -3,7 +3,8 @@ require_relative 'vertex'
|
|
3
3
|
module Rley # This module is used as a namespace
|
4
4
|
module GFG # This module is used as a namespace
|
5
5
|
# Represents a specialized vertex in a grammar flow graph
|
6
|
-
# that is associated to a given non-terminal symbol
|
6
|
+
# that is associated to a given non-terminal symbol and
|
7
|
+
# that may have in-degree or out-degree > 1
|
7
8
|
# Responsibilities (in addition to inherited ones):
|
8
9
|
# - Know its related non-terminal symbol
|
9
10
|
class NonTerminalVertex < Vertex
|
@@ -13,6 +14,14 @@ module Rley # This module is used as a namespace
|
|
13
14
|
super()
|
14
15
|
@non_terminal = aNonTerminal
|
15
16
|
end
|
17
|
+
|
18
|
+
protected
|
19
|
+
|
20
|
+
# Validation method for adding an outgoing edge to the vertex.
|
21
|
+
# A start vertex may accept an indegree and outdegree greater than one
|
22
|
+
def check_add_edge(anEdge)
|
23
|
+
return anEdge
|
24
|
+
end
|
16
25
|
|
17
26
|
end # class
|
18
27
|
end # module
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require_relative 'edge'
|
2
|
+
|
3
|
+
module Rley # This module is used as a namespace
|
4
|
+
module GFG # This module is used as a namespace
|
5
|
+
# Specialization of an edge in a grammar flow graph
|
6
|
+
# that has a end vertex (X.) as its head
|
7
|
+
# and an item vertex as its tail
|
8
|
+
|
9
|
+
# Responsibilities:
|
10
|
+
# - To know the successor vertex (tail)
|
11
|
+
class ReturnEdge < Edge
|
12
|
+
attr_reader(:key)
|
13
|
+
|
14
|
+
# Pre-condition: thePredecessor is an EndVertex
|
15
|
+
# Pre-condition: theSuccessor is an ItemVertex
|
16
|
+
def initialize(thePredecessor, theSuccessor)
|
17
|
+
super(thePredecessor, theSuccessor)
|
18
|
+
do_set_key(thePredecessor, theSuccessor)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
def do_set_key(thePredecessor, theSuccessor)
|
23
|
+
tail_d_item = theSuccessor.dotted_item
|
24
|
+
@key = "RET_#{tail_d_item.production.object_id}_#{tail_d_item.prev_position}"
|
25
|
+
end
|
26
|
+
|
27
|
+
end # class
|
28
|
+
end # module
|
29
|
+
end # module
|
30
|
+
|
31
|
+
# End of file
|
data/lib/rley/gfg/scan_edge.rb
CHANGED
@@ -2,7 +2,8 @@ require_relative 'edge'
|
|
2
2
|
|
3
3
|
module Rley # This module is used as a namespace
|
4
4
|
module GFG # This module is used as a namespace
|
5
|
-
#
|
5
|
+
# Specialization of an edge in a grammar flow graph
|
6
|
+
# that is taken as a consequence of a scan rule.
|
6
7
|
# Responsibilities:
|
7
8
|
# - To know the successor vertex
|
8
9
|
class ScanEdge < Edge
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require_relative 'edge'
|
2
|
+
|
3
|
+
module Rley # This module is used as a namespace
|
4
|
+
module GFG # This module is used as a namespace
|
5
|
+
# Abstract class. Represents an edge in a grammar flow graph
|
6
|
+
# Responsibilities:
|
7
|
+
# - To know the successor vertex
|
8
|
+
class ShortcutEdge < Edge
|
9
|
+
# The terminal symbol expected from the input stream
|
10
|
+
attr_reader :nonterminal
|
11
|
+
|
12
|
+
def initialize(thePredecessor, theSuccessor)
|
13
|
+
@successor = theSuccessor
|
14
|
+
@nonterminal = thePredecessor.next_symbol
|
15
|
+
thePredecessor.shortcut = self
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_s()
|
19
|
+
" -#{nonterminal}-> #{successor.label}"
|
20
|
+
end
|
21
|
+
|
22
|
+
end # class
|
23
|
+
end # module
|
24
|
+
end # module
|
25
|
+
|
26
|
+
# End of file
|
data/lib/rley/gfg/vertex.rb
CHANGED
@@ -14,7 +14,33 @@ module Rley # This module is used as a namespace
|
|
14
14
|
|
15
15
|
# Add an graph edge to this vertex
|
16
16
|
def add_edge(anEdge)
|
17
|
-
|
17
|
+
arrow = check_add_edge(anEdge)
|
18
|
+
edges << arrow
|
19
|
+
end
|
20
|
+
|
21
|
+
# Returns true iff the vertex corresponds to an dotted item that has its dot
|
22
|
+
# at the end of a production (i.e. is a reduced item).
|
23
|
+
def complete?()
|
24
|
+
return false # Default implementation
|
25
|
+
end
|
26
|
+
|
27
|
+
# Return the symbol before the dot else nil.
|
28
|
+
def prev_symbol()
|
29
|
+
return nil # Default implementation
|
30
|
+
end
|
31
|
+
|
32
|
+
# Return the symbol after the dot else nil.
|
33
|
+
def next_symbol()
|
34
|
+
return nil # Default implementation
|
35
|
+
end
|
36
|
+
|
37
|
+
protected
|
38
|
+
# Validation method for adding an outgoing edge to the vertex.
|
39
|
+
# Vertices will accept an indegree and outdegree of at most one
|
40
|
+
# unless this method is overridden in subclasses
|
41
|
+
def check_add_edge(anEdge)
|
42
|
+
fail StandardError, 'At most one edge accepted' unless edges.empty?
|
43
|
+
return anEdge
|
18
44
|
end
|
19
45
|
|
20
46
|
end # class
|
@@ -0,0 +1,115 @@
|
|
1
|
+
module Rley # This module is used as a namespace
|
2
|
+
# A visitor class dedicated in the visit of a parse forest.
|
3
|
+
# It combines the Visitor and Observer patterns.
|
4
|
+
class ParseForestVisitor
|
5
|
+
# Link to the parse forest to visit
|
6
|
+
attr_reader(:pforest)
|
7
|
+
|
8
|
+
# List of objects that subscribed to the visit event notification.
|
9
|
+
attr_reader(:subscribers)
|
10
|
+
|
11
|
+
# A Hash with pairs of the form: Node => node visit data
|
12
|
+
attr_reader(:agenda)
|
13
|
+
|
14
|
+
# Indicates the kind of forest traversal to perform: :post_order, :pre-order
|
15
|
+
attr_reader(:traversal)
|
16
|
+
|
17
|
+
# Build a visitor for the given pforest.
|
18
|
+
# @param aParseForest [ParseForest] the parse tree to visit.
|
19
|
+
def initialize(aParseForest, aTraversalStrategy = :post_order)
|
20
|
+
@pforest = aParseForest
|
21
|
+
@subscribers = []
|
22
|
+
@traversal = aTraversalStrategy
|
23
|
+
end
|
24
|
+
|
25
|
+
public
|
26
|
+
|
27
|
+
# Add a subscriber for the visit event notifications.
|
28
|
+
# @param aSubscriber [Object]
|
29
|
+
def subscribe(aSubscriber)
|
30
|
+
subscribers << aSubscriber
|
31
|
+
end
|
32
|
+
|
33
|
+
# Remove the given object from the subscription list.
|
34
|
+
# The object won't be notified of visit events.
|
35
|
+
# @param aSubscriber [Object]
|
36
|
+
def unsubscribe(aSubscriber)
|
37
|
+
subscribers.delete_if { |entry| entry == aSubscriber }
|
38
|
+
end
|
39
|
+
|
40
|
+
# The signal to begin the visit of the parse forest.
|
41
|
+
def start()
|
42
|
+
pforest.accept(self)
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
# Visit event. The visitor is about to visit the pforest.
|
47
|
+
# @param aParseForest [ParseForest] the pforest to visit.
|
48
|
+
def start_visit_pforest(aParseForest)
|
49
|
+
broadcast(:before_pforest, aParseForest)
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
# Visit event. The visitor is about to visit the given non terminal node.
|
54
|
+
# @param aNonTerminalNode [NonTerminalNode] the node to visit.
|
55
|
+
def visit_nonterminal(aNonTerminalNode)
|
56
|
+
if @traversal == :post_order
|
57
|
+
broadcast(:before_non_terminal, aNonTerminalNode)
|
58
|
+
traverse_children(aNonTerminalNode)
|
59
|
+
else
|
60
|
+
traverse_children(aNonTerminalNode)
|
61
|
+
broadcast(:before_non_terminal, aNonTerminalNode)
|
62
|
+
end
|
63
|
+
broadcast(:after_non_terminal, aNonTerminalNode)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Visit event. The visitor is visiting the
|
67
|
+
# given terminal node.
|
68
|
+
# @param aTerminalNode [TerminalNode] the terminal to visit.
|
69
|
+
def visit_terminal(aTerminalNode)
|
70
|
+
broadcast(:before_terminal, aTerminalNode)
|
71
|
+
broadcast(:after_terminal, aTerminalNode)
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
# Visit event. The visitor has completed its visit of the given
|
76
|
+
# non-terminal node.
|
77
|
+
# @param aNonTerminalNode [NonTerminalNode] the node to visit.
|
78
|
+
def end_visit_nonterminal(aNonTerminalNode)
|
79
|
+
broadcast(:after_non_terminal, aNonTerminalNode)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Visit event. The visitor has completed the visit of the pforest.
|
83
|
+
# @param aParseForest [ParseForest] the pforest to visit.
|
84
|
+
def end_visit_pforest(aParseForest)
|
85
|
+
broadcast(:after_pforest, aParseForest)
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
# Visit event. The visitor is about to visit the children of a non
|
91
|
+
# terminal node.
|
92
|
+
# @param aParentNode [NonTeminalNode] the (non-terminal) parent node.
|
93
|
+
def traverse_children(aParentNode)
|
94
|
+
children = aParentNode.children
|
95
|
+
broadcast(:before_children, aParentNode, children)
|
96
|
+
|
97
|
+
# Let's proceed with the visit of children
|
98
|
+
children.each { |a_node| a_node.accept(self) }
|
99
|
+
|
100
|
+
broadcast(:after_children, aParentNode, children)
|
101
|
+
end
|
102
|
+
|
103
|
+
# Send a notification to all subscribers.
|
104
|
+
# @param msg [Symbol] event to notify
|
105
|
+
# @param args [Array] arguments of the notification.
|
106
|
+
def broadcast(msg, *args)
|
107
|
+
subscribers.each do |a_subscriber|
|
108
|
+
next unless a_subscriber.respond_to?(msg)
|
109
|
+
a_subscriber.send(msg, *args)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end # class
|
113
|
+
end # module
|
114
|
+
|
115
|
+
# End of file
|