dendroid 0.2.00 → 0.2.02

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.
@@ -1,28 +1,28 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'parse_node'
4
-
5
- module Dendroid
6
- module Parsing
7
- class EmptyRuleNode < ParseNode
8
- attr_reader :rule
9
- attr_reader :alt_index
10
-
11
- def initialize(anEItem, rank)
12
- super(rank, rank)
13
- @rule = WeakRef.new(anEItem.dotted_item.rule)
14
- @alt_index = anEItem.dotted_item.alt_index
15
- end
16
-
17
- def to_s
18
- "_ #{super}"
19
- end
20
-
21
- # Part of the 'visitee' role in Visitor design pattern.
22
- # @param aVisitor[ParseTreeVisitor] the visitor
23
- def accept(aVisitor)
24
- aVisitor.visit_empty_rule_node(self)
25
- end
26
- end # class
27
- end # module
28
- end # module
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'parse_node'
4
+
5
+ module Dendroid
6
+ module Parsing
7
+ class EmptyRuleNode < ParseNode
8
+ attr_reader :rule
9
+ attr_reader :alt_index
10
+
11
+ def initialize(anEItem, rank)
12
+ super(rank, rank)
13
+ @rule = WeakRef.new(anEItem.dotted_item.rule)
14
+ @alt_index = anEItem.dotted_item.alt_index
15
+ end
16
+
17
+ def to_s
18
+ "_ #{super}"
19
+ end
20
+
21
+ # Part of the 'visitee' role in Visitor design pattern.
22
+ # @param aVisitor[ParseTreeVisitor] the visitor
23
+ def accept(aVisitor)
24
+ aVisitor.visit_empty_rule_node(self)
25
+ end
26
+ end # class
27
+ end # module
28
+ end # module
@@ -1,51 +1,46 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'composite_parse_node'
4
-
5
- module Dendroid
6
- module Parsing
7
- class OrNode < CompositeParseNode
8
- attr_reader :symbol
9
-
10
- def initialize(sym, lower, upper, arity)
11
- @symbol = sym
12
- super(lower, upper, arity)
13
- end
14
-
15
- def add_child(child_node, _index)
16
- idx = children.find_index(&:nil?)
17
- if idx
18
- # Use first found available slot...
19
- super(child_node, idx)
20
- if children.size > 3
21
- raise StandardError
22
- end
23
- else
24
- raise StandardError
25
- end
26
- end
27
-
28
- def match(anEItem)
29
- return false if range[0] != anEItem.origin
30
-
31
- dotted = anEItem.dotted_item
32
- (symbol == dotted.rule.lhs) && children.any? { |ch| ch.match(anEItem) }
33
- end
34
-
35
- def partial?
36
- # children.any?(&:nil?)
37
- false
38
- end
39
-
40
- def to_s
41
- "OR: #{symbol.name} #{range}"
42
- end
43
-
44
- # Part of the 'visitee' role in Visitor design pattern.
45
- # @param aVisitor[ParseTreeVisitor] the visitor
46
- def accept(aVisitor)
47
- aVisitor.visit_or_node(self)
48
- end
49
- end # class
50
- end # module
51
- end # module
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'composite_parse_node'
4
+
5
+ module Dendroid
6
+ module Parsing
7
+ class OrNode < CompositeParseNode
8
+ attr_reader :symbol
9
+
10
+ def initialize(sym, lower, upper, arity)
11
+ @symbol = sym
12
+ super(lower, upper, arity)
13
+ end
14
+
15
+ def add_child(child_node, _index)
16
+ idx = children.find_index(&:nil?)
17
+ raise StandardError unless idx
18
+
19
+ # Use first found available slot...
20
+ super(child_node, idx)
21
+ end
22
+
23
+ def match(anEItem)
24
+ return false if range[0] != anEItem.origin
25
+
26
+ dotted = anEItem.dotted_item
27
+ (symbol == dotted.rule.lhs) && children.any? { |ch| ch.match(anEItem) }
28
+ end
29
+
30
+ def partial?
31
+ # children.any?(&:nil?)
32
+ false
33
+ end
34
+
35
+ def to_s
36
+ "OR: #{symbol.name} #{range}"
37
+ end
38
+
39
+ # Part of the 'visitee' role in Visitor design pattern.
40
+ # @param aVisitor[ParseTreeVisitor] the visitor
41
+ def accept(aVisitor)
42
+ aVisitor.visit_or_node(self)
43
+ end
44
+ end # class
45
+ end # module
46
+ end # module
@@ -1,26 +1,26 @@
1
- # frozen_string_literal: true
2
-
3
- module Dendroid
4
- module Parsing
5
- class ParseNode
6
- # @return [Array<Integer>] The range of input tokens that match this node.
7
- attr_reader :range
8
-
9
- def initialize(lowerBound, upperBound)
10
- @range = valid_range(lowerBound, upperBound)
11
- end
12
-
13
- def to_s
14
- "[#{range[0]}, #{range[1]}]"
15
- end
16
-
17
- private
18
-
19
- def valid_range(lowerBound, upperBound)
20
- raise StandardError unless lowerBound.is_a?(Integer) && upperBound.is_a?(Integer)
21
-
22
- [lowerBound, upperBound]
23
- end
24
- end # class
25
- end # module
26
- end # module
1
+ # frozen_string_literal: true
2
+
3
+ module Dendroid
4
+ module Parsing
5
+ class ParseNode
6
+ # @return [Array<Integer>] The range of input tokens that match this node.
7
+ attr_reader :range
8
+
9
+ def initialize(lowerBound, upperBound)
10
+ @range = valid_range(lowerBound, upperBound)
11
+ end
12
+
13
+ def to_s
14
+ "[#{range[0]}, #{range[1]}]"
15
+ end
16
+
17
+ private
18
+
19
+ def valid_range(lowerBound, upperBound)
20
+ raise StandardError unless lowerBound.is_a?(Integer) && upperBound.is_a?(Integer)
21
+
22
+ [lowerBound, upperBound]
23
+ end
24
+ end # class
25
+ end # module
26
+ end # module
@@ -1,127 +1,127 @@
1
- # frozen_string_literal: true
2
-
3
- class ParseTreeVisitor
4
- # Link to the result root node of the tree (forest)
5
- attr_reader(:root)
6
-
7
- # List of objects that subscribed to the visit event notification.
8
- attr_reader(:subscribers)
9
-
10
- # Indicates the kind of tree traversal to perform: :post_order, :pre-order
11
- attr_reader(:traversal)
12
-
13
- # Build a visitor for the given root.
14
- # @param aParseTree [ParseTree] the parse tree to visit.
15
- def initialize(aParseTree, aTraversalStrategy = :post_order)
16
- raise StandardError if aParseTree.nil?
17
-
18
- @root = aParseTree
19
- @subscribers = []
20
- @traversal = aTraversalStrategy
21
- end
22
-
23
- # Add a subscriber for the visit event notifications.
24
- # @param aSubscriber [Object]
25
- def subscribe(aSubscriber)
26
- subscribers << aSubscriber
27
- end
28
-
29
- # Remove the given object from the subscription list.
30
- # The object won't be notified of visit events.
31
- # @param aSubscriber [Object]
32
- def unsubscribe(aSubscriber)
33
- subscribers.delete_if { |entry| entry == aSubscriber }
34
- end
35
-
36
- # The signal to begin the visit of the parse tree.
37
- def start
38
- root.accept(self)
39
- end
40
-
41
- # Visit event. The visitor is about to visit the root.
42
- # @param aParseTree [ParseTree] the root to visit.
43
- def start_visit_root(aParseTree)
44
- broadcast(:before_root, aParseTree)
45
- end
46
-
47
- # Visit event. The visitor is about to visit the given non terminal node.
48
- # @param aNonTerminalNode [ANDNode] the node to visit.
49
- def visit_and_node(aNonTerminalNode)
50
- if @traversal == :post_order
51
- broadcast(:before_and_node, aNonTerminalNode)
52
- traverse_subnodes(aNonTerminalNode)
53
- else
54
- traverse_subnodes(aNonTerminalNode)
55
- broadcast(:before_and_node, aNonTerminalNode)
56
- end
57
- broadcast(:after_and_node, aNonTerminalNode)
58
- end
59
-
60
- # Visit event. The visitor is about to visit the given non terminal node.
61
- # @param aNonTerminalNode [OrNode] the node to visit.
62
- def visit_or_node(aNonTerminalNode)
63
- if @traversal == :post_order
64
- broadcast(:before_or_node, aNonTerminalNode)
65
- traverse_subnodes(aNonTerminalNode)
66
- else
67
- traverse_subnodes(aNonTerminalNode)
68
- broadcast(:before_or_node, aNonTerminalNode)
69
- end
70
- broadcast(:after_or_node, aNonTerminalNode)
71
- end
72
-
73
- # Visit event. The visitor is visiting the
74
- # given terminal node.
75
- # @param anEmptyRuleNode [EmptyRuleNode] the node to visit.
76
- def visit_empty_rule_node(anEmptyRuleNode)
77
- broadcast(:before_empty_rule_node, anEmptyRuleNode)
78
- broadcast(:after_empty_rule_node, anEmptyRuleNode)
79
- end
80
-
81
- # Visit event. The visitor is visiting the
82
- # given terminal node.
83
- # @param aTerminalNode [TerminalNode] the terminal to visit.
84
- def visit_terminal(aTerminalNode)
85
- broadcast(:before_terminal, aTerminalNode)
86
- broadcast(:after_terminal, aTerminalNode)
87
- end
88
-
89
- # Visit event. The visitor has completed its visit of the given
90
- # non-terminal node.
91
- # @param aNonTerminalNode [NonTerminalNode] the node to visit.
92
- def end_visit_nonterminal(aNonTerminalNode)
93
- broadcast(:after_and_node, aNonTerminalNode)
94
- end
95
-
96
- # Visit event. The visitor has completed the visit of the root.
97
- # @param aParseTree [ParseTree] the root to visit.
98
- def end_visit_root(aParseTree)
99
- broadcast(:after_root, aParseTree)
100
- end
101
-
102
- private
103
-
104
- # Visit event. The visitor is about to visit the subnodes of a non
105
- # terminal node.
106
- # @param aParentNode [NonTeminalNode] the (non-terminal) parent node.
107
- def traverse_subnodes(aParentNode)
108
- subnodes = aParentNode.children
109
- broadcast(:before_subnodes, aParentNode, subnodes)
110
-
111
- # Let's proceed with the visit of subnodes
112
- subnodes.each { |a_node| a_node.accept(self) }
113
-
114
- broadcast(:after_subnodes, aParentNode, subnodes)
115
- end
116
-
117
- # Send a notification to all subscribers.
118
- # @param msg [Symbol] event to notify
119
- # @param args [Array] arguments of the notification.
120
- def broadcast(msg, *args)
121
- subscribers.each do |subscr|
122
- next unless subscr.respond_to?(msg) || subscr.respond_to?(:accept_all)
123
-
124
- subscr.send(msg, *args)
125
- end
126
- end
127
- end # class
1
+ # frozen_string_literal: true
2
+
3
+ class ParseTreeVisitor
4
+ # Link to the result root node of the tree (forest)
5
+ attr_reader(:root)
6
+
7
+ # List of objects that subscribed to the visit event notification.
8
+ attr_reader(:subscribers)
9
+
10
+ # Indicates the kind of tree traversal to perform: :post_order, :pre-order
11
+ attr_reader(:traversal)
12
+
13
+ # Build a visitor for the given root.
14
+ # @param aParseTree [ParseTree] the parse tree to visit.
15
+ def initialize(aParseTree, aTraversalStrategy = :post_order)
16
+ raise StandardError if aParseTree.nil?
17
+
18
+ @root = aParseTree
19
+ @subscribers = []
20
+ @traversal = aTraversalStrategy
21
+ end
22
+
23
+ # Add a subscriber for the visit event notifications.
24
+ # @param aSubscriber [Object]
25
+ def subscribe(aSubscriber)
26
+ subscribers << aSubscriber
27
+ end
28
+
29
+ # Remove the given object from the subscription list.
30
+ # The object won't be notified of visit events.
31
+ # @param aSubscriber [Object]
32
+ def unsubscribe(aSubscriber)
33
+ subscribers.delete_if { |entry| entry == aSubscriber }
34
+ end
35
+
36
+ # The signal to begin the visit of the parse tree.
37
+ def start
38
+ root.accept(self)
39
+ end
40
+
41
+ # Visit event. The visitor is about to visit the root.
42
+ # @param aParseTree [ParseTree] the root to visit.
43
+ def start_visit_root(aParseTree)
44
+ broadcast(:before_root, aParseTree)
45
+ end
46
+
47
+ # Visit event. The visitor is about to visit the given non terminal node.
48
+ # @param aNonTerminalNode [ANDNode] the node to visit.
49
+ def visit_and_node(aNonTerminalNode)
50
+ if @traversal == :post_order
51
+ broadcast(:before_and_node, aNonTerminalNode)
52
+ traverse_subnodes(aNonTerminalNode)
53
+ else
54
+ traverse_subnodes(aNonTerminalNode)
55
+ broadcast(:before_and_node, aNonTerminalNode)
56
+ end
57
+ broadcast(:after_and_node, aNonTerminalNode)
58
+ end
59
+
60
+ # Visit event. The visitor is about to visit the given non terminal node.
61
+ # @param aNonTerminalNode [OrNode] the node to visit.
62
+ def visit_or_node(aNonTerminalNode)
63
+ if @traversal == :post_order
64
+ broadcast(:before_or_node, aNonTerminalNode)
65
+ traverse_subnodes(aNonTerminalNode)
66
+ else
67
+ traverse_subnodes(aNonTerminalNode)
68
+ broadcast(:before_or_node, aNonTerminalNode)
69
+ end
70
+ broadcast(:after_or_node, aNonTerminalNode)
71
+ end
72
+
73
+ # Visit event. The visitor is visiting the
74
+ # given terminal node.
75
+ # @param anEmptyRuleNode [EmptyRuleNode] the node to visit.
76
+ def visit_empty_rule_node(anEmptyRuleNode)
77
+ broadcast(:before_empty_rule_node, anEmptyRuleNode)
78
+ broadcast(:after_empty_rule_node, anEmptyRuleNode)
79
+ end
80
+
81
+ # Visit event. The visitor is visiting the
82
+ # given terminal node.
83
+ # @param aTerminalNode [TerminalNode] the terminal to visit.
84
+ def visit_terminal(aTerminalNode)
85
+ broadcast(:before_terminal, aTerminalNode)
86
+ broadcast(:after_terminal, aTerminalNode)
87
+ end
88
+
89
+ # Visit event. The visitor has completed its visit of the given
90
+ # non-terminal node.
91
+ # @param aNonTerminalNode [NonTerminalNode] the node to visit.
92
+ def end_visit_nonterminal(aNonTerminalNode)
93
+ broadcast(:after_and_node, aNonTerminalNode)
94
+ end
95
+
96
+ # Visit event. The visitor has completed the visit of the root.
97
+ # @param aParseTree [ParseTree] the root to visit.
98
+ def end_visit_root(aParseTree)
99
+ broadcast(:after_root, aParseTree)
100
+ end
101
+
102
+ private
103
+
104
+ # Visit event. The visitor is about to visit the subnodes of a non
105
+ # terminal node.
106
+ # @param aParentNode [NonTeminalNode] the (non-terminal) parent node.
107
+ def traverse_subnodes(aParentNode)
108
+ subnodes = aParentNode.children
109
+ broadcast(:before_subnodes, aParentNode, subnodes)
110
+
111
+ # Let's proceed with the visit of subnodes
112
+ subnodes.each { |a_node| a_node.accept(self) }
113
+
114
+ broadcast(:after_subnodes, aParentNode, subnodes)
115
+ end
116
+
117
+ # Send a notification to all subscribers.
118
+ # @param msg [Symbol] event to notify
119
+ # @param args [Array] arguments of the notification.
120
+ def broadcast(msg, *args)
121
+ subscribers.each do |subscr|
122
+ next unless subscr.respond_to?(msg) || subscr.respond_to?(:accept_all)
123
+
124
+ subscr.send(msg, *args)
125
+ end
126
+ end
127
+ end # class
@@ -1,32 +1,32 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'parse_node'
4
-
5
- module Dendroid
6
- module Parsing
7
- class TerminalNode < ParseNode
8
- # @return [Dendroid::Syntax::Terminal] Terminal symbol of matching token.
9
- attr_reader :symbol
10
-
11
- # @return [Dendroid::Lexical::Token] Matching input token object.
12
- attr_reader :token
13
-
14
- def initialize(sym, tok, rank)
15
- super(rank, rank + 1)
16
- @symbol = sym
17
- @token = tok
18
- end
19
-
20
- # Part of the 'visitee' role in Visitor design pattern.
21
- # @param aVisitor[ParseTreeVisitor] the visitor
22
- def accept(aVisitor)
23
- aVisitor.visit_terminal(self)
24
- end
25
-
26
- def to_s()
27
- display_val = token.is_a?(Dendroid::Lexical::Literal) ? ": #{token.value}" : ''
28
- "#{symbol.name}#{display_val} #{super}"
29
- end
30
- end # class
31
- end # module
32
- end # module
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'parse_node'
4
+
5
+ module Dendroid
6
+ module Parsing
7
+ class TerminalNode < ParseNode
8
+ # @return [Dendroid::Syntax::Terminal] Terminal symbol of matching token.
9
+ attr_reader :symbol
10
+
11
+ # @return [Dendroid::Lexical::Token] Matching input token object.
12
+ attr_reader :token
13
+
14
+ def initialize(sym, tok, rank)
15
+ super(rank, rank + 1)
16
+ @symbol = sym
17
+ @token = tok
18
+ end
19
+
20
+ # Part of the 'visitee' role in Visitor design pattern.
21
+ # @param aVisitor[ParseTreeVisitor] the visitor
22
+ def accept(aVisitor)
23
+ aVisitor.visit_terminal(self)
24
+ end
25
+
26
+ def to_s
27
+ display_val = token.is_a?(Dendroid::Lexical::Literal) ? ": #{token.value}" : ''
28
+ "#{symbol.name}#{display_val} #{super}"
29
+ end
30
+ end # class
31
+ end # module
32
+ end # module