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.
@@ -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