cast 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
###
|