crokus 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,443 @@
1
+
2
+ require_relative 'code'
3
+ require_relative 'visitor'
4
+ require_relative 'cleaner'
5
+
6
+ module Crokus
7
+
8
+ class PrettyPrinter < Visitor
9
+
10
+ include Indent
11
+ attr_accessor :code
12
+
13
+ def initialize
14
+ @ind=-2
15
+ @verbose=false
16
+ end
17
+
18
+ def visit ast
19
+ @code=Code.new
20
+ ast.accept(self)
21
+ c_code=@code.finalize
22
+ c_code=Cleaner.new.clean(c_code)
23
+ return c_code
24
+ end
25
+
26
+ def visitToken tok, args=nil
27
+ tok.to_s
28
+ end
29
+
30
+ def visitDesignUnit du,args=nil
31
+ indent "DesignUnit"
32
+ du.list.each{|e| code << e.accept(self,:body)}
33
+ dedent
34
+ end
35
+
36
+ def visitDecl decl,args=nil
37
+ code=Code.new
38
+ type=decl.type.accept(self)
39
+
40
+ array_size=""
41
+ t=decl.type
42
+
43
+ while t.is_a? ArrayOf
44
+ type=t.name.accept(self)
45
+ size=t.size.accept(self)
46
+ array_size="[#{size}]"+array_size
47
+ t=t.type
48
+ end
49
+ t=nil
50
+
51
+ vname=decl.var.accept(self)
52
+ init=decl.init.accept(self) if decl.init
53
+
54
+ if init.is_a? Code
55
+ init=" = "+init.finalize
56
+ else
57
+ init=" = "+init
58
+ end if decl.init
59
+
60
+ # handle complex declaration that use structs
61
+ if type.is_a? Code
62
+ last=type.lines.pop
63
+ type.lines.each do |line|
64
+ code << line
65
+ end
66
+ last_str=last+" #{vname}#{array_size}#{init}"
67
+
68
+ code << last_str
69
+ else
70
+ ret = "#{type} #{vname}#{array_size}#{init}"
71
+ end
72
+ code << ret
73
+ code << ";"
74
+ return code
75
+ end
76
+
77
+ def visitInclude include,args=nil
78
+ name=include.name.accept(self)
79
+ case include.env
80
+ when :env
81
+ name="<#{name}>"
82
+ when :local
83
+ end
84
+ return "#include #{name}"
85
+ end
86
+
87
+ def visitDefine define,args=nil
88
+ name=define.name.accept(self)
89
+ e=define.expr.accept(self)
90
+ return "#define #{name} #{e}"
91
+ end
92
+
93
+ def visitTypedef typdef,args=nil
94
+ type=typdef.type.accept(self)
95
+ name=typdef.name.accept(self)
96
+ return "typedef #{type} #{name};"
97
+ end
98
+
99
+ def visitType type,args=nil
100
+ precisions=type.precisions.collect{|spec| spec.accept(self)}
101
+ precisions=precisions.join(" ")
102
+ precisions+=" " if precisions.size>0
103
+ name=type.name.accept(self)
104
+ return "#{precisions}#{name}"
105
+ end
106
+
107
+ def visitPointerTo pto,args=nil
108
+ tname=pto.type.accept(self)
109
+ return "#{tname} *"
110
+ end
111
+
112
+ def visitArrayOf aof,args=nil
113
+ type=aof.type.accept(self)
114
+ size=aof.size.accept(self) if aof.size
115
+ aof
116
+ "#{type}" #[size] not returned!
117
+ end
118
+
119
+ def visitStruct struct,args=nil
120
+ name=struct.name.accept(self) if struct.name
121
+ code=Code.new
122
+ code << "struct #{name} {"
123
+ code.indent=2
124
+ struct.decls.each do |decl|
125
+ code << decl.accept(self)
126
+ end
127
+ code.indent=0
128
+ code << "}"
129
+ return code.finalize
130
+ end
131
+
132
+ def visitCasting cast,args=nil
133
+ type=cast.type.accept(self)
134
+ return "#{type} #{cast.modifier}"
135
+ end
136
+
137
+ def visitCastedExpr cexpr, args=nil
138
+ type=cexpr.type.accept(self)
139
+ e=cexpr.expr.accept(self)
140
+ return "(#{type}) #{e}"
141
+ end
142
+ #......... end of types..........
143
+
144
+ def visitFunction func,args=nil
145
+ code=Code.new
146
+ tname=func.type.accept(self)
147
+ fname=func.name.accept(self)
148
+ args=func.args.collect{|arg| arg.accept(self)}
149
+ args=args.join(",")
150
+ code << "\n#{tname} #{fname}(#{args})"
151
+ code.indent=2
152
+ code << func.body.accept(self)
153
+ code.indent=0
154
+ return code
155
+ end
156
+
157
+ def visitFunctionProto func,args=nil
158
+ tname=func.type.accept(self)
159
+ fname=func.name.accept(self)
160
+ args =func.args.collect{|arg| arg.accept(self)}
161
+ args=args.join(",")
162
+ code = "\n#{tname} #{fname}(#{args})"
163
+ return code
164
+ end
165
+
166
+ def visitFormalArg formalArg,args=nil
167
+ tname=formalArg.type.accept(self)
168
+ array_size=""
169
+ t=formalArg.type
170
+ while t.is_a? ArrayOf
171
+ type=t.name.accept(self)
172
+ size=t.size.accept(self) if t.size
173
+ array_size+="[#{size}]"+array_size if tname.size
174
+ t=t.type
175
+ end
176
+
177
+ vname=formalArg.name.accept(self) if formalArg.name # e.g : main(void)
178
+ tname+=" " if formalArg.name
179
+ return "#{tname}#{vname}#{array_size}"
180
+ end
181
+
182
+ #...........stmts...............
183
+ def visitCommaStmt comma,args=nil
184
+ lhs=comma.lhs.accept(self)
185
+ rhs=comma.rhs.accept(self)
186
+ ret="#{lhs},#{rhs}"
187
+ ret
188
+ end
189
+
190
+ def visitAssign assign,args=nil
191
+ lhs=assign.lhs.accept(self)
192
+ op =assign.op.accept(self)
193
+ rhs=assign.rhs.accept(self)
194
+ ret="#{lhs} #{op} #{rhs};"
195
+ ret
196
+ end
197
+
198
+ def visitPostFixAccu accu,args=nil
199
+ lhs=accu.lhs.accept(self) if accu.lhs #++i
200
+ op =accu.op.accept(self)
201
+ ret="#{lhs}#{op}"
202
+ ret
203
+ end
204
+
205
+ def visitPreFixAccu accu,args=nil
206
+ lhs=accu.lhs.accept(self) if accu.lhs #++i
207
+ op =accu.op.accept(self)
208
+ ret="#{lhs}#{op}"
209
+ ret
210
+ end
211
+
212
+ def visitFunCall fcall,as_procedure=nil
213
+ fname=fcall.name.accept(self)
214
+ argus=fcall.args.collect{|argu| argu.accept(self)}
215
+ argus=argus.join(',')
216
+ ret="#{fname}(#{argus})"
217
+ ret+=";" if as_procedure
218
+ ret
219
+ end
220
+
221
+ def visitFor for_,args=nil
222
+ code=Code.new
223
+ init=for_.init.collect do |stmt|
224
+ stmt_init=stmt.accept(self)
225
+ case stmt_init
226
+ when Code
227
+ stmt_init.finalize
228
+ else
229
+ stmt_init
230
+ end
231
+ end
232
+ init=init.join(";")
233
+ cond=for_.cond.accept(self)
234
+ incr=for_.increment.accept(self)
235
+ code << "for(#{init};#{cond};#{incr})"
236
+ code.indent=2
237
+ code << for_.body.accept(self)
238
+ code.indent=0
239
+ return code
240
+ end
241
+
242
+ def visitReturn ret,args=nil
243
+ e=ret.expr.accept(self) if ret.expr
244
+ return "return #{e};"
245
+ end
246
+
247
+ def visitIf if_,args=nil
248
+ cond=if_.cond.accept(self)
249
+ code=Code.new
250
+ code << "if (#{cond})"
251
+ code.indent=2
252
+ code << if_.body.accept(self)
253
+ code.indent=0
254
+ code << if_.else.accept(self,:body) if if_.else
255
+ return code
256
+ end
257
+
258
+ def visitElse else_,args=nil
259
+ code=Code.new
260
+ code << "else"
261
+ code.indent=2
262
+ code << else_.body.accept(self)
263
+ code.indent=0
264
+ return code
265
+ end
266
+
267
+ def visitSwitch sw_,args=nil
268
+ e=sw_.expr.accept(self)
269
+ sw_.cases.each{|case_| case_.accept(self)}
270
+ code=Code.new
271
+ code << "switch(#{e}){"
272
+ code.indent=2
273
+ sw_.cases.each{|case_|
274
+ code << case_.accept(self)
275
+ }
276
+ code.indent=0
277
+ if sw_.default
278
+ code.indent=2
279
+ code << "default:"
280
+ code.indent=4
281
+ code << sw_.default.accept(self)
282
+ code.indent=0
283
+ end
284
+
285
+ code << "}"
286
+ return code
287
+ end
288
+
289
+ def visitCase case_,args=nil
290
+ e=case_.expr.accept(self)
291
+ code=Code.new
292
+ code << "case #{e}:"
293
+ code.indent=2
294
+ code << case_.body.accept(self)
295
+ code.indent=0
296
+ return code
297
+ end
298
+
299
+ def visitWhile while_,args=nil
300
+ cond=while_.cond.accept(self)
301
+ body=while_.body.accept(self)
302
+ code=Code.new
303
+ code << "while (#{cond})"
304
+ code.indent=2
305
+ code << body
306
+ code.indent=0
307
+ return code
308
+ end
309
+
310
+ def visitDoWhile while_,args=nil
311
+ cond=while_.cond.accept(self)
312
+ code=Code.new
313
+ code << "do"
314
+ code.indent=2
315
+ code << while_.body.accept(self)
316
+ code.indent=0
317
+ code << "while #{cond};"
318
+ return code
319
+ end
320
+
321
+ def visitBreak brk,args=nil
322
+ return "break;"
323
+ end
324
+
325
+ def visitContinue cont,args=nil
326
+ return "continue;"
327
+ end
328
+
329
+ def visitLabeledStmt label,args=nil
330
+ stmt=label.stmt.accept(self)
331
+ code=Code.new
332
+ code << stmt
333
+ return code
334
+ end
335
+
336
+ def visitGoto goto,args=nil
337
+ label=goto.label.accept(self)
338
+ return "goto #{label};"
339
+ end
340
+
341
+ #..........expresions..........
342
+ def visitIdent ident,args=nil
343
+ return ident.to_s
344
+ end
345
+
346
+ def visitIntLit lit,args=nil
347
+ return lit.to_s
348
+ end
349
+
350
+ def visitStrLit lit,args=nil
351
+ return lit.to_s
352
+ end
353
+
354
+ def visitCharLit lit,args=nil
355
+ return lit.to_s
356
+ end
357
+
358
+ def visitBinary expr,args=nil
359
+ lhs=expr.lhs.accept(self)
360
+ op =expr.op.accept(self)
361
+ rhs=expr.rhs.accept(self)
362
+ case op
363
+ when "+","-","*","/"
364
+ else
365
+ op=" "+op+" "
366
+ end
367
+ return "#{lhs}#{op}#{rhs}"
368
+ end
369
+
370
+ def visitUnary unary,args=nil
371
+ op=unary.op.accept(self)
372
+ e =unary.rhs.accept(self)
373
+ return unary.postfix ? "#{e}#{op}" : "#{op}#{e}"
374
+ end
375
+
376
+ def visitParenth par,args=nil
377
+ e=par.expr.accept(self)
378
+ return "(#{e})"
379
+ end
380
+
381
+ def visitArrow arrow,args=nil
382
+ lhs=arrow.lhs.accept(self)
383
+ rhs=arrow.rhs.accept(self)
384
+ return "#{lhs}->#{rhs}"
385
+ end
386
+
387
+ def visitIndexed index,args=nil
388
+ lhs=index.lhs.accept(self)
389
+ rhs=index.rhs.accept(self)
390
+ return "#{lhs}[#{rhs}]"
391
+ end
392
+
393
+ def visitArrayOrStructInit init,args=nil
394
+ inits=init.elements.collect{|e| e.accept(self)}
395
+ #handle imbrications
396
+ inits=inits.collect{|init| (init.is_a? Code) ? init.finalize : init}
397
+ code=Code.new
398
+ code << "{"+inits.join(",")+"}"
399
+ return code
400
+ end
401
+
402
+ def visitAddressOf ao,args=nil
403
+ e=ao.expr.accept(self)
404
+ return " &#{e} "
405
+ end
406
+
407
+ def visitDotted dotted,args=nil
408
+ lhs=dotted.lhs.accept(self)
409
+ rhs=dotted.rhs.accept(self)
410
+ return "#{lhs}.#{rhs}"
411
+ end
412
+
413
+ def visitSizeof sizeof,args=nil
414
+ tname=sizeof.type.accept(self)
415
+ return "sizeof(#{tname})"
416
+ end
417
+
418
+ def visitDeref deref,args=nil
419
+ e=deref.expr.accept(self)
420
+ return "*#{e}"
421
+ end
422
+
423
+ def visitBody body,args=nil
424
+ code=Code.new
425
+ code << "{"
426
+ code.indent=2
427
+ body.each do |stmt|
428
+ code << stmt.accept(self,true)
429
+ end
430
+ code.indent=0
431
+ code << "}"
432
+ return code
433
+ end
434
+
435
+ #================= IR ============
436
+ def visitITE ite,args=nil
437
+ cond=ite.cond.accept(self)
438
+ label1=ite.trueBranch.label
439
+ label2=ite.falseBranch.label
440
+ "ite #{cond},#{label1},#{label2}"
441
+ end
442
+ end #class Visitor
443
+ end #module
@@ -0,0 +1,86 @@
1
+ require "optparse"
2
+
3
+ require_relative "compiler"
4
+
5
+ module Crokus
6
+
7
+ class Runner
8
+
9
+ def self.run *arguments
10
+ new.run(arguments)
11
+ end
12
+
13
+ def run arguments
14
+ compiler=Compiler.new
15
+ compiler.options = args = parse_options(arguments)
16
+ if filename=args[:cfile]
17
+ compiler.compile filename
18
+ else
19
+ puts "need a C file : crokus [options] <file.c>"
20
+ end
21
+ end
22
+
23
+ def header
24
+ puts "Crokus (#{VERSION})- (c) JC Le Lann 2016-20"
25
+ end
26
+
27
+ private
28
+ def parse_options(arguments)
29
+ header
30
+
31
+ parser = OptionParser.new
32
+
33
+ no_arguments=arguments.empty?
34
+
35
+ options = {}
36
+
37
+ parser.on("-h", "--help", "Show help message") do
38
+ puts parser
39
+ exit(true)
40
+ end
41
+
42
+ parser.on("-p", "--parse", "parse only") do
43
+ options[:parse_only]=true
44
+ end
45
+
46
+ parser.on("--pp", "pretty print back source code ") do
47
+ options[:pp] = true
48
+ end
49
+
50
+ parser.on("--ast", "abstract syntax tree (AST)") do
51
+ options[:ast] = true
52
+ end
53
+
54
+ parser.on("--cfg", "control-flow graphs for each function") do
55
+ options[:cfg] = true
56
+ end
57
+
58
+ parser.on("--tac", "draw three address code (TAC) CFG") do
59
+ options[:tac] = true
60
+ end
61
+
62
+ parser.on("--emit-ir", "dump textual IR from TAC CFG") do
63
+ options[:emit_ir] = true
64
+ end
65
+
66
+ parser.on("--vv", "verbose") do
67
+ options[:verbose] = true
68
+ end
69
+
70
+ parser.on("-v", "--version", "Show version number") do
71
+ puts VERSION
72
+ exit(true)
73
+ end
74
+
75
+ parser.parse!(arguments)
76
+
77
+ options[:cfile]=arguments.shift #the remaining c file
78
+
79
+ if no_arguments
80
+ puts parser
81
+ end
82
+
83
+ options
84
+ end
85
+ end
86
+ end