crokus 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,10 @@
1
+ module Crokus
2
+ class Cleaner
3
+ def clean str_c
4
+ str_c.gsub!(";;",";")
5
+ str_c.gsub!(";)",")")
6
+ str_c.gsub!(/\n\s*\;/,";")
7
+ #str_c.gsub!(/\n\s+\{/,"{")
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,46 @@
1
+ class Code
2
+
3
+ attr_accessor :indent,:lines
4
+
5
+ def initialize str=nil
6
+ @lines=[]
7
+ (@lines << str) if str
8
+ @indent=0
9
+ end
10
+
11
+ def <<(thing)
12
+ if (code=thing).is_a? Code
13
+ code.lines.each do |line|
14
+ @lines << " "*@indent+line.to_s
15
+ end
16
+ elsif thing.is_a? Array
17
+ thing.each do |kode|
18
+ @lines << kode
19
+ end
20
+ elsif thing.nil?
21
+ else
22
+ @lines << " "*@indent+thing.to_s
23
+ end
24
+ end
25
+
26
+ def finalize
27
+ return @lines.join("\n") if @lines.any?
28
+ ""
29
+ end
30
+
31
+ def newline
32
+ @lines << " "
33
+ end
34
+
35
+ def save_as filename,verbose=true,sep="\n"
36
+ str=self.finalize
37
+ File.open(filename,'w'){|f| f.puts(str)}
38
+ return filename
39
+ end
40
+
41
+ def size
42
+ @lines.size
43
+ end
44
+
45
+
46
+ end
@@ -0,0 +1,124 @@
1
+ require_relative 'ast'
2
+ require_relative 'ast_printer'
3
+ require_relative 'parser'
4
+ #require_relative 'parser_only'
5
+ require_relative 'visitor'
6
+ require_relative 'transformer'
7
+ require_relative 'pretty_printer'
8
+ require_relative 'cfg_builder'
9
+ require_relative 'tac_builder'
10
+ require_relative 'ir_dumper'
11
+
12
+ module Crokus
13
+
14
+ class Compiler
15
+
16
+ attr_accessor :options
17
+ attr_accessor :parser
18
+ attr_accessor :ast
19
+ attr_accessor :base_name
20
+
21
+ def initialize
22
+ @options={}
23
+ $options=@options
24
+ @parser=Parser.new
25
+ end
26
+
27
+ def header
28
+
29
+ end
30
+
31
+ def compile filename
32
+ header
33
+
34
+ parse(filename)
35
+ if options[:parse_only]
36
+ return true
37
+ end
38
+
39
+ build_cfg
40
+ if options[:cfg]
41
+ return true
42
+ end
43
+
44
+ build_tac
45
+ if options[:tac]
46
+ return true
47
+ end
48
+
49
+ emit_ir
50
+ return true
51
+ end
52
+
53
+
54
+
55
+ def parse filename
56
+ @base_name=File.basename(filename, ".c")
57
+ code=IO.read(filename)
58
+ puts "=> parsing #{filename}" unless options[:mute]
59
+ @ast=Parser.new.parse(code)
60
+ draw_ast if options[:draw_ast]
61
+ pretty_print if options[:pp]
62
+ end
63
+
64
+ # def parse filename
65
+ # @base_name=File.basename(filename, ".c")
66
+ # code=IO.read(filename)
67
+ # @ast=Parser.new.parse(code)
68
+ # end
69
+
70
+ def draw_ast tree=nil,filename=nil
71
+ dotname=filename || "#{base_name}.dot"
72
+ puts " |--> drawing AST '#{dotname}'" unless options[:mute]
73
+ ast_ = tree || @ast
74
+ dot=AstPrinter.new.print(ast_)
75
+ dot.save_as dotname
76
+ end
77
+
78
+ def transform
79
+ puts "=> dummy transform" unless options[:mute]
80
+ ast_t= Transformer.new.transform(ast)
81
+ dotname="#{base_name}_trans.dot"
82
+ draw_ast ast_t,dotname
83
+ end
84
+
85
+ def visit
86
+ puts "=> dummy visit" unless options[:mute]
87
+ Visitor.new.visit(ast)
88
+ end
89
+
90
+ def pretty_print
91
+ puts "=> pretty_print" unless options[:mute]
92
+ code=PrettyPrinter.new.visit(ast)
93
+ pp_c=@base_name+"_pp.c"
94
+ File.open(pp_c,'w'){|f| f.puts code}
95
+ puts " |--> saved as #{pp_c}" unless options[:mute]
96
+ end
97
+
98
+ def build_cfg
99
+ puts "=> building CFGs" unless options[:mute]
100
+ builder=CFGBuilder.new
101
+ builder.build(@ast)
102
+ end
103
+
104
+ def build_tac
105
+ puts "=> building TAC" unless options[:mute]
106
+ builder=TACBuilder.new
107
+ builder.visit(@ast)
108
+ end
109
+
110
+ def emit_ir
111
+ puts "=> emit textual IR " unless options[:mute]
112
+ IRDumper.new.visit(@ast)
113
+ end
114
+
115
+ end
116
+ end
117
+ #
118
+ # if $PROGRAM_NAME == __FILE__
119
+ # filename=ARGV[0]
120
+ # t1 = Time.now
121
+ # C::Compiler.new.compile(filename)
122
+ # t2 = Time.now
123
+ # puts "parsed in : #{t2-t1} s"
124
+ # end
@@ -0,0 +1,62 @@
1
+ require 'strscan'
2
+
3
+ require_relative 'token'
4
+
5
+ class GenericLexer
6
+
7
+ def initialize
8
+ @rules = []
9
+ @rules << [:newline,/[\n]/]
10
+ end
11
+
12
+ def ignore pattern
13
+ @rules << [:skip,pattern]
14
+ end
15
+
16
+ def keyword str
17
+ @rules.unshift [str.to_sym,/#{str}\b/]
18
+ end
19
+
20
+ def token h_token_pattern
21
+ token,pattern=*h_token_pattern.to_a.first
22
+ @rules << [token, pattern]
23
+ end
24
+
25
+ def open code
26
+ @ssc = StringScanner.new code
27
+ @line=0
28
+ end
29
+
30
+ def next_token
31
+ return [nil,nil,nil] if @ssc.empty?
32
+ tok = get_token
33
+ return (tok.is_a? :skip) ? next_token : tok
34
+ end
35
+
36
+ def get_token
37
+ linecol=position()
38
+ @rules.each do |rule, regexp|
39
+ val = @ssc.scan(regexp)
40
+ return Token.new([rule, val, linecol]) if val
41
+ end
42
+ raise "lexing error line #{linecol.first} around '#{@ssc.peek(10)}' "
43
+ end
44
+
45
+ def position
46
+ if @ssc.bol?
47
+ @line+=1
48
+ @old_pos=@ssc.pos
49
+ end
50
+ [@line,@ssc.pos-@old_pos+1]
51
+ end
52
+
53
+ def tokenize code
54
+ open(code)
55
+ tokens=[]
56
+ tokens << next_token() while not @ssc.eos?
57
+ # while not @ssc.eos?
58
+ # tokens << (p next_token)
59
+ # end
60
+ tokens
61
+ end
62
+ end
@@ -0,0 +1,19 @@
1
+ module Indent
2
+
3
+ INDENT=2
4
+
5
+ def indent str
6
+ @indentation||=-INDENT
7
+ @indentation+=INDENT
8
+ say(str)
9
+ end
10
+
11
+ def dedent
12
+ @indentation-=INDENT
13
+ end
14
+
15
+ def say str
16
+ puts " "*@indentation+str if @verbose
17
+ end
18
+
19
+ end
@@ -0,0 +1,48 @@
1
+ module Crokus
2
+
3
+ class IRDumper < Visitor
4
+
5
+ def visitFunction func,args=nil
6
+ puts "IR for '#{func.name}'".center(40,'=')
7
+ dump func.cfg
8
+ end
9
+
10
+ def dump cfg
11
+ @visited=[]
12
+ visit_rec cfg.starter
13
+ end
14
+
15
+ def visit_rec bb
16
+ print bb.label+":"
17
+ @visited << bb
18
+ @current=bb
19
+ bb.stmts.each do |stmt|
20
+ unless stmt.is_a? Break or stmt.is_a? Continue
21
+ puts "\t"+stmt.str.gsub(/;/,'')
22
+ end
23
+ end
24
+ unless bb.stmts.last.is_a? Crokus::ITE
25
+ if bb.succs.any?
26
+ puts "\tgoto #{bb.succs.first.label}"
27
+ end
28
+ end
29
+ if bb.succs.empty?
30
+ puts "\tstop"
31
+ else
32
+ bb.succs.each do |bb|
33
+ unless @visited.include? bb
34
+ visit_rec(bb)
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ def visitITE ite,args=nil
41
+ cond=ite.cond.accept(self)
42
+ label1=ite.trueBranch.label
43
+ label2=ite.falseBranch.label
44
+ "\t"+"ite #{cond},#{label1},#{label2}"
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,113 @@
1
+ require_relative 'generic_lexer'
2
+
3
+ module Crokus
4
+ class Lexer < GenericLexer
5
+
6
+ def initialize
7
+ super
8
+ ignore /\s+/
9
+ keyword "auto"
10
+ keyword "break"
11
+ keyword "case"
12
+ keyword "char"
13
+ keyword "const"
14
+ keyword "continue"
15
+ keyword "default"
16
+ keyword "do"
17
+ keyword "double"
18
+ keyword "else"
19
+ keyword "enum"
20
+ keyword "extern"
21
+ keyword "float"
22
+ keyword "for"
23
+ keyword "goto"
24
+ keyword "if"
25
+ keyword "int"
26
+ keyword "long"
27
+ keyword "register"
28
+ keyword "return"
29
+ keyword "short"
30
+ keyword "signed"
31
+ keyword "sizeof"
32
+ keyword "static"
33
+ keyword "struct"
34
+ keyword "switch"
35
+ keyword "typedef"
36
+ keyword "union"
37
+ keyword "unsigned"
38
+ keyword "void"
39
+ keyword "volatile"
40
+ keyword "while"
41
+
42
+ token :qmark => /\?/
43
+ token :lparen => /\(/
44
+ token :rparen => /\)/
45
+ token :lbrace => /\{/
46
+ token :rbrace => /\}/
47
+ token :lbrack => /\[/
48
+ token :rbrack => /\]/
49
+ token :semicolon => /;/
50
+ token :colon => /:/
51
+ token :comma => /\,/
52
+ token :lcomment => /\/\*/
53
+ token :rcomment => /\*\//
54
+ token :comment => /\/\/(.*)/
55
+
56
+ token :dot => /\./
57
+ token :neq => /!=/
58
+ token :not => /\!/
59
+ token :eq => /\=\=/
60
+ token :assign => /\=/
61
+ token :inc_op => /\+\+/
62
+ token :add_assign => /\+\=/
63
+ token :add => /\+/
64
+ token :dec_op => /\-\-/
65
+ token :sub_assign => /\-\=/
66
+ token :ptr_op => /\-\>/
67
+ token :sub => /\-/
68
+ token :mul_assign => /\*=/
69
+ token :mul => /\*/
70
+ token :div_assign => /\/=/
71
+ token :div => /\//
72
+
73
+ token :shift_r => /\>\>/
74
+ token :shift_l => /\<\</
75
+ token :oror => /\|\|/
76
+ token :lte => /<=/
77
+ token :lt => /</
78
+ token :gte => />=/
79
+ token :gt => />/
80
+ token :andand => /\&\&/
81
+ token :and => /\&/
82
+ token :or => /\|/
83
+ token :mod_assign => /\%=/
84
+ token :mod => /\%/
85
+ token :xor_assign => /\^\=/
86
+ token :xor => /\^/
87
+
88
+ token :sharp => /#/
89
+
90
+ # .............literals..............................
91
+
92
+ token :ident => /\A[a-zA-Z]\w*/i
93
+ token :float_lit => /\A\d*(\.\d+)(E([+-]?)\d+)?/
94
+ token :integer_lit => /\A(0x[0-9a-fA-F]+)|\d+/
95
+ token :string_lit => /\A"[^"]*"/
96
+ token :char_lit => /\A'\\?.'/
97
+ token :lexer_warning => /./
98
+
99
+ end
100
+ end
101
+ end
102
+
103
+ if $PROGRAM_NAME == __FILE__
104
+ str=IO.read(ARGV[0])
105
+ puts str
106
+ t1 = Time.now
107
+ lexer=Crokus::Lexer.new
108
+ tokens=lexer.tokenize(str)
109
+ t2 = Time.now
110
+ pp tokens
111
+ puts "number of tokens : #{tokens.size}"
112
+ puts "tokenized in : #{t2-t1} s"
113
+ end
@@ -0,0 +1,1072 @@
1
+ require 'pp'
2
+
3
+ require_relative 'lexer'
4
+ require_relative 'ast'
5
+ require_relative 'indent'
6
+ require_relative 'pretty_printer'
7
+
8
+ module Crokus
9
+
10
+ class Parser
11
+
12
+ attr_accessor :tokens,:str
13
+ include Indent
14
+
15
+ def initialize
16
+ @ppr=PrettyPrinter.new
17
+ @verbose=false
18
+ #@verbose=true
19
+ end
20
+
21
+ def acceptIt
22
+ say showNext.kind.to_s+" "+showNext.val
23
+ tokens.shift
24
+ end
25
+
26
+ def maybe kind
27
+ return acceptIt if showNext.is_a? kind
28
+ end
29
+
30
+ def expect kind
31
+ if ((actual=tokens.shift).kind)!=kind
32
+ puts "ERROR :"
33
+ show_line(actual.pos)
34
+ raise "expecting '#{kind}'. Received '#{actual.val}' around #{actual.pos}"
35
+ end
36
+ say actual.kind.to_s+" "+actual.val
37
+ return actual
38
+ end
39
+
40
+ def showNext(n=1)
41
+ tokens[n-1] if tokens.any?
42
+ end
43
+
44
+ def lookahead(n=2)
45
+ tokens[n] if tokens.any?
46
+ end
47
+
48
+ def show_line pos
49
+ l,c=*pos
50
+ show_lines(str,l-2)
51
+ line=str.split(/\n/)[l-1]
52
+ pointer="-"*(5+c)+ "^"
53
+ puts "#{l.to_s.ljust(5)}|#{line}"
54
+ puts pointer
55
+ end
56
+ #--------------------------------------------------
57
+ def dbg_print_next n
58
+ pp tokens[0..n-1].collect{|tok| tok.inspect}
59
+ end
60
+
61
+ def dbg_print node
62
+ puts "debug ast node".center(60,'-')
63
+ puts node.accept(@ppr)
64
+ puts "-"*60
65
+ end
66
+ #............ parsing methods ...........
67
+ def parse str
68
+ begin
69
+ @str=str
70
+ @tokens=Lexer.new.tokenize(str)
71
+ @tokens=remove_comments()
72
+ warnings=@tokens.select{|tok| tok.is_a? :lexer_warning}
73
+ show_lexer_warnings(warnings)
74
+ @tokens=@tokens.select{|tok| !tok.is_a? [:newline]}
75
+ ast=design_unit()
76
+ rescue Exception => e
77
+ puts "PARSING ERROR : #{e}"
78
+ puts "in C source at line/col #{showNext.pos}"
79
+ puts e.backtrace
80
+ abort
81
+ end
82
+ end
83
+
84
+ def show_lexer_warnings warnings
85
+ warnings.each do |warn|
86
+ puts "lexer warning : #{warn.val} at #{warn.pos}"
87
+ end
88
+ end
89
+
90
+ def remove_comments
91
+ ret=[]
92
+ in_comment=false
93
+ tokens.each do |tok|
94
+ case tok.kind
95
+ when :comment
96
+ when :lcomment
97
+ in_comment=true
98
+ when :rcomment
99
+ in_comment=false
100
+ else
101
+ ret << tok unless in_comment
102
+ end
103
+ end
104
+ ret
105
+ end
106
+
107
+ def design_unit
108
+ indent "designUnit"
109
+ du=DesignUnit.new
110
+ while tokens.any?
111
+ case showNext.kind
112
+ when :sharp
113
+ case showNext(2).val
114
+ when "include"
115
+ du << include()
116
+ when "define"
117
+ du << define()
118
+ end
119
+ else
120
+ du << declaration
121
+ maybe :semicolon if tokens.any?
122
+ end
123
+ end
124
+ dedent
125
+ du.list.flatten!
126
+ return du
127
+ end
128
+
129
+ def include
130
+ indent "include"
131
+ expect :sharp
132
+ expect :ident #include
133
+ case showNext.kind
134
+ when :lt
135
+ acceptIt
136
+ id1=expect :ident
137
+ expect :dot
138
+ id2=expect :ident
139
+ expect :gt
140
+ name=Token.new [:ident,id1.val+"."+id2.val,id1.pos]
141
+ env=:env
142
+ when :string_lit
143
+ name=acceptIt
144
+ env=:local
145
+ end
146
+ dedent
147
+ return Include.new(name,env)
148
+ end
149
+
150
+ def define
151
+ indent "define"
152
+ expect :sharp
153
+ expect :ident #define
154
+ name=expect :ident
155
+ e=expression()
156
+ dedent
157
+ return Define.new(name,e)
158
+ end
159
+
160
+ def parse_struct
161
+ indent "struct"
162
+ expect :struct
163
+ name=nil
164
+ if showNext.is_a? :ident
165
+ name=acceptIt
166
+ end
167
+ ret=Struct.new(name)
168
+ if showNext.is_a? :lbrace
169
+ acceptIt
170
+ while !showNext.is_a? :rbrace
171
+ ret.decls << declaration()
172
+ end
173
+ ret.decls.flatten!
174
+ expect :rbrace
175
+ end
176
+ dedent
177
+ return ret
178
+ end
179
+
180
+ def typedef
181
+ indent "typedef"
182
+ expect :typedef
183
+ type=parse_type()
184
+ id=expect(:ident)
185
+ dedent
186
+ return Typedef.new(type,id)
187
+ end
188
+
189
+ def function_decl name,type_
190
+ indent "function"
191
+ args=function_formal_args()
192
+ case showNext.kind
193
+ when :semicolon
194
+ acceptIt
195
+ ret =FunctionProto.new(name,type_,args)
196
+ else
197
+ body=function_body()
198
+ ret= Function.new(name,type_,args,body)
199
+ end
200
+ dedent
201
+ return ret
202
+ end
203
+
204
+ def function_formal_args
205
+ indent "function_formal_args"
206
+ args=[]
207
+ expect :lparen
208
+ while !showNext.is_a? :rparen
209
+ args << func_formal_arg()
210
+ if !showNext.is_a? :rparen
211
+ expect :comma
212
+ end
213
+ end
214
+ expect :rparen
215
+ dedent
216
+ return args
217
+ end
218
+
219
+ def func_formal_arg
220
+ indent "function_arg"
221
+ @current_type=type=parse_type()
222
+ d=declarator
223
+ a=arrayed?(type)
224
+ #parenthesized?
225
+ dedent
226
+ return FormalArg.new(type,d)
227
+ end
228
+
229
+ def function_body
230
+ indent "function_body"
231
+ body=Body.new
232
+ expect :lbrace
233
+ while showNext.kind!=:rbrace
234
+ s=statement()
235
+ body << s if s
236
+ end
237
+ expect :rbrace
238
+ dedent
239
+ return body
240
+ end
241
+
242
+ def statement(arg=nil)
243
+ indent "statement ...#{showNext.kind} #{showNext.pos.first}"
244
+ case showNext.kind
245
+ when :lbrace
246
+ ret=parse_body()
247
+ when :unsigned,:signed,:int,:short,:float,:double,:long,:char,:void
248
+ ret=declaration()
249
+ when :struct
250
+ ret=declaration()
251
+ when :if
252
+ ret=parse_if()
253
+ when :while
254
+ ret=parse_while()
255
+ when :for
256
+ ret=parse_for()
257
+ when :switch
258
+ ret=switch()
259
+ when :return
260
+ ret=parse_return
261
+ when :break
262
+ acceptIt
263
+ ret=Break.new
264
+ when :continue
265
+ acceptIt
266
+ ret=Continue.new
267
+ when :do
268
+ ret=do_while()
269
+ when :goto
270
+ ret=parse_goto()
271
+ when :ident
272
+ case showNext(2).kind
273
+ when :ident
274
+ ret=declaration
275
+ when :colon
276
+ l=parse_label
277
+ s=statement
278
+ ret=LabeledStmt.new(l,s)
279
+ else
280
+ ret=expression_statement
281
+ end
282
+ when :const,:volatile
283
+ declaration
284
+ when :semicolon
285
+ acceptIt
286
+ #ret=expression_statement
287
+ when :inc_op,:dec_op
288
+ ret=expression_statement
289
+ else
290
+ show_line(showNext.pos)
291
+ raise "unknown statement start at #{showNext.pos} .Got #{showNext.kind} #{showNext.val}"
292
+ end
293
+ maybe :semicolon
294
+ dedent
295
+ return ret
296
+ end
297
+
298
+ def parse_label
299
+ expect :ident
300
+ expect :colon
301
+ end
302
+
303
+ def parse_goto
304
+ indent "goto"
305
+ expect :goto #label
306
+ id=expect(:ident)
307
+ dedent
308
+ Goto.new(id)
309
+ end
310
+
311
+ def do_while
312
+ indent "do_while"
313
+ expect :do
314
+ body=statement()
315
+ expect :while
316
+ e=expression
317
+ dedent
318
+ DoWhile.new(e,body)
319
+ end
320
+
321
+ def switch
322
+ indent "switch"
323
+ expect :switch
324
+ expect :lparen
325
+ e=expression
326
+ ret=Switch.new(e,cases=[],default=nil)
327
+ expect :rparen
328
+ expect :lbrace
329
+ while showNext.is_a? :case
330
+ expect :case
331
+ case_e=expression
332
+ case_body=Body.new
333
+ expect :colon
334
+ while showNext.kind!=:rbrace and showNext.kind!=:case and showNext.kind!=:default
335
+ case_body << statement()
336
+ end
337
+ cases << Case.new(case_e,case_body)
338
+ end
339
+ if showNext.is_a? :default
340
+ acceptIt
341
+ expect :colon
342
+ default_body=Body.new
343
+ while showNext.kind!=:rbrace
344
+ default_body << statement()
345
+ end
346
+ ret.default=default_body
347
+ end
348
+ expect :rbrace
349
+ dedent
350
+ return ret
351
+ end
352
+
353
+ def parse_return
354
+ indent "parse_return"
355
+ expect :return
356
+ unless showNext.is_a? :semicolon
357
+ e=expression
358
+ end
359
+ dedent
360
+ Return.new(e)
361
+ end
362
+
363
+ # int a
364
+ # int * a
365
+ # int a=1,b=2;
366
+ # int a[]
367
+ # int* f()
368
+ # struct name *ptr;
369
+ # paire_t paire = {1,2};
370
+ # int a,b[10],*c
371
+ #------------------------------
372
+ # TYPE ident
373
+ # ident ident
374
+
375
+ def declaration
376
+ ret=[]
377
+ @current_type=type=parse_type()
378
+ d=declarator()
379
+ a=arrayed?(type)
380
+ if a
381
+ type=a
382
+ end
383
+ func=parenthesized?
384
+ if func
385
+ func.type=type
386
+ ret << func #func
387
+ return ret
388
+ end
389
+ init=initialization?
390
+ ret << Decl.new(type,d,init)
391
+ while tokens.any? and showNext.is_a?(:comma)
392
+ acceptIt
393
+ ptr=pointed?
394
+ if ptr
395
+ type2=PointerTo.new(type)
396
+ end
397
+ d2=declarator
398
+ a2=arrayed?(type)
399
+ i2=initialization?
400
+ ret << Decl.new(type2||type,d2)
401
+ end
402
+ if tokens.any?
403
+ maybe :semicolon
404
+ end
405
+ return ret
406
+ end
407
+
408
+ def declarator
409
+ if showNext.is_a? :ident
410
+ ret=@current_ident=Ident.new(acceptIt)
411
+ end
412
+ return ret
413
+ end
414
+
415
+ def pointed?
416
+ return if tokens.empty?
417
+ while showNext.is_a? :mul
418
+ acceptIt
419
+ end
420
+ end
421
+
422
+ def arrayed?(type)
423
+ return if tokens.empty?
424
+ while showNext.is_a? :lbrack
425
+ acceptIt
426
+ if showNext.is_a? :rbrack
427
+ acceptIt
428
+ type=ArrayOf.new(type,IntLit.new(ZERO))
429
+ else
430
+ e=expression
431
+ type=ArrayOf.new(type,e)
432
+ expect :rbrack
433
+ end
434
+ end
435
+ return type
436
+ end
437
+
438
+ def initialization?
439
+ return if tokens.empty?
440
+ if showNext.is_a? :assign
441
+ expect :assign
442
+ e=expression
443
+ return e
444
+ end
445
+ end
446
+
447
+ def parenthesized?
448
+ return if tokens.empty?
449
+ if showNext.is_a? :lparen
450
+ f=function_decl(@current_ident,@current_type)
451
+ return f
452
+ end
453
+ end
454
+
455
+ def parse_type
456
+ indent "parse_type"
457
+ ret=Type.new(nil)
458
+
459
+ ret.precisions << spec_qualifier?() # const, volatile
460
+ if showNext.is_a? [:signed,:unsigned]
461
+ ret.precisions << acceptIt
462
+ end
463
+
464
+ case showNext.kind
465
+ when :ident,:char,:int,:short,:long,:float,:double,:void
466
+ ret.name=acceptIt
467
+ while showNext.is_a? [:char,:int,:short,:long,:float,:double,:void]
468
+ ret.precisions << ret.name
469
+ ret.name=acceptIt
470
+ end
471
+ ret.precisions.flatten!
472
+ when :struct
473
+ ret=parse_struct()
474
+ when :typedef
475
+ ret=typedef()
476
+ else
477
+ raise "Parsing ERROR in type declaration: '#{showNext}'"
478
+ end
479
+
480
+ while showNext.is_a? [:mul,:lparen]
481
+ case showNext.kind
482
+ when :mul
483
+ acceptIt
484
+ ret=PointerTo.new(ret)
485
+ when :lparen
486
+ acceptIt
487
+ if showNext.is_a? :rparen
488
+ acceptIt
489
+ else
490
+ expression
491
+ expect :rparen
492
+ end
493
+ end
494
+ end
495
+ dedent
496
+ return ret
497
+ end
498
+
499
+ def spec_qualifier?
500
+ list=[]
501
+ while showNext.is_a? STARTERS_TYPE_QUALIFIER
502
+ case showNext.kind
503
+ when :volatile
504
+ list << acceptIt
505
+ when :const
506
+ list << acceptIt
507
+ end
508
+ end
509
+ list
510
+ end
511
+
512
+ def parse_if
513
+ indent "parse_if"
514
+ expect :if
515
+ if showNext.is_a? :lparen # helps wrt casting.
516
+ acceptIt
517
+ lparen=true
518
+ end
519
+ cond=expression()
520
+ expect :rparen if lparen
521
+ body=Body.new
522
+ if showNext.is_a? :lbrace
523
+ lbrace=acceptIt
524
+ end
525
+ body << statement()
526
+ if lbrace
527
+ until showNext.is_a? :rbrace
528
+ body << statement
529
+ end
530
+ expect :rbrace
531
+ end
532
+ if showNext.is_a? :else
533
+ else_=parse_else()
534
+ end
535
+ dedent
536
+ return If.new(cond,body,else_)
537
+ end
538
+
539
+ def parse_else
540
+ indent "parse else"
541
+ expect :else
542
+ ret=Else.new
543
+ ret.body=statement()
544
+ dedent
545
+ return ret
546
+ end
547
+
548
+ def parse_while
549
+ indent "parse_while"
550
+ expect :while
551
+ cond=expression()
552
+ body=[]
553
+ body=statement()
554
+ dedent
555
+ return While.new(cond,body)
556
+ end
557
+
558
+ def parse_for
559
+ indent "parse_for"
560
+ forloop=For.new
561
+ expect :for
562
+ expect :lparen
563
+ forloop.init << expression_statement
564
+ forloop.cond = expression()
565
+ expect :semicolon
566
+ forloop.increment=expression()
567
+ expect :rparen
568
+ forloop.body=statement()
569
+ dedent
570
+ forloop
571
+ end
572
+
573
+ def parseLoopInit
574
+ indent "parseLoopInit"
575
+ ret=statement()
576
+ dedent
577
+ return [ret] # because for (int a,b=0;i<10;i++) is also possible.
578
+ # then parser returns an array of Decl
579
+ end
580
+
581
+ def parseLoopCond
582
+ indent "parseLoopCond"
583
+ e=expression()
584
+ dedent
585
+ return e
586
+ end
587
+
588
+ def parseLoopEnd
589
+ indent "parseLoopEnd"
590
+ s=statement()
591
+ dedent
592
+ return s
593
+ end
594
+
595
+ def parse_body
596
+ body=Body.new
597
+ expect :lbrace
598
+ while !showNext.is_a? :rbrace
599
+ body << statement()
600
+ end
601
+ expect :rbrace
602
+ return body
603
+ end
604
+
605
+ def expression_statement
606
+ if showNext.is_a? :semicolon
607
+ acceptIt
608
+ else
609
+ e=expression
610
+ expect :semicolon
611
+ return e
612
+ end
613
+ end
614
+ #===============================================================
615
+ def debug
616
+ puts " "*@indentation+@tokens[0..4].map{|t| "'#{t.val}'"}.join(" ")
617
+ end
618
+ #===============================================================
619
+ def expression
620
+ indent "expression : #{showNext}"
621
+ e1=assign()
622
+ while showNext.is_a? :comma
623
+ acceptIt
624
+ e2=assign()
625
+ e1=CommaStmt.new(e1,e2)
626
+ end
627
+ dedent
628
+ return e1
629
+ end
630
+
631
+ STARTERS_ARRAY_OR_STRUCT_INIT=[:lbrace]
632
+ STARTERS_PRIMARY=[:ident,:integer_lit,:float_lit,:string_lit,:char_lit,:lparen]+STARTERS_ARRAY_OR_STRUCT_INIT
633
+ UNARY_OP=[:and,:mul,:add,:sub,:tilde,:not]
634
+ STARTERS_UNARY=[:inc_op,:dec_op,:sizeof]+STARTERS_PRIMARY+UNARY_OP
635
+ ASSIGN_OP=[:assign,:add_assign,:sub_assign,:mul_assign,:div_assign,:mod_assign,:xor_assign]
636
+
637
+ def assign
638
+ indent "assign : #{showNext}"
639
+ e1=cond_expr
640
+ while showNext.is_a? ASSIGN_OP
641
+ op=acceptIt
642
+ e2=assign
643
+ e1=Assign.new(e1,op,e2)
644
+ end
645
+ dedent
646
+ return e1
647
+ end
648
+
649
+ def cond_expr
650
+ indent "cond_expr : #{showNext}"
651
+ e1=logor
652
+ while showNext.is_a? :qmark
653
+ acceptIt
654
+ e2=expression
655
+ expect :colon
656
+ e3=cond_expr
657
+ e1=CondExpr.new(e1,e2,e3)
658
+ end
659
+ dedent
660
+ return e1
661
+ end
662
+
663
+ def logor
664
+ indent "logor : #{showNext}"
665
+ e1=logand
666
+ while showNext.is_a? :oror
667
+ op=acceptIt
668
+ e2=logand
669
+ e1=Or2.new(e1,op,e2)
670
+ end
671
+ dedent
672
+ return e1
673
+ end
674
+
675
+ def logand
676
+ indent "logand : #{showNext}"
677
+ e1=inclor
678
+ while showNext.is_a? :andand
679
+ op=acceptIt
680
+ e2=inclor
681
+ e1=Binary.new(e1,op,e2)
682
+ end
683
+ dedent
684
+ e1
685
+ end
686
+
687
+ def inclor
688
+ indent "inclor : #{showNext}"
689
+ e1=exclor
690
+ while showNext.is_a? :or
691
+ op=acceptIt
692
+ e2=exclor
693
+ e1=Binary.new(e1,op,e2)
694
+ end
695
+ dedent
696
+ e1
697
+ end
698
+
699
+ def exclor
700
+ indent "exclor : #{showNext}"
701
+ e1=andexp
702
+ while showNext.is_a? :xor
703
+ op=acceptIt
704
+ e2=andexp
705
+ e1=Binary.new(e1,op,e2)
706
+ end
707
+ dedent
708
+ e1
709
+ end
710
+
711
+ def andexp
712
+ indent "andexp : #{showNext}"
713
+ e1=eqexp
714
+ while showNext.is_a? :and
715
+ op=acceptIt
716
+ e2=eqexp
717
+ e1=Binary.new(e1,op,e2)
718
+ end
719
+ dedent
720
+ e1
721
+ end
722
+
723
+ def eqexp
724
+ indent "eqexp : #{showNext}"
725
+ e1=relexp
726
+ while showNext.is_a? [:eq,:neq]
727
+ op=acceptIt
728
+ e2=relexp
729
+ e1=Binary.new(e1,op,e2)
730
+ end
731
+ dedent
732
+ e1
733
+ end
734
+
735
+ def relexp
736
+ indent "relexp : #{showNext}"
737
+ e1=shiftexp
738
+ while showNext.is_a? [:lte,:lt,:gte,:gt ]
739
+ op=acceptIt
740
+ e2=shiftexp
741
+ e1=Binary.new(e1,op,e2)
742
+ end
743
+ dedent
744
+ e1
745
+ end
746
+
747
+ def shiftexp
748
+ indent "shiftexp : #{showNext}"
749
+ e1=additive
750
+ while showNext.is_a? [:shift_l,:shift_r]
751
+ op=acceptIt
752
+ e2=additive
753
+ e1=Binary.new(e1,op,e2)
754
+ end
755
+ dedent
756
+ e1
757
+ end
758
+
759
+ def additive
760
+ indent "addititve : #{showNext}"
761
+ e1=multitive
762
+ while showNext.is_a? [:add,:sub]
763
+ op=acceptIt
764
+ e2=multitive
765
+ e1=Binary.new(e1,op,e2)
766
+ end
767
+ dedent
768
+ e1
769
+ end
770
+
771
+ def multitive
772
+ indent "multitive : #{showNext}"
773
+ e1=castexp
774
+ while showNext.is_a? [:mul,:div,:mod]
775
+ op=acceptIt
776
+ e2=castexp
777
+ e1=Binary.new(e1,op,e2)
778
+ end
779
+ dedent
780
+ e1
781
+ end
782
+
783
+ def castexp
784
+ indent "castexpr : #{showNext}"
785
+ case showNext.kind
786
+ when :lparen # parenth expr OR casting !
787
+ res=is_casting?
788
+ puts "casting? : #{res}" if $options[:verbose]
789
+ if res
790
+ e=casting
791
+ else
792
+ e=parenthesized
793
+ end
794
+ else
795
+ e=unary
796
+ end
797
+ dedent
798
+ return e
799
+ end
800
+
801
+ def is_casting?
802
+ i=0
803
+ tok=DUMMY
804
+ while tok.kind!=:rparen
805
+ tok=@tokens[i]
806
+ i+=1
807
+ end
808
+ tok=@tokens[i]
809
+ return false if tok.is_a? [:mul,:add,:sub]
810
+ return true if tok.is_a? STARTERS_UNARY-STARTERS_ARRAY_OR_STRUCT_INIT
811
+ return false
812
+ end
813
+
814
+ def casting
815
+ puts "casting : #{showNext}" if $options[:verbose]
816
+ expect :lparen
817
+ #typename
818
+ t=parse_type
819
+ expect :rparen
820
+ u=unary
821
+ CastedExpr.new(t,u)
822
+ end
823
+
824
+ def parenthesized
825
+ indent "parenthesized : #{showNext}"
826
+ expect :lparen
827
+ e=expression
828
+ expect :rparen
829
+ dedent
830
+ return Parenth.new(e)
831
+ end
832
+
833
+ def typename
834
+ indent "typename"
835
+ type=specifier_qualifier
836
+ while showNext.is_a? STARTERS_ABSTRACT_DECLARATOR
837
+ list << abstract_decl
838
+ end
839
+ dedent
840
+ list
841
+ end
842
+
843
+ def spec_qualifier_list
844
+ indent "spec_qualifier_list #{showNext.inspect}"
845
+ while showNext.is_a? STARTERS_TYPE_SPECIFIER+STARTERS_TYPE_QUALIFIER
846
+ if showNext.is_a? STARTERS_TYPE_SPECIFIER
847
+ list << type_specifier
848
+ else
849
+ list << type_qualifier
850
+ end
851
+ end
852
+ dedent
853
+ list
854
+ end
855
+
856
+ STARTERS_TYPE_SPECIFIER=[:void,:char,:short,:int,:long,:float,:signed,:unsigned,:struct,:union,:enum,:ident]
857
+ def type_specifier
858
+ type=Type.new(nil,[])
859
+ indent "type_specifier #{showNext}"
860
+ if showNext.is_a? STARTERS_TYPE_SPECIFIER
861
+ ret=acceptIt
862
+ type.name=ret
863
+ else
864
+ raise "ERROR : type_specifier. Expecting one of '#{STARTERS_TYPE_SPECIFIER}' at #{showNext.pos}"
865
+ end
866
+ dedent
867
+ type
868
+ end
869
+
870
+ # abstract_declarator
871
+ # : pointer
872
+ # | direct_abstract_declarator
873
+ # | pointer direct_abstract_declarator
874
+ # ;
875
+ STARTERS_ABSTRACT_DECLARATOR=[:mul,:lparen,:lbrack]
876
+ def abstract_decl
877
+ indent "abstract_decl"
878
+ if showNext.is_a? STARTERS_ABSTRACT_DECLARATOR
879
+ case showNext.kind
880
+ when :mul
881
+ pointer
882
+ else
883
+ direct_abstract_declarator
884
+ end
885
+ else
886
+ raise "ERROR : in abstract_declarator. Expecting one of #{STARTERS_ABSTRACT_DECLARATOR}"
887
+ end
888
+ dedent
889
+ end
890
+
891
+ # pointer
892
+ # : '*'
893
+ # | '*' type_qualifier_list
894
+ # | '*' pointer
895
+ # | '*' type_qualifier_list pointer
896
+ # ;
897
+ STARTERS_TYPE_QUALIFIER=[:const,:volatile]
898
+ def pointer
899
+ expect :mul
900
+ while showNext.is_a? STARTERS_TYPE_QUALIFIER+[:mul]
901
+ case showNext.kind
902
+ when :volatile
903
+ acceptIt
904
+ when :const
905
+ acceptIt
906
+ when :mult
907
+ acceptIt
908
+ end
909
+ end
910
+ end
911
+
912
+ def direct_abstract_declarator
913
+ raise
914
+ end
915
+
916
+ def unary
917
+ if STARTERS_PRIMARY.include? showNext.kind
918
+ u=postfix
919
+ elsif showNext.is_a? [:and,:mul,:add,:sub,:tilde,:not]
920
+ op=acceptIt
921
+ e=castexp
922
+ u=Unary.new(op,e)
923
+ else
924
+ case showNext.kind
925
+ when :inc_op
926
+ op=acceptIt
927
+ u=unary
928
+ u=PreFixAccu.new(op,u)
929
+ when :dec_op
930
+ op=acceptIt
931
+ u=unary
932
+ u=PreFixAccu.new(op,u)
933
+ when :sizeof
934
+ u=sizeof()
935
+ else
936
+ raise "not an unary"
937
+ end
938
+ end
939
+ return u
940
+ end
941
+
942
+ def sizeof
943
+ expect :sizeof
944
+ case showNext.kind
945
+ when :lparen
946
+ acceptIt
947
+ #e=typename
948
+ e=parse_type
949
+ expect :rparen
950
+ else
951
+ #e=unary
952
+ e=expression
953
+ end
954
+ Sizeof.new(e)
955
+ end
956
+
957
+ def postfix
958
+ indent "postfix : #{showNext}"
959
+ e1=primary
960
+ while showNext.is_a? [:lbrack,:lparen,:dot,:inc_op,:dec_op,:ptr_op]
961
+ case showNext.kind
962
+ when :lbrack
963
+ acceptIt
964
+ e2=expression
965
+ expect :rbrack
966
+ e1=Indexed.new(e1,e2)
967
+ when :lparen
968
+ acceptIt
969
+ args=[]
970
+ if !showNext.is_a? :rparen
971
+ args=argument_expr_list
972
+ end
973
+ expect :rparen
974
+ args=linearize_comma_stmt(args)
975
+ e1=FunCall.new(e1,args)
976
+ when :dot
977
+ acceptIt
978
+ e2=Ident.new(expect :ident)
979
+ e1=Dotted.new(e1,e2)
980
+ when :ptr_op
981
+ op=acceptIt
982
+ expect :ident
983
+ when :inc_op,:dec_op
984
+ op=acceptIt
985
+ e1=PostFixAccu.new(e1,op)
986
+ end
987
+ end
988
+ dedent
989
+ e1
990
+ end
991
+
992
+ def linearize_comma_stmt ary
993
+ ary.collect do |stmt|
994
+ case stmt
995
+ when CommaStmt
996
+ stmt.to_list
997
+ else
998
+ stmt
999
+ end
1000
+ end.flatten
1001
+ end
1002
+
1003
+ def primary
1004
+ case showNext.kind
1005
+ when :ident
1006
+ return Ident.new(acceptIt)
1007
+ when :integer_lit
1008
+ return IntLit.new(acceptIt)
1009
+ when :float_lit
1010
+ return FloatLit.new(acceptIt)
1011
+ when :string_lit
1012
+ return StrLit.new(acceptIt)
1013
+ when :char_lit
1014
+ return CharLit.new(acceptIt)
1015
+ when :lparen
1016
+ acceptIt
1017
+ e=expression
1018
+ expect :rparen
1019
+ return Parenth.new(e)
1020
+ when :lbrace
1021
+ return array_or_struct_init()
1022
+ end
1023
+ end
1024
+
1025
+ def argument_expr_list
1026
+ list=[]
1027
+ list << expression
1028
+ while showNext.is_a? :comma
1029
+ acceptIt
1030
+ list << expression
1031
+ end
1032
+ list
1033
+ end
1034
+
1035
+ def array_or_struct_init
1036
+ indent "array_or_struct_init"
1037
+ expect :lbrace
1038
+ elements=[]
1039
+ while !showNext.is_a? :rbrace
1040
+ elements << (e=expression)
1041
+ if showNext.is_a? :comma
1042
+ acceptIt
1043
+ end
1044
+ end
1045
+ expect :rbrace
1046
+ dedent
1047
+ return ArrayOrStructInit.new(elements)
1048
+ end
1049
+
1050
+ end#class Parser
1051
+ end #module
1052
+
1053
+ def show_lines str,upto=nil
1054
+ lines=str.split(/\n/)
1055
+ upto=upto || lines.size
1056
+ lines[0..upto].each_with_index do |line,idx|
1057
+ puts "#{(idx+1).to_s.ljust(5)}|#{line}"
1058
+ end
1059
+ end
1060
+
1061
+ if $PROGRAM_NAME == __FILE__
1062
+ require_relative 'dot_printer_rec'
1063
+ str=IO.read(ARGV[0])
1064
+ show_lines(str)
1065
+ t1 = Time.now
1066
+ parser=C::Parser.new
1067
+ ast=parser.parse(str)
1068
+ dot=C::DotPrinter.new.print(ast)
1069
+ dot.save_as "test.dot"
1070
+ t2 = Time.now
1071
+ puts "parsed in : #{t2-t1} s"
1072
+ end