dendroid 0.2.00 → 0.2.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.
@@ -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
@@ -130,7 +130,7 @@ case kode
130
130
  when 0
131
131
  recognizer = Dendroid::Recognizer::Recognizer.new(grammar_l1, tokenizer_l1)
132
132
  chart = recognizer.run('2 + 3 * 4')
133
- succ_item = retrieve_success_item(chart, recognizer.grm_analysis.grammar)
133
+ succ_item = retrieve_success_item(chart, recognizer.grm_analysis.grammar)
134
134
  walker = Dendroid::Parsing::ChartWalker.new(chart)
135
135
  root = walker.walk(succ_item)
136
136
 
@@ -142,7 +142,7 @@ when 0
142
142
  when 1
143
143
  recognizer = Dendroid::Recognizer::Recognizer.new(grammar_l10, tokenizer_l10)
144
144
  chart = recognizer.run('a a a a a')
145
- succ_item = retrieve_success_item(chart, recognizer.grm_analysis.grammar)
145
+ succ_item = retrieve_success_item(chart, recognizer.grm_analysis.grammar)
146
146
  walker = Dendroid::Parsing::ChartWalker.new(chart)
147
147
  root = walker.walk(succ_item)
148
148
 
@@ -153,7 +153,7 @@ when 1
153
153
  when 2
154
154
  recognizer = Dendroid::Recognizer::Recognizer.new(grammar_l11, tokenizer_l11)
155
155
  chart = recognizer.run('a a a a a')
156
- succ_item = retrieve_success_item(chart, recognizer.grm_analysis.grammar)
156
+ succ_item = retrieve_success_item(chart, recognizer.grm_analysis.grammar)
157
157
  walker = Dendroid::Parsing::ChartWalker.new(chart)
158
158
  root = walker.walk(succ_item)
159
159
 
@@ -164,7 +164,7 @@ when 2
164
164
  when 3
165
165
  recognizer = Dendroid::Recognizer::Recognizer.new(grammar_l31, tokenizer_l1)
166
166
  chart = recognizer.run('2 + 3 * 4')
167
- succ_item = retrieve_success_item(chart, recognizer.grm_analysis.grammar)
167
+ succ_item = retrieve_success_item(chart, recognizer.grm_analysis.grammar)
168
168
  walker = Dendroid::Parsing::ChartWalker.new(chart)
169
169
  root = walker.walk(succ_item)
170
170
 
@@ -175,7 +175,7 @@ when 3
175
175
  when 4
176
176
  recognizer = Dendroid::Recognizer::Recognizer.new(grammar_l8, tokenizer_l8)
177
177
  chart = recognizer.run('x x x x')
178
- succ_item = retrieve_success_item(chart, recognizer.grm_analysis.grammar)
178
+ succ_item = retrieve_success_item(chart, recognizer.grm_analysis.grammar)
179
179
  walker = Dendroid::Parsing::ChartWalker.new(chart)
180
180
  root = walker.walk(succ_item)
181
181
 
@@ -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