rockit 0.7.1 → 0.7.2
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.
- data/README +24 -160
- data/TODO +17 -17
- data/VERSION +1 -1
- data/doc/rockit_paper.pdf +0 -0
- data/lib/packrat/grammar.rb +139 -84
- data/rakefile +27 -9
- data/tests/acceptance/packrat/java/atest_java.rb +37 -0
- data/tests/acceptance/packrat/java/java.rb +136 -0
- data/tests/acceptance/packrat/java/t.rb +10 -0
- data/tests/acceptance/packrat/java/todo +10 -0
- data/tests/acceptance/packrat/java/xtc.lang.java/Java.rats +446 -0
- data/tests/acceptance/packrat/java/xtc.lang.java/JavaConstant.rats +111 -0
- data/tests/acceptance/packrat/java/xtc.lang.java/JavaCore.rats +508 -0
- data/tests/acceptance/packrat/java/xtc.lang.java/JavaIdentifier.rats +62 -0
- data/tests/acceptance/packrat/java/xtc.lang.java/JavaSymbol.rats +38 -0
- data/tests/acceptance/packrat/java/xtc.lang.java/JavaTree.rats +40 -0
- data/tests/acceptance/packrat/java/xtc.lang.java/JavaType.rats +61 -0
- data/tests/acceptance/packrat/java/xtc.lang.java/Spacing.rats +36 -0
- data/tests/acceptance/packrat/java/xtc.lang.java/Symbol.rats +77 -0
- data/tests/acceptance/packrat/minibasic/README +13 -0
- data/tests/acceptance/packrat/minibasic/atest_minibasic.rb +151 -13
- data/tests/acceptance/packrat/minibasic/minibasic.rb +94 -76
- data/tests/acceptance/packrat/minibasic/mult3.basic +6 -0
- data/tests/acceptance/packrat/minibasic/sumeven.basic +19 -0
- data/tests/unit/packrat/test_ast.rb +116 -0
- data/tests/unit/packrat/test_interpreting_parser.rb +15 -55
- metadata +22 -59
- data/lib/rockit/prettyprint/box.rb +0 -60
- data/lib/rockit/prettyprint/renderer.rb +0 -41
- data/lib/rockit/prettyprint/text_renderer.rb +0 -47
- data/lib/rockit/tree/base.rb +0 -223
- data/lib/rockit/tree/enter_leave_visitor.rb +0 -12
- data/lib/rockit/tree/graphviz.rb +0 -69
- data/lib/rockit/tree/visitor.rb +0 -12
- data/lib/util/array_alternatives.rb +0 -20
- data/lib/util/enter_leave_visitor.rb +0 -69
- data/lib/util/graphviz_dot.rb +0 -182
- data/lib/util/string_location.rb +0 -42
- data/lib/util/visitor.rb +0 -49
- data/lib/util/visitor_combinators.rb +0 -14
- data/tests/acceptance/rockit/dparser/atest_any_operator.rb +0 -33
- data/tests/acceptance/rockit/dparser/atest_arithmetic_grammar.rb +0 -30
- data/tests/acceptance/rockit/dparser/atest_list_operator.rb +0 -57
- data/tests/acceptance/rockit/dparser/atest_mult_operator.rb +0 -60
- data/tests/acceptance/rockit/dparser/atest_operator_grammar.rb +0 -61
- data/tests/acceptance/rockit/dparser/atest_plus_operator.rb +0 -55
- data/tests/acceptance/rockit/dparser/atest_samples_calculator.rb +0 -14
- data/tests/acceptance/rockit/dparser/atest_samples_minibasic.rb +0 -20
- data/tests/acceptance/rockit/dparser/atest_samples_multifunccalculator.rb +0 -36
- data/tests/acceptance/rockit/dparser/atest_simple_grammar.rb +0 -34
- data/tests/acceptance/rockit/dparser/atest_speculative_code_action.rb +0 -128
- data/tests/acceptance/rockit/dparser/calc_tests_common.rb +0 -103
- data/tests/unit/parse/utest_ebnf_grammar.rb +0 -50
- data/tests/unit/parse/utest_expand_grammar.rb +0 -23
- data/tests/unit/parse/utest_grammar.rb +0 -160
- data/tests/unit/rockit/assembler/llvm/utest_instructions.rb +0 -41
- data/tests/unit/rockit/assembler/llvm/utest_module.rb +0 -19
- data/tests/unit/rockit/prettyprint/utest_box.rb +0 -44
- data/tests/unit/rockit/tree/utest_tree_base.rb +0 -301
- data/tests/unit/rockit/tree/utest_tree_enter_leave_visitor.rb +0 -69
- data/tests/unit/rockit/tree/utest_tree_visitor.rb +0 -63
- data/tests/unit/rockit/utest_grammar.rb +0 -145
- data/tests/unit/rockit/utest_grammar_symbol.rb +0 -11
- data/tests/unit/rockit/utest_maybe_operator.rb +0 -12
- data/tests/unit/rockit/utest_regexp_terminal.rb +0 -45
- data/tests/unit/rockit/utest_repetition_operators.rb +0 -35
- data/tests/unit/rockit/utest_rule.rb +0 -23
- data/tests/unit/rockit/utest_string_terminal.rb +0 -40
- data/tests/unit/util/utest_array_alternatives.rb +0 -23
- data/tests/unit/util/utest_enter_leave_visitor.rb +0 -89
- data/tests/unit/util/utest_string_location.rb +0 -42
- data/tests/unit/util/utest_visitor.rb +0 -92
- data/tests/unit/util/utest_visitor_combinators.rb +0 -64
data/lib/rockit/tree/visitor.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
# Collect alternatives to an array by pushing them onto an internal
|
2
|
-
# instance variable @__alternatives. We can then assemble all the alternatives
|
3
|
-
# (including self) into an Array. This is used for specifying alternative
|
4
|
-
# RightHandSides in a Rule in a Grammar.
|
5
|
-
class Array
|
6
|
-
def __alternatives
|
7
|
-
@__alternatives ||= Array.new
|
8
|
-
end
|
9
|
-
|
10
|
-
def /(other)
|
11
|
-
self.__alternatives << other
|
12
|
-
self
|
13
|
-
end
|
14
|
-
|
15
|
-
def assemble_alternatives
|
16
|
-
alternatives = self.__alternatives
|
17
|
-
alternatives.unshift self
|
18
|
-
alternatives
|
19
|
-
end
|
20
|
-
end
|
@@ -1,69 +0,0 @@
|
|
1
|
-
require 'util/visitor'
|
2
|
-
|
3
|
-
# An EnterLeaveVisitor is a Visitor that visits objects both on the way down
|
4
|
-
# and on the way up when traversing an object structure/hierarchy.
|
5
|
-
# It will first call enter_X(x) if available, then visit_X(x) if avilable
|
6
|
-
# then traverse down into children objects and then call leave_X(x) if
|
7
|
-
# available.
|
8
|
-
# Objects use visit_all to indicate structure. The first argument to visit_all
|
9
|
-
# is a parent object and the rest are children objects.
|
10
|
-
# NOTE! If they simply call visit the leave method will never be called but
|
11
|
-
# the enter and visit methods will.
|
12
|
-
module EnterLeaveVisitor
|
13
|
-
include Visitor
|
14
|
-
|
15
|
-
def visit(obj)
|
16
|
-
visit_me_then_children(obj)
|
17
|
-
end
|
18
|
-
|
19
|
-
def enter(obj)
|
20
|
-
method = _enter_method(obj)
|
21
|
-
self.send(method, obj) if method
|
22
|
-
end
|
23
|
-
|
24
|
-
def leave(obj)
|
25
|
-
method = _leave_method(obj)
|
26
|
-
self.send(method, obj) if method
|
27
|
-
end
|
28
|
-
|
29
|
-
# Each children should be an array with children
|
30
|
-
def visit_me_then_children(parent, *children)
|
31
|
-
enter_method, visit_method, leave_method = _evl_methods(parent)
|
32
|
-
self.send(enter_method, parent) if enter_method
|
33
|
-
self.send(visit_method, parent) if visit_method
|
34
|
-
children.each {|cs| cs.each {|c| c.accept_visitor(self)}}
|
35
|
-
self.send(leave_method, parent) if leave_method
|
36
|
-
end
|
37
|
-
|
38
|
-
def _evl_methods(obj)
|
39
|
-
obj.class.ancestors.map {|c| _evl_methods_for_class(c)}.compact.first
|
40
|
-
end
|
41
|
-
|
42
|
-
def _evl_methods_for_class(klass)
|
43
|
-
# Memoized so not dynamic, maybe we should clear cache when a method is
|
44
|
-
# added?
|
45
|
-
(@_memoized_methods ||= Hash.new)[klass] ||= _methodnames_from_class(klass)
|
46
|
-
end
|
47
|
-
|
48
|
-
def _methodname_from_classname(klassName, prefix)
|
49
|
-
name = prefix + klassName
|
50
|
-
self.class.instance_methods.include?(name) ? name : nil
|
51
|
-
end
|
52
|
-
|
53
|
-
def _methodnames_from_class(klass)
|
54
|
-
class_name = klass.inspect.split("::").last
|
55
|
-
l = ["enter_", "visit_", "leave_"].map do |prefix|
|
56
|
-
_methodname_from_classname(class_name, prefix)
|
57
|
-
end
|
58
|
-
# Return nil unless we found at least one method to visit
|
59
|
-
(l.compact.length > 0) ? l : nil
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
module EnterLeaveVisitable
|
64
|
-
include Visitable
|
65
|
-
end
|
66
|
-
|
67
|
-
class Object
|
68
|
-
include EnterLeaveVisitable
|
69
|
-
end
|
data/lib/util/graphviz_dot.rb
DELETED
@@ -1,182 +0,0 @@
|
|
1
|
-
class DotGraphPrinter
|
2
|
-
attr_accessor :orientation, :size, :color
|
3
|
-
|
4
|
-
# The following can be set to blocks of code that gives a default
|
5
|
-
# value for the node shapes, node labels and link labels, respectively.
|
6
|
-
attr_accessor :node_shaper, :node_labeler, :link_labeler
|
7
|
-
|
8
|
-
# A node shaper maps each node to a string describing its shape.
|
9
|
-
# Valid shapes are:
|
10
|
-
# "ellipse" (default)
|
11
|
-
# "box"
|
12
|
-
# "circle"
|
13
|
-
# "plaintext" (no outline)
|
14
|
-
# "doublecircle"
|
15
|
-
# "diamond"
|
16
|
-
# Not yet supported or untested once are:
|
17
|
-
# "polygon", "record", "epsf"
|
18
|
-
@@default_node_shaper = proc{|n| "box"}
|
19
|
-
|
20
|
-
@@default_node_labeler = proc{|n|
|
21
|
-
if Symbol===n
|
22
|
-
n.id2name
|
23
|
-
elsif String===n
|
24
|
-
n
|
25
|
-
else
|
26
|
-
n.inspect
|
27
|
-
end
|
28
|
-
}
|
29
|
-
|
30
|
-
@@default_link_labeler = proc{|info| info ? info.inspect : nil}
|
31
|
-
|
32
|
-
# links is either array of
|
33
|
-
# arrays [fromNode, toNode [, infoOnLink]], or
|
34
|
-
# objects with attributes :from, :to, :info
|
35
|
-
# nodes is array of node objects
|
36
|
-
# All nodes used in the links are used as nodes even if they are not
|
37
|
-
# in the "nodes" parameters.
|
38
|
-
def initialize(links = [], nodes = [])
|
39
|
-
@links, @nodes = links, add_nodes_in_links(links, nodes)
|
40
|
-
@node_attributes, @edge_attributes = Hash.new, Hash.new
|
41
|
-
set_default_values
|
42
|
-
end
|
43
|
-
|
44
|
-
def set_default_values
|
45
|
-
@color = "black"
|
46
|
-
@size = "9,11"
|
47
|
-
@orientation = "portrait"
|
48
|
-
@node_shaper = @@default_node_shaper
|
49
|
-
@node_labeler = @@default_node_labeler
|
50
|
-
@link_labeler = @@default_link_labeler
|
51
|
-
end
|
52
|
-
|
53
|
-
def write_to_file(filename, fileType = "ps")
|
54
|
-
dotfile = temp_filename(filename)
|
55
|
-
File.open(dotfile, "w") {|f| f.write to_dot_specification}
|
56
|
-
system "dot -T#{fileType} -o #{filename} #{dotfile}"
|
57
|
-
File.delete(dotfile)
|
58
|
-
end
|
59
|
-
|
60
|
-
def set_edge_attributes(anEdge, aHash)
|
61
|
-
# TODO check if attributes are valid dot edge attributes
|
62
|
-
edge = find_edge(anEdge)
|
63
|
-
set_attributes(edge, @edge_attributes, true, aHash)
|
64
|
-
end
|
65
|
-
|
66
|
-
def set_node_attributes(aNode, aHash)
|
67
|
-
# TODO check if attributes are valid dot node attributes
|
68
|
-
set_attributes(aNode, @node_attributes, true, aHash)
|
69
|
-
end
|
70
|
-
|
71
|
-
def to_dot_specification
|
72
|
-
set_edge_labels(@links)
|
73
|
-
set_node_labels_and_shape(@nodes)
|
74
|
-
"digraph G {\n" +
|
75
|
-
graph_parameters_to_dot_specification +
|
76
|
-
@nodes.uniq.map {|n| format_node(n)}.join(";\n") + ";\n" +
|
77
|
-
@links.uniq.map {|l| format_link(l)}.join(";\n") + ";\n" +
|
78
|
-
"}"
|
79
|
-
end
|
80
|
-
|
81
|
-
protected
|
82
|
-
|
83
|
-
def find_edge(anEdge)
|
84
|
-
@links.each do |link|
|
85
|
-
return link if source_and_dest(link) == source_and_dest(anEdge)
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
def set_attributes(key, hash, override, newAttributeHash)
|
90
|
-
h = hash[key] || Hash.new
|
91
|
-
newAttributeHash = all_keys_to_s(newAttributeHash)
|
92
|
-
newAttributeHash.each do |k, value|
|
93
|
-
h[k] = value unless h[k] and !override
|
94
|
-
end
|
95
|
-
hash[key] = h
|
96
|
-
end
|
97
|
-
|
98
|
-
def graph_parameters_to_dot_specification
|
99
|
-
"graph [\n" +
|
100
|
-
(self.size ? " size = #{@size.inspect},\n" : "") +
|
101
|
-
(self.orientation ? " orientation = #{@orientation},\n" : "") +
|
102
|
-
(self.color ? " color = #{@color}\n" : "") +
|
103
|
-
"]\n"
|
104
|
-
end
|
105
|
-
|
106
|
-
def each_node_in_links(links)
|
107
|
-
links.each do |l|
|
108
|
-
src, dest = source_and_dest(l)
|
109
|
-
yield src
|
110
|
-
yield dest
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
def add_nodes_in_links(links, nodes)
|
115
|
-
new_nodes = []
|
116
|
-
each_node_in_links(links) {|node| new_nodes.push node}
|
117
|
-
(nodes + new_nodes).uniq
|
118
|
-
end
|
119
|
-
|
120
|
-
def all_keys_to_s(aHash)
|
121
|
-
# MAYBE reuse existing hash?
|
122
|
-
Hash[*(aHash.map{|p| p[0] = p[0].to_s; p}.flatten)]
|
123
|
-
end
|
124
|
-
|
125
|
-
def set_edge_labels(edges)
|
126
|
-
edges.each do |edge|
|
127
|
-
src, dest, info = get_link_data(edge)
|
128
|
-
if info
|
129
|
-
label = @link_labeler.call(info)
|
130
|
-
set_attributes(edge, @edge_attributes, false, :label =>label) if label
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
def set_node_labels_and_shape(nodes)
|
136
|
-
nodes.each do |node|
|
137
|
-
set_attributes(node, @node_attributes, false,
|
138
|
-
:label => @node_labeler.call(node).inspect,
|
139
|
-
:shape => @node_shaper.call(node).inspect)
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
def get_link_data(link)
|
144
|
-
begin
|
145
|
-
return link.from, link.to, link.info
|
146
|
-
rescue Exception
|
147
|
-
return link[0], link[1], link[2]
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
def source_and_dest(link)
|
152
|
-
get_link_data(link)[0,2]
|
153
|
-
end
|
154
|
-
|
155
|
-
def format_attributes(attributes)
|
156
|
-
return "" unless attributes
|
157
|
-
strings = attributes.map {|a, v| "#{a}=#{v}"}
|
158
|
-
strings.length > 0 ? (" [" + strings.join(", ") + "]") : ("")
|
159
|
-
end
|
160
|
-
|
161
|
-
def mangle_node_name(node)
|
162
|
-
"n" + node.hash.abs.inspect
|
163
|
-
end
|
164
|
-
|
165
|
-
def format_link(link)
|
166
|
-
from, to, info = get_link_data(link)
|
167
|
-
mangle_node_name(from) + " -> " + mangle_node_name(to) +
|
168
|
-
format_attributes(@edge_attributes[link])
|
169
|
-
end
|
170
|
-
|
171
|
-
def format_node(node)
|
172
|
-
mangle_node_name(node) + format_attributes(@node_attributes[node])
|
173
|
-
end
|
174
|
-
|
175
|
-
def temp_filename(base = "tmp")
|
176
|
-
tmpfile = base + rand(100000).inspect
|
177
|
-
while test(?f, tmpfile)
|
178
|
-
tmpfile = base + rand(100000).inspect
|
179
|
-
end
|
180
|
-
tmpfile
|
181
|
-
end
|
182
|
-
end
|
data/lib/util/string_location.rb
DELETED
@@ -1,42 +0,0 @@
|
|
1
|
-
# A class for calculating locations (line, column) in a string based
|
2
|
-
# on an offset.
|
3
|
-
class StringLocations
|
4
|
-
def initialize(string)
|
5
|
-
@string, @string_length = string, string.length
|
6
|
-
@line_lengths = @string.split(/\n/).map {|l| l.length}
|
7
|
-
@start_pos_of_line = [0]
|
8
|
-
@line_lengths.each do |l|
|
9
|
-
@start_pos_of_line << @start_pos_of_line.last + l + 1
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
def location(offset)
|
14
|
-
l = line(offset)
|
15
|
-
return l, column(offset, l)
|
16
|
-
end
|
17
|
-
|
18
|
-
def column(offset, l = nil)
|
19
|
-
l ||= line(offset)
|
20
|
-
offset - @start_pos_of_line[l-1]
|
21
|
-
end
|
22
|
-
|
23
|
-
def line(offset)
|
24
|
-
if offset >= @string_length
|
25
|
-
raise "#{offset} is larger than the string size #{@string_length}"
|
26
|
-
end
|
27
|
-
line_index(offset) + 1
|
28
|
-
end
|
29
|
-
|
30
|
-
# Find the index to the line where the given offset can be found. Assumes
|
31
|
-
# the start_pos_of_line array has been extended so that offset is covered.
|
32
|
-
def line_index(offset)
|
33
|
-
index = nil
|
34
|
-
for index in (0...(@start_pos_of_line.length))
|
35
|
-
if @start_pos_of_line[index] <= offset &&
|
36
|
-
@start_pos_of_line[index+1] > offset
|
37
|
-
break
|
38
|
-
end
|
39
|
-
end
|
40
|
-
index
|
41
|
-
end
|
42
|
-
end
|
data/lib/util/visitor.rb
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
module Visitor
|
2
|
-
def visit(obj)
|
3
|
-
method = _visitor_method(obj)
|
4
|
-
self.send(method, obj) if method
|
5
|
-
end
|
6
|
-
|
7
|
-
def visit_me_and_my_children(me, children)
|
8
|
-
visit(me)
|
9
|
-
children.each {|c| c.accept_visitor(self)}
|
10
|
-
end
|
11
|
-
|
12
|
-
def visit_me_then_children(obj, *children)
|
13
|
-
visit(obj)
|
14
|
-
children.each {|cs| cs.each {|c| c.accept_visitor(self)}}
|
15
|
-
end
|
16
|
-
|
17
|
-
# Find the visit_X method to use based on the inheritance tree. First try
|
18
|
-
# the class name then traverse the ancestors list.
|
19
|
-
def _visitor_method(obj)
|
20
|
-
obj.class.ancestors.map {|c| _visitor_method_for_class(c)}.compact.first
|
21
|
-
end
|
22
|
-
|
23
|
-
def _visitor_method_for_class(klass)
|
24
|
-
_visitor_methods[klass] ||= _methodname_from_class(klass)
|
25
|
-
end
|
26
|
-
|
27
|
-
def _visitor_methods
|
28
|
-
@_visitor_methods ||= Hash.new
|
29
|
-
end
|
30
|
-
|
31
|
-
def _methodname_from_class(klass)
|
32
|
-
name = "visit_" + klass.inspect.split("::").last
|
33
|
-
self.class.instance_methods.include?(name) ? name : nil
|
34
|
-
end
|
35
|
-
|
36
|
-
def visit_each(ary)
|
37
|
-
ary.each {|e| e.accept_visitor(self)}
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
module Visitable
|
42
|
-
def accept_visitor(visitor)
|
43
|
-
visitor.visit(self)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
class Object
|
48
|
-
include Visitable
|
49
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
require 'test/unit'
|
2
|
-
require 'rockit/dparser'
|
3
|
-
|
4
|
-
class ATestAnyOperator < Test::Unit::TestCase
|
5
|
-
AnyTestGrammar = Rockit::DParser::Grammar.new do
|
6
|
-
start :S, [["a", any("b", "c"), any(:D, :E), ast(:S, 0, 1, 2)]]
|
7
|
-
("d".."e").map {|s| term(s.upcase.intern, s)}
|
8
|
-
end
|
9
|
-
|
10
|
-
Parser = AnyTestGrammar.new_parser
|
11
|
-
|
12
|
-
def test_01
|
13
|
-
ast = Parser.parse "abd"
|
14
|
-
assert_equal("a", ast[0])
|
15
|
-
assert_equal("b", ast[1])
|
16
|
-
assert_equal("d", ast[2])
|
17
|
-
|
18
|
-
ast = Parser.parse "abe"
|
19
|
-
assert_equal("a", ast[0])
|
20
|
-
assert_equal("b", ast[1])
|
21
|
-
assert_equal("e", ast[2])
|
22
|
-
|
23
|
-
ast = Parser.parse "acd"
|
24
|
-
assert_equal("a", ast[0])
|
25
|
-
assert_equal("c", ast[1])
|
26
|
-
assert_equal("d", ast[2])
|
27
|
-
|
28
|
-
ast = Parser.parse "ace"
|
29
|
-
assert_equal("a", ast[0])
|
30
|
-
assert_equal("c", ast[1])
|
31
|
-
assert_equal("e", ast[2])
|
32
|
-
end
|
33
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
require 'test/unit'
|
2
|
-
require 'rockit/dparser'
|
3
|
-
|
4
|
-
class ATestArithmeticGrammar < Test::Unit::TestCase
|
5
|
-
ArithmeticTestGrammar = Rockit::DParser::Grammar.new do
|
6
|
-
start :Expr, [
|
7
|
-
[:Digit, "+", :Digit, ast(:Add, 0, 2)],
|
8
|
-
[:Digit, "*", :Digit, ast(:Mult, 0, 2)],
|
9
|
-
]
|
10
|
-
term :Digit, /[0-9]+/
|
11
|
-
end
|
12
|
-
|
13
|
-
def test_03_use_parser
|
14
|
-
parser = ArithmeticTestGrammar.new_parser
|
15
|
-
|
16
|
-
ast = parser.parse "12+34"
|
17
|
-
assert_equal("Add", ast.name)
|
18
|
-
assert_kind_of(parser.astclass_of_name(:Add), ast)
|
19
|
-
assert_equal(2, ast.num_children)
|
20
|
-
assert_equal("12", ast[0])
|
21
|
-
assert_equal("34", ast[1])
|
22
|
-
|
23
|
-
ast = parser.parse "567*980"
|
24
|
-
assert_equal("Mult", ast.name)
|
25
|
-
assert_kind_of(parser.astclass_of_name(:Mult), ast)
|
26
|
-
assert_equal(2, ast.num_children)
|
27
|
-
assert_equal("567", ast[0])
|
28
|
-
assert_equal("980", ast[1])
|
29
|
-
end
|
30
|
-
end
|