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.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +16 -0
- data/lib/dendroid/formatters/ascii_tree.rb +142 -142
- data/lib/dendroid/formatters/base_formatter.rb +24 -25
- data/lib/dendroid/formatters/bracket_notation.rb +50 -50
- data/lib/dendroid/grm_analysis/dotted_item.rb +0 -1
- data/lib/dendroid/grm_analysis/grm_analyzer.rb +9 -1
- data/lib/dendroid/grm_analysis/rule_items.rb +1 -1
- data/lib/dendroid/parsing/and_node.rb +54 -56
- data/lib/dendroid/parsing/chart_walker.rb +301 -293
- data/lib/dendroid/parsing/composite_parse_node.rb +20 -21
- data/lib/dendroid/parsing/empty_rule_node.rb +28 -28
- data/lib/dendroid/parsing/or_node.rb +46 -51
- data/lib/dendroid/parsing/parse_node.rb +26 -26
- data/lib/dendroid/parsing/parse_tree_visitor.rb +127 -127
- data/lib/dendroid/parsing/terminal_node.rb +32 -32
- data/lib/dendroid/parsing/walk_progress.rb +121 -117
- data/lib/dendroid/recognizer/chart.rb +1 -6
- data/lib/dendroid/recognizer/recognizer.rb +12 -6
- data/lib/dendroid/syntax/grammar.rb +3 -5
- data/lib/dendroid/syntax/rule.rb +1 -1
- data/lib/dendroid.rb +13 -0
- data/spec/dendroid/grm_analysis/dotted_item_spec.rb +1 -1
- data/spec/dendroid/parsing/chart_walker_spec.rb +250 -223
- data/spec/dendroid/parsing/terminal_node_spec.rb +36 -36
- data/spec/dendroid/recognizer/recognizer_spec.rb +0 -1
- data/spec/dendroid/support/sample_grammars.rb +0 -2
- data/version.txt +1 -1
- metadata +3 -4
- data/lib/dendroid/parsing/parser.rb +0 -185
@@ -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
|
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
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
end
|
34
|
-
|
35
|
-
def
|
36
|
-
#
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
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
|