cast 0.0.1 → 0.1.0
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 +4 -4
- data/doc/index.html +7 -15
- data/ext/cast.h +141 -0
- data/ext/cast_ext.c +10 -0
- data/ext/extconf.rb +2 -0
- data/ext/parser.c +287 -0
- data/ext/yylex.c +8189 -0
- data/ext/yylex.re +330 -0
- data/lib/cast.rb +15 -8
- data/lib/cast/c.tab.rb +3398 -0
- data/lib/{c.y → cast/c.y} +212 -270
- data/lib/{c_nodes.rb → cast/c_nodes.rb} +12 -7
- data/lib/{to_debug.rb → cast/inspect.rb} +12 -12
- data/lib/{node.rb → cast/node.rb} +0 -0
- data/lib/{node_list.rb → cast/node_list.rb} +10 -2
- data/lib/{parse.rb → cast/parse.rb} +0 -0
- data/lib/{to_s.rb → cast/to_s.rb} +12 -3
- data/test/run.rb +204 -2
- data/test/test_c_nodes.rb +5 -9
- data/test/test_node.rb +0 -10
- data/test/test_node_list.rb +20 -3
- data/test/test_parse.rb +623 -626
- data/test/test_parser.rb +80 -33
- metadata +44 -32
- data/install.rb +0 -14
- data/lib/c.tab.rb +0 -3433
- data/test/common.rb +0 -174
@@ -401,13 +401,6 @@ module C
|
|
401
401
|
initializer :cond, :then, :else
|
402
402
|
end
|
403
403
|
###
|
404
|
-
### Sizeof
|
405
|
-
###
|
406
|
-
class Sizeof
|
407
|
-
child :expr
|
408
|
-
initializer :expr
|
409
|
-
end
|
410
|
-
###
|
411
404
|
### Variable
|
412
405
|
###
|
413
406
|
class Variable
|
@@ -444,6 +437,13 @@ module C
|
|
444
437
|
initializer :expr
|
445
438
|
end
|
446
439
|
###
|
440
|
+
### Sizeof
|
441
|
+
###
|
442
|
+
class Sizeof
|
443
|
+
child :expr
|
444
|
+
initializer :expr
|
445
|
+
end
|
446
|
+
###
|
447
447
|
### Positive
|
448
448
|
###
|
449
449
|
class Positive
|
@@ -849,6 +849,7 @@ module C
|
|
849
849
|
###
|
850
850
|
class StringLiteral
|
851
851
|
field :val
|
852
|
+
field :wide?
|
852
853
|
initializer :val
|
853
854
|
end
|
854
855
|
###
|
@@ -856,6 +857,7 @@ module C
|
|
856
857
|
###
|
857
858
|
class CharLiteral
|
858
859
|
field :val
|
860
|
+
field :wide?
|
859
861
|
initializer :val
|
860
862
|
end
|
861
863
|
###
|
@@ -872,6 +874,7 @@ module C
|
|
872
874
|
class IntLiteral
|
873
875
|
field :val
|
874
876
|
field :format, :dec
|
877
|
+
field :suffix
|
875
878
|
initializer :val
|
876
879
|
def dec?
|
877
880
|
format.equal? :dec
|
@@ -888,6 +891,8 @@ module C
|
|
888
891
|
###
|
889
892
|
class FloatLiteral
|
890
893
|
field :val
|
894
|
+
field :format, :dec
|
895
|
+
field :suffix
|
891
896
|
initializer :val
|
892
897
|
end
|
893
898
|
|
@@ -1,33 +1,33 @@
|
|
1
1
|
###
|
2
2
|
### ##################################################################
|
3
3
|
###
|
4
|
-
### Node#
|
4
|
+
### Node#inspect.
|
5
5
|
###
|
6
6
|
### ##################################################################
|
7
7
|
###
|
8
8
|
|
9
9
|
module C
|
10
10
|
class Node
|
11
|
-
|
12
|
-
def
|
13
|
-
return Node.
|
11
|
+
INSPECT_TAB = ' '
|
12
|
+
def inspect
|
13
|
+
return Node.inspect1(self)
|
14
14
|
end
|
15
15
|
|
16
|
-
def Node.
|
16
|
+
def Node.inspect1 x, prefix='', indent=0, is_child=true
|
17
17
|
case x
|
18
18
|
when NodeList
|
19
19
|
if x.empty?
|
20
|
-
return "#{
|
20
|
+
return "#{INSPECT_TAB*indent}#{prefix}[]\n"
|
21
21
|
else
|
22
|
-
str = "#{
|
22
|
+
str = "#{INSPECT_TAB*indent}#{prefix}\n"
|
23
23
|
x.each do |el|
|
24
|
-
str <<
|
24
|
+
str << inspect1(el, "- ", indent+1)
|
25
25
|
end
|
26
26
|
return str
|
27
27
|
end
|
28
28
|
when Node
|
29
29
|
classname = x.class.name.gsub(/^C::/, '')
|
30
|
-
str = "#{
|
30
|
+
str = "#{INSPECT_TAB*indent}#{prefix}#{classname}"
|
31
31
|
|
32
32
|
fields = x.fields
|
33
33
|
bools, others = fields.partition{|field| field.reader.to_s[-1] == ??}
|
@@ -45,13 +45,13 @@ module C
|
|
45
45
|
## don't bother with non-child Nodes, since they may cause
|
46
46
|
## loops in the tree
|
47
47
|
(val.is_a?(Node) && !field.child?)
|
48
|
-
str <<
|
48
|
+
str << inspect1(val, "#{field.reader}: ", indent+1, field.child?)
|
49
49
|
end
|
50
50
|
return str
|
51
51
|
when Symbol
|
52
|
-
return "#{
|
52
|
+
return "#{INSPECT_TAB*indent}#{prefix}#{x}\n"
|
53
53
|
else
|
54
|
-
return "#{
|
54
|
+
return "#{INSPECT_TAB*indent}#{prefix}#{x.inspect}\n"
|
55
55
|
end
|
56
56
|
return s.string
|
57
57
|
end
|
File without changes
|
@@ -451,7 +451,11 @@ module C
|
|
451
451
|
removed_(ret)
|
452
452
|
return ret
|
453
453
|
else
|
454
|
-
|
454
|
+
args.length == 1 or
|
455
|
+
raise ArgumentError, "wrong number of arguments (#{args.length} for 0..1)"
|
456
|
+
arg = args[0]
|
457
|
+
arg = @array.length if @array.length < arg
|
458
|
+
ret = @array.slice!(-arg, arg)
|
455
459
|
removed_ *ret
|
456
460
|
return ret
|
457
461
|
end
|
@@ -461,7 +465,11 @@ module C
|
|
461
465
|
ret = @array.shift
|
462
466
|
removed_ ret
|
463
467
|
else
|
464
|
-
|
468
|
+
args.length == 1 or
|
469
|
+
raise ArgumentError, "wrong number of arguments (#{args.length} for 0..1)"
|
470
|
+
arg = args[0]
|
471
|
+
arg = @array.length if @array.length < arg
|
472
|
+
ret = @array.slice!(0, arg)
|
465
473
|
removed_ *ret
|
466
474
|
end
|
467
475
|
adjust_indices_(0)
|
File without changes
|
@@ -301,7 +301,12 @@ module C
|
|
301
301
|
else
|
302
302
|
rvalstr = "#{rval}"
|
303
303
|
end
|
304
|
-
|
304
|
+
if lval.to_s_precedence < self.to_s_precedence
|
305
|
+
lvalstr = "(#{lval})"
|
306
|
+
else
|
307
|
+
lvalstr = "#{lval}"
|
308
|
+
end
|
309
|
+
"#{lvalstr} #{op}= #{rvalstr}"
|
305
310
|
end
|
306
311
|
end
|
307
312
|
## Other Expressions
|
@@ -470,7 +475,11 @@ module C
|
|
470
475
|
class Parameter
|
471
476
|
def to_s
|
472
477
|
str = register? ? 'register ' : ''
|
473
|
-
|
478
|
+
if type
|
479
|
+
str << type.to_s(name)
|
480
|
+
else
|
481
|
+
str << name.to_s
|
482
|
+
end
|
474
483
|
end
|
475
484
|
end
|
476
485
|
|
@@ -490,7 +499,7 @@ module C
|
|
490
499
|
str = ''
|
491
500
|
type and
|
492
501
|
str << "(#{type}) "
|
493
|
-
str << "{\n" << indent(
|
502
|
+
str << "{\n" << indent(member_inits.join(",\n")) << "\n}"
|
494
503
|
end
|
495
504
|
end
|
496
505
|
class MemberInit
|
data/test/run.rb
CHANGED
@@ -1,5 +1,207 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
require 'test/unit'
|
4
|
+
require 'stringio'
|
5
|
+
|
6
|
+
# require cast
|
7
|
+
CAST_ROOT = File.expand_path('..', File.dirname(__FILE__))
|
8
|
+
ENV['CAST_EXTDIR'] = "#{CAST_ROOT}/ext"
|
9
|
+
ENV['CAST_LIBDIR'] = "#{CAST_ROOT}/lib/cast"
|
10
|
+
require "#{CAST_ROOT}/lib/cast.rb"
|
11
|
+
|
12
|
+
###
|
13
|
+
### ------------------------------------------------------------------
|
14
|
+
### Helpers for testing
|
15
|
+
### ------------------------------------------------------------------
|
16
|
+
###
|
17
|
+
|
18
|
+
class Array
|
19
|
+
def same_list? other
|
20
|
+
self.length == other.length or
|
21
|
+
return false
|
22
|
+
self.zip(other).all? do |mine, yours|
|
23
|
+
mine.equal? yours or
|
24
|
+
return false
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class Integer
|
30
|
+
###
|
31
|
+
### Return a `self'-element array containing the result of the given
|
32
|
+
### block.
|
33
|
+
###
|
34
|
+
def of &blk
|
35
|
+
Array.new(self, &blk)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
module Test::Unit::Assertions
|
40
|
+
INDENT = ' '
|
41
|
+
###
|
42
|
+
### Assert that the given string is parsed as expected. The given
|
43
|
+
### string is of the format:
|
44
|
+
###
|
45
|
+
### <program>
|
46
|
+
### ----
|
47
|
+
### <expected inspect string>
|
48
|
+
###
|
49
|
+
### The <program> part is yielded to obtain the AST.
|
50
|
+
###
|
51
|
+
def check_ast test_data
|
52
|
+
inp, exp = test_data.split(/^----+\n/)
|
53
|
+
ast = yield(inp)
|
54
|
+
assert_tree(ast)
|
55
|
+
assert(ast.is_a?(C::Node))
|
56
|
+
assert_equal_inspect_strs(exp, ast.inspect)
|
57
|
+
end
|
58
|
+
###
|
59
|
+
### Assert that the given Node#inspect strings are equal.
|
60
|
+
###
|
61
|
+
def assert_equal_inspect_strs exp, out
|
62
|
+
## remove EOL space
|
63
|
+
out = out.gsub(/ *$/, '')
|
64
|
+
exp = exp.gsub(/ *$/, '')
|
65
|
+
|
66
|
+
## normalize BOL space
|
67
|
+
exp.gsub!(%r'^#{INDENT}*') do |s|
|
68
|
+
levels = s.length / INDENT.length
|
69
|
+
C::Node::INSPECT_TAB*levels
|
70
|
+
end
|
71
|
+
|
72
|
+
## compare
|
73
|
+
msg = "Debug strings unequal:\n#{juxtapose('Expected', exp, 'Output', out)}"
|
74
|
+
assert_block(msg){out == exp}
|
75
|
+
end
|
76
|
+
###
|
77
|
+
### Return a string of `s1' and `s2' side by side with a dividing
|
78
|
+
### line in between indicating differences. `h1' and `h2' are the
|
79
|
+
### column headings.
|
80
|
+
###
|
81
|
+
def juxtapose h1, s1, h2, s2
|
82
|
+
s1 = s1.map{|line| line.chomp}
|
83
|
+
s2 = s2.map{|line| line.chomp}
|
84
|
+
rows = [s1.length, s2.length].max
|
85
|
+
wl = s1.map{|line| line.length}.max
|
86
|
+
wr = s2.map{|line| line.length}.max
|
87
|
+
ret = ''
|
88
|
+
ret << "#{('-'*wl)}----#{'-'*wr}\n"
|
89
|
+
ret << "#{h1.ljust(wl)} || #{h2}\n"
|
90
|
+
ret << "#{('-'*wl)}-++-#{'-'*wr}\n"
|
91
|
+
(0...rows).each do |i|
|
92
|
+
if i >= s1.length
|
93
|
+
ret << "#{' '*wl} > #{s2[i]}\n"
|
94
|
+
elsif i >= s2.length
|
95
|
+
ret << "#{s1[i].ljust(wl)} <\n"
|
96
|
+
elsif s1[i] == s2[i]
|
97
|
+
ret << "#{s1[i].ljust(wl)} || #{s2[i]}\n"
|
98
|
+
else
|
99
|
+
ret << "#{s1[i].ljust(wl)} <> #{s2[i]}\n"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
ret << "#{('-'*wl)}----#{'-'*wr}\n"
|
103
|
+
return ret
|
104
|
+
end
|
105
|
+
###
|
106
|
+
### Assert that an exception of the given class is raised, and that
|
107
|
+
### the message matches the given regex.
|
108
|
+
###
|
109
|
+
def assert_error klass, re
|
110
|
+
ex = nil
|
111
|
+
assert_raise(klass) do
|
112
|
+
begin
|
113
|
+
yield
|
114
|
+
rescue Exception => ex
|
115
|
+
raise
|
116
|
+
end
|
117
|
+
end
|
118
|
+
assert_match(re, ex.message)
|
119
|
+
end
|
120
|
+
###
|
121
|
+
### Assert that the given ast's nodes' parents are correct, and
|
122
|
+
### there aren't non-Nodes where there shouldn't be.
|
123
|
+
###
|
124
|
+
def assert_tree ast
|
125
|
+
meth = 'unknown method'
|
126
|
+
caller.each do |line|
|
127
|
+
if line =~ /in `(test_.*?)'/ #`
|
128
|
+
meth = $1
|
129
|
+
break
|
130
|
+
end
|
131
|
+
end
|
132
|
+
filename = "#{self.class}_#{meth}.out"
|
133
|
+
begin
|
134
|
+
assert_tree1(ast, nil)
|
135
|
+
assert(true)
|
136
|
+
rescue BadTreeError => e
|
137
|
+
require 'pp'
|
138
|
+
open("#{filename}", 'w'){|f| PP.pp(ast, f)}
|
139
|
+
flunk("#{e.message}. Output dumped to `#{filename}'.")
|
140
|
+
end
|
141
|
+
end
|
142
|
+
###
|
143
|
+
def assert_tree1 x, parent
|
144
|
+
if x.is_a? C::Node
|
145
|
+
parent.equal? x.parent or
|
146
|
+
raise BadTreeError, "#{x.class}:0x#{(x.id << 1).to_s(16)} has #{x.parent ? 'wrong' : 'no'} parent"
|
147
|
+
x.fields.each do |field|
|
148
|
+
next if !field.child?
|
149
|
+
val = x.send(field.reader)
|
150
|
+
next if val.nil?
|
151
|
+
val.is_a? C::Node or
|
152
|
+
raise BadTreeError, "#{x.class}:0x#{(x.id << 1).to_s(16)} is a non-Node child"
|
153
|
+
assert_tree1(val, x)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
class BadTreeError < StandardError; end
|
158
|
+
###
|
159
|
+
### Assert that `arg' is a C::NodeList.
|
160
|
+
###
|
161
|
+
def assert_list arg
|
162
|
+
assert_kind_of(C::NodeList, arg)
|
163
|
+
end
|
164
|
+
###
|
165
|
+
### Assert that `arg' is an empty C::NodeList.
|
166
|
+
###
|
167
|
+
def assert_empty_list arg
|
168
|
+
assert_list arg
|
169
|
+
assert(arg.empty?)
|
170
|
+
end
|
171
|
+
###
|
172
|
+
### Assert that the elements of exp are the same as those of out,
|
173
|
+
### and are in the same order.
|
174
|
+
###
|
175
|
+
def assert_same_list exp, out
|
176
|
+
assert_equal(exp.length, out.length, "Checking length")
|
177
|
+
(0...exp.length).each do |i|
|
178
|
+
assert_same(exp[i], out[i], "At index #{i} (of 0...#{exp.length})")
|
179
|
+
end
|
180
|
+
end
|
181
|
+
###
|
182
|
+
### Assert that out is ==, but not the same as exp (i.e., it is a
|
183
|
+
### copy).
|
184
|
+
###
|
185
|
+
def assert_copy exp, out
|
186
|
+
assert_not_same exp, out
|
187
|
+
assert_equal exp, out
|
188
|
+
end
|
189
|
+
###
|
190
|
+
### Assert the invariants of `node'.
|
191
|
+
###
|
192
|
+
def assert_invariants node
|
193
|
+
node.assert_invariants(self)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
###
|
198
|
+
### ------------------------------------------------------------------
|
199
|
+
### Main
|
200
|
+
### ------------------------------------------------------------------
|
201
|
+
###
|
202
|
+
|
203
|
+
if $0 == __FILE__
|
204
|
+
Dir.new(Dir.pwd).grep(/^test_/) do |filename|
|
205
|
+
require "#{Dir.pwd}/#{filename}"
|
206
|
+
end
|
5
207
|
end
|
data/test/test_c_nodes.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'common'
|
2
|
-
|
3
1
|
###
|
4
2
|
### ##################################################################
|
5
3
|
###
|
@@ -9,8 +7,6 @@ require 'common'
|
|
9
7
|
### ##################################################################
|
10
8
|
###
|
11
9
|
class MiscTests < Test::Unit::TestCase
|
12
|
-
include CheckAst
|
13
|
-
|
14
10
|
###
|
15
11
|
### ----------------------------------------------------------------
|
16
12
|
### Declarator#
|
@@ -42,22 +38,22 @@ class MiscTests < Test::Unit::TestCase
|
|
42
38
|
arr = C::Array.new(C::Pointer.new, C::IntLiteral.new(10))
|
43
39
|
decl.declarators << C::Declarator.new(arr, 'm')
|
44
40
|
|
45
|
-
|
41
|
+
assert_equal_inspect_strs(decl.declarators[0].type.inspect, <<EOS)
|
46
42
|
Int
|
47
43
|
EOS
|
48
|
-
|
44
|
+
assert_equal_inspect_strs(decl.declarators[1].type.inspect, <<EOS)
|
49
45
|
Pointer
|
50
46
|
type: Int
|
51
47
|
EOS
|
52
|
-
|
48
|
+
assert_equal_inspect_strs(decl.declarators[2].type.inspect, <<EOS)
|
53
49
|
Array
|
54
50
|
type: Int
|
55
51
|
EOS
|
56
|
-
|
52
|
+
assert_equal_inspect_strs(decl.declarators[3].type.inspect, <<EOS)
|
57
53
|
Function
|
58
54
|
type: Int
|
59
55
|
EOS
|
60
|
-
|
56
|
+
assert_equal_inspect_strs(decl.declarators[4].type.inspect, <<EOS)
|
61
57
|
Array
|
62
58
|
type: Pointer
|
63
59
|
type: Int
|
data/test/test_node.rb
CHANGED
@@ -6,16 +6,6 @@
|
|
6
6
|
### ##################################################################
|
7
7
|
###
|
8
8
|
|
9
|
-
require 'common'
|
10
|
-
require 'stringio'
|
11
|
-
|
12
|
-
require 'pp'
|
13
|
-
class C::Node
|
14
|
-
def pretty_print q
|
15
|
-
q.text self.to_debug
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
9
|
Chain = C::NodeChain
|
20
10
|
|
21
11
|
###
|