crokus 0.0.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.
- checksums.yaml +7 -0
- data/bin/crokus +5 -0
- data/lib/crokus.rb +4 -0
- data/lib/crokus/ast.rb +431 -0
- data/lib/crokus/ast_printer.rb +86 -0
- data/lib/crokus/cfg.rb +81 -0
- data/lib/crokus/cfg_builder.rb +169 -0
- data/lib/crokus/cfg_cleaner.rb +62 -0
- data/lib/crokus/cfg_printer.rb +73 -0
- data/lib/crokus/cleaner.rb +10 -0
- data/lib/crokus/code.rb +46 -0
- data/lib/crokus/compiler.rb +124 -0
- data/lib/crokus/generic_lexer.rb +62 -0
- data/lib/crokus/indent.rb +19 -0
- data/lib/crokus/ir_dumper.rb +48 -0
- data/lib/crokus/lexer.rb +113 -0
- data/lib/crokus/parser.rb +1072 -0
- data/lib/crokus/parser_only.rb +993 -0
- data/lib/crokus/pretty_printer.rb +443 -0
- data/lib/crokus/runner.rb +86 -0
- data/lib/crokus/tac_builder.rb +109 -0
- data/lib/crokus/token.rb +43 -0
- data/lib/crokus/transformer.rb +304 -0
- data/lib/crokus/version.rb +3 -0
- data/lib/crokus/visitor.rb +341 -0
- metadata +70 -0
@@ -0,0 +1,109 @@
|
|
1
|
+
module Crokus
|
2
|
+
|
3
|
+
class TACBuilder < Transformer
|
4
|
+
|
5
|
+
OP_ASSIGN=Token.new([:assign,"=",[0,0]])
|
6
|
+
|
7
|
+
def visitFunction func,args=nil
|
8
|
+
puts " |--> tac builder for '#{func.name}'"
|
9
|
+
build func.cfg
|
10
|
+
end
|
11
|
+
|
12
|
+
def build cfg
|
13
|
+
bb0=cfg.starter
|
14
|
+
@tmp_id=0
|
15
|
+
@visited=[]
|
16
|
+
visit_rec(bb0)
|
17
|
+
cfg.name="tac_#{cfg.name}"
|
18
|
+
cfg.print
|
19
|
+
end
|
20
|
+
|
21
|
+
def new_tmp
|
22
|
+
tok=Token.create "$"+@tmp_id.to_s
|
23
|
+
@tmp_id+=1
|
24
|
+
tok
|
25
|
+
end
|
26
|
+
|
27
|
+
def visit_rec bb
|
28
|
+
@visited << bb
|
29
|
+
@current=bb
|
30
|
+
@new_stmts=[]
|
31
|
+
@post_stmts=[]
|
32
|
+
bb.stmts.each do |stmt|
|
33
|
+
@new_stmts << stmt.accept(self)
|
34
|
+
end
|
35
|
+
bb.stmts=@new_stmts
|
36
|
+
bb.stmts << @post_stmts
|
37
|
+
bb.stmts.flatten!
|
38
|
+
bb.succs.each do |bb|
|
39
|
+
unless @visited.include? bb
|
40
|
+
visit_rec(bb)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def visitAssign assign,args=nil
|
46
|
+
assign_1= super(assign)
|
47
|
+
if assign_1.lhs.is_a? Indexed
|
48
|
+
if (rhs=assign_1.rhs).is_a? Indexed
|
49
|
+
rhs=rhs.accept(self)
|
50
|
+
tmp=new_tmp()
|
51
|
+
@new_stmts << Assign.new(tmp,OP_ASSIGN,rhs)
|
52
|
+
assign_1.rhs=tmp
|
53
|
+
end
|
54
|
+
end
|
55
|
+
unless assign.op.kind==:assign
|
56
|
+
rhs=assign_1.rhs
|
57
|
+
rhs.accept(self)
|
58
|
+
tmp=new_tmp()
|
59
|
+
@new_stmts << Assign.new(tmp,OP_ASSIGN,rhs)
|
60
|
+
assign_1.rhs=tmp
|
61
|
+
end
|
62
|
+
assign_1
|
63
|
+
end
|
64
|
+
|
65
|
+
def visitITE ite,args=nil
|
66
|
+
ret=ITE.new(ite.cond,ite.trueBranch,ite.falseBranch)
|
67
|
+
if ite.cond.is_a?(Binary)
|
68
|
+
cond=ite.cond.accept(self)
|
69
|
+
tmp=new_tmp()
|
70
|
+
@new_stmts << Assign.new(tmp,OP_ASSIGN,cond)
|
71
|
+
ret.cond=tmp
|
72
|
+
end
|
73
|
+
ret
|
74
|
+
end
|
75
|
+
|
76
|
+
def visitBinary bin,args=nil
|
77
|
+
ret=Binary.new(bin.lhs,bin.op,bin.rhs)
|
78
|
+
ret.lhs=bin.lhs.accept(self)
|
79
|
+
if bin.lhs.respond_to? :lhs #Binary,Indexed,etc
|
80
|
+
#lhs=bin.lhs.accept(self)
|
81
|
+
tmp=new_tmp()
|
82
|
+
@new_stmts << Assign.new(tmp,OP_ASSIGN,lhs)
|
83
|
+
ret.lhs=tmp
|
84
|
+
end
|
85
|
+
ret.rhs=bin.rhs.accept(self)
|
86
|
+
if bin.rhs.respond_to? :lhs #Binary,Indexed,etc
|
87
|
+
# rhs=bin.rhs.accept()
|
88
|
+
tmp=new_tmp()
|
89
|
+
@new_stmts << Assign.new(tmp,OP_ASSIGN,rhs)
|
90
|
+
ret.rhs=tmp
|
91
|
+
end
|
92
|
+
return ret
|
93
|
+
end
|
94
|
+
|
95
|
+
def visitIndexed idx,args=nil
|
96
|
+
lhs=idx.lhs.accept(self)
|
97
|
+
ret=Indexed.new(lhs,idx.rhs)
|
98
|
+
if idx.rhs.respond_to? :lhs # WARNING : Indexed! Pointed! etc
|
99
|
+
lhs=idx.rhs.accept(self)
|
100
|
+
tmp=new_tmp()
|
101
|
+
@new_stmts << Assign.new(tmp,OP_ASSIGN,lhs)
|
102
|
+
ret.rhs=tmp
|
103
|
+
end
|
104
|
+
return ret
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
end
|
109
|
+
end
|
data/lib/crokus/token.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
class Token
|
2
|
+
attr_accessor :kind,:val,:pos
|
3
|
+
def initialize tab
|
4
|
+
@kind,@val,@pos=*tab
|
5
|
+
end
|
6
|
+
|
7
|
+
def is_a? kind
|
8
|
+
case kind
|
9
|
+
when Symbol
|
10
|
+
return @kind==kind
|
11
|
+
when Array
|
12
|
+
for sym in kind
|
13
|
+
return true if @kind==sym
|
14
|
+
end
|
15
|
+
return false
|
16
|
+
else
|
17
|
+
raise "wrong type during lookahead"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def accept visitor,arg=nil
|
22
|
+
visitor.visitToken(self,arg)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.create str
|
26
|
+
Token.new [:id,str,[0,0]]
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_s
|
30
|
+
val
|
31
|
+
end
|
32
|
+
|
33
|
+
def inspect
|
34
|
+
"(#{kind},#{val},#{pos})"
|
35
|
+
end
|
36
|
+
|
37
|
+
alias :str :val
|
38
|
+
end
|
39
|
+
|
40
|
+
ONE = Token.new [:int_lit,'1',['na','na']]
|
41
|
+
ZERO = Token.new [:int_lit,'0',['na','na']]
|
42
|
+
DUMMY= Token.new [:id ,'' ,['na','na']]
|
43
|
+
EQUAL= Token.new [:eq ,'==' ,['na','na']]
|
@@ -0,0 +1,304 @@
|
|
1
|
+
|
2
|
+
require_relative 'code'
|
3
|
+
|
4
|
+
module Crokus
|
5
|
+
|
6
|
+
# here we transform an AST into another AST.
|
7
|
+
# we don't use Marshalling.
|
8
|
+
|
9
|
+
class Transformer
|
10
|
+
|
11
|
+
attr_accessor :code
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@ind=-2
|
15
|
+
@verbose=true
|
16
|
+
@verbose=false
|
17
|
+
end
|
18
|
+
|
19
|
+
def transform ast
|
20
|
+
ast.accept(self)
|
21
|
+
end
|
22
|
+
|
23
|
+
alias :visit :transform
|
24
|
+
|
25
|
+
def visitDesignUnit du,args=nil
|
26
|
+
list=du.list.collect{|e| e.accept(self)}
|
27
|
+
DesignUnit.new(list)
|
28
|
+
end
|
29
|
+
|
30
|
+
def visitDecl decl,args=nil
|
31
|
+
type=decl.type.accept(self)
|
32
|
+
var=decl.var.accept(self) if decl.var
|
33
|
+
init=decl.init.accept(self) if decl.init
|
34
|
+
Decl.new(type,var,init)
|
35
|
+
end
|
36
|
+
|
37
|
+
def visitInclude incl,args=nil
|
38
|
+
name=incl.name.accept(self)
|
39
|
+
env=incl.env
|
40
|
+
Include.new(name,env)
|
41
|
+
end
|
42
|
+
|
43
|
+
def visitDefine define,args=nil
|
44
|
+
name=define.name.accept(self)
|
45
|
+
expr=define.expr.accept(self)
|
46
|
+
Define.new(name,expr)
|
47
|
+
end
|
48
|
+
|
49
|
+
def visitTypedef typdef,args=nil
|
50
|
+
type=typdef.type.accept(self)
|
51
|
+
name=typdef.name.accept(self)
|
52
|
+
Typedef.new(type,name)
|
53
|
+
end
|
54
|
+
|
55
|
+
def visitType type,args=nil
|
56
|
+
precisions=type.precisions.collect{|prc| prc.accept(self)}
|
57
|
+
name=type.name.accept(self)
|
58
|
+
ret=Type.new(name)
|
59
|
+
ret.precisions=precisions
|
60
|
+
ret
|
61
|
+
end
|
62
|
+
|
63
|
+
def visitPointerTo pto,args=nil
|
64
|
+
type=pto.type.accept(self)
|
65
|
+
PointerTo.new(type)
|
66
|
+
end
|
67
|
+
|
68
|
+
def visitArrayOf aof,args=nil
|
69
|
+
type=aof.type.accept(self)
|
70
|
+
size=aof.size.accept(self) if aof.size
|
71
|
+
ArrayOf.new(type,size)
|
72
|
+
end
|
73
|
+
|
74
|
+
def visitStruct struct,args=nil
|
75
|
+
name=struct.name.accept(self) if struct.name
|
76
|
+
decls=struct.decls.collect{|decl| decl.accept(self)}
|
77
|
+
Struct.new(name,decls)
|
78
|
+
end
|
79
|
+
|
80
|
+
def visitCasting cast,args=nil
|
81
|
+
type=cast.type.accept(self)
|
82
|
+
modifier=cast.modifier.accept(self)
|
83
|
+
Casting.new(type,modifier)
|
84
|
+
end
|
85
|
+
|
86
|
+
def visitCastedExpr cexpr,args=nil
|
87
|
+
type=cexpr.type.accept(self)
|
88
|
+
expr=cexpr.expr.accept(self)
|
89
|
+
CastedExpr.new(type,expr)
|
90
|
+
end
|
91
|
+
|
92
|
+
#......... end of types..........
|
93
|
+
|
94
|
+
def visitFunction func,args=nil
|
95
|
+
type=func.type.accept(self)
|
96
|
+
name=func.name.accept(self)
|
97
|
+
args=func.args.collect{|arg| arg.accept(self)}
|
98
|
+
body=func.body.accept(self)
|
99
|
+
Function.new(name,type,args,body)
|
100
|
+
end
|
101
|
+
|
102
|
+
def visitFunctionProto func,args=nil
|
103
|
+
type=func.type.accept(self)
|
104
|
+
name=func.name.accept(self)
|
105
|
+
args=func.args.collect{|arg| arg.accept(self)}
|
106
|
+
FunctionProto.new(name,type,args)
|
107
|
+
end
|
108
|
+
|
109
|
+
def visitFormalArg formalArg,args=nil
|
110
|
+
name=formalArg.name.accept(self) if formalArg.name # e.g : main(void)
|
111
|
+
type=formalArg.type.accept(self)
|
112
|
+
FormalArg.new(type,name)
|
113
|
+
end
|
114
|
+
|
115
|
+
#...........stmts...............
|
116
|
+
def visitCommaStmt comma,args=nil
|
117
|
+
lhs=comma.lhs.accept(self)
|
118
|
+
rhs=comma.rhs.accept(self)
|
119
|
+
CommaStmt.new(lhs,rhs)
|
120
|
+
end
|
121
|
+
|
122
|
+
def visitAssign assign,args=nil
|
123
|
+
lhs=assign.lhs.accept(self)
|
124
|
+
op=assign.op.accept(self)
|
125
|
+
rhs=assign.rhs.accept(self)
|
126
|
+
Assign.new(lhs,op,rhs)
|
127
|
+
end
|
128
|
+
|
129
|
+
def visitPostFixAccu accu,args=nil
|
130
|
+
lhs=accu.lhs.accept(self) if accu.lhs #++i
|
131
|
+
op=accu.op.accept(self)
|
132
|
+
PostFixAccu.new(lhs,op)
|
133
|
+
end
|
134
|
+
|
135
|
+
def visitPreFixAccu accu,args=nil
|
136
|
+
lhs=accu.lhs.accept(self) if accu.lhs #++i
|
137
|
+
op=accu.op.accept(self)
|
138
|
+
PreFixAccu.new(lhs,op)
|
139
|
+
end
|
140
|
+
|
141
|
+
def visitFunCall fcall,args=nil
|
142
|
+
name=fcall.name.accept(self)
|
143
|
+
args=fcall.args.collect{|arg| arg.accept(self)}
|
144
|
+
FunCall.new(name,args)
|
145
|
+
end
|
146
|
+
|
147
|
+
def visitFor for_,args=nil
|
148
|
+
init=for_.init.collect{|stmt| stmt.accept(self)}
|
149
|
+
cond=for_.cond.accept(self)
|
150
|
+
increment=for_.increment.accept(self)
|
151
|
+
body=for_.body.accept(self)
|
152
|
+
For.new(init,cond,increment,body)
|
153
|
+
end
|
154
|
+
|
155
|
+
def visitReturn ret,args=nil
|
156
|
+
expr=ret.expr.accept(self) if ret.expr
|
157
|
+
Return.new(expr)
|
158
|
+
end
|
159
|
+
|
160
|
+
def visitIf if_,args=nil
|
161
|
+
cond=if_.cond.accept(self)
|
162
|
+
body=if_.body.accept(self)
|
163
|
+
else_=if_.else.accept(self) if if_.else
|
164
|
+
If.new(cond,body,else_)
|
165
|
+
end
|
166
|
+
|
167
|
+
def visitElse else_,args=nil
|
168
|
+
body=else_.body.accept(self)
|
169
|
+
Else.new(body)
|
170
|
+
end
|
171
|
+
|
172
|
+
def visitSwitch sw_,args=nil
|
173
|
+
expr =sw_.expr.accept(self)
|
174
|
+
cases=sw_.cases.collect{|case_| case_.accept(self)}
|
175
|
+
Switch.new(expr,cases)
|
176
|
+
end
|
177
|
+
|
178
|
+
def visitCase case_,args=nil
|
179
|
+
expr=case_.expr.accept(self)
|
180
|
+
body=case_.body.accept(self)
|
181
|
+
Case.new(expr,body)
|
182
|
+
end
|
183
|
+
|
184
|
+
def visitWhile while_,args=nil
|
185
|
+
cond=while_.cond.accept(self)
|
186
|
+
body=while_.body.accept(self)
|
187
|
+
While.new(cond,body)
|
188
|
+
end
|
189
|
+
|
190
|
+
def visitDoWhile while_,args=nil
|
191
|
+
cond=while_.cond.accept(self)
|
192
|
+
body=while_.body.each{|stmt| stmt.accept(self)}
|
193
|
+
DoWhile.new(cond,body)
|
194
|
+
end
|
195
|
+
|
196
|
+
def visitBreak brk,args=nil
|
197
|
+
Break.new
|
198
|
+
end
|
199
|
+
|
200
|
+
def visitContinue cont,args=nil
|
201
|
+
Continue.new
|
202
|
+
end
|
203
|
+
|
204
|
+
def visitLabelledStmt label,args=nil
|
205
|
+
stmt=label.stmt.accept(self)
|
206
|
+
LabelledStmt.new(stmt)
|
207
|
+
end
|
208
|
+
|
209
|
+
def visitGoto goto,args=nil
|
210
|
+
label=goto.label.accept(self)
|
211
|
+
Goto.new(label)
|
212
|
+
end
|
213
|
+
#..........expresions..........
|
214
|
+
def visitIdent ident,args=nil
|
215
|
+
tok=ident.tok.accept(self)
|
216
|
+
Ident.new(tok)
|
217
|
+
end
|
218
|
+
|
219
|
+
def visitIntLit lit,args=nil
|
220
|
+
tok=lit.tok.accept(self)
|
221
|
+
IntLit.new(tok)
|
222
|
+
end
|
223
|
+
|
224
|
+
def visitStrLit lit,args=nil
|
225
|
+
tok=lit.tok.accept(self)
|
226
|
+
StrLit.new(tok)
|
227
|
+
end
|
228
|
+
|
229
|
+
def visitCharLit lit,args=nil
|
230
|
+
tok=lit.tok.accept(self)
|
231
|
+
CharLit.new(tok)
|
232
|
+
end
|
233
|
+
|
234
|
+
def visitFloatLit lit,args=nil
|
235
|
+
tok=lit.tok.accept(self)
|
236
|
+
FloatLit.new(tok)
|
237
|
+
end
|
238
|
+
|
239
|
+
def visitBinary expr,args=nil
|
240
|
+
lhs=expr.lhs.accept(self)
|
241
|
+
op=expr.op.accept(self)
|
242
|
+
rhs=expr.rhs.accept(self)
|
243
|
+
Binary.new(lhs,op,rhs)
|
244
|
+
end
|
245
|
+
|
246
|
+
def visitUnary unary,args=nil
|
247
|
+
op=unary.op.accept(self)
|
248
|
+
rhs=unary.rhs.accept(self)
|
249
|
+
Unary.new(op,rhs,unary.postfix)
|
250
|
+
end
|
251
|
+
|
252
|
+
def visitParenth par,args=nil
|
253
|
+
e=par.expr.accept(self)
|
254
|
+
Parenth.new(e)
|
255
|
+
end
|
256
|
+
|
257
|
+
def visitArrow arrow,args=nil
|
258
|
+
lhs=arrow.lhs.accept(self)
|
259
|
+
rhs=arrow.rhs.accept(self)
|
260
|
+
Arrow.new(lhs,rhs)
|
261
|
+
end
|
262
|
+
|
263
|
+
def visitIndexed index,args=nil
|
264
|
+
lhs=index.lhs.accept(self)
|
265
|
+
rhs=index.rhs.accept(self)
|
266
|
+
Indexed.new(lhs,rhs)
|
267
|
+
end
|
268
|
+
|
269
|
+
def visitArrayOrStructInit init,args=nil
|
270
|
+
elements=init.elements.map{|e| e.accept(self)}
|
271
|
+
ArrayOrStructInit.new(elements)
|
272
|
+
end
|
273
|
+
|
274
|
+
def visitAddressOf ao,args=nil
|
275
|
+
e=ao.expr.accept(self)
|
276
|
+
AddressOf.new(e)
|
277
|
+
end
|
278
|
+
|
279
|
+
def visitDotted dotted,args=nil
|
280
|
+
lhs=dotted.lhs.accept(self)
|
281
|
+
rhs=dotted.rhs.accept(self)
|
282
|
+
Dotted.new(lhs,rhs)
|
283
|
+
end
|
284
|
+
|
285
|
+
def visitSizeof sizeof,args=nil
|
286
|
+
type=sizeof.type.accept(self)
|
287
|
+
Sizeof.new(type)
|
288
|
+
end
|
289
|
+
|
290
|
+
def visitDeref deref,args=nil
|
291
|
+
e=deref.expr.accept(self)
|
292
|
+
Deref.new(e)
|
293
|
+
end
|
294
|
+
|
295
|
+
def visitBody body,args=nil
|
296
|
+
stmts=body.stmts.map{|stmt| stmt.accept(self)}
|
297
|
+
Body.new(stmts)
|
298
|
+
end
|
299
|
+
|
300
|
+
def visitToken tok,args=nil
|
301
|
+
Token.new [tok.kind,tok.val,tok.pos]
|
302
|
+
end
|
303
|
+
end #class Visitor
|
304
|
+
end #module
|