chelsy 0.0.3 → 0.0.4
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 +4 -4
- data/.travis.yml +1 -0
- data/.yardopts +1 -0
- data/README.md +38 -6
- data/chelsy.gemspec +12 -11
- data/lib/chelsy/ast.rb +922 -91
- data/lib/chelsy/syntax.rb +23 -10
- data/lib/chelsy/translator.rb +562 -43
- data/lib/chelsy/version.rb +1 -1
- data/sample/hello_chelsy.rb +1 -2
- data/sample/temperature.c +17 -0
- data/sample/temperature.rb +39 -0
- metadata +21 -4
data/lib/chelsy/ast.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "chelsy/syntax"
|
2
|
+
require "forwardable"
|
2
3
|
|
3
4
|
module Chelsy
|
4
5
|
|
@@ -7,41 +8,87 @@ module Chelsy
|
|
7
8
|
end
|
8
9
|
end
|
9
10
|
|
10
|
-
# The class must provide a method
|
11
|
+
# The class must provide a method validate_node`
|
11
12
|
module NodeList
|
12
13
|
include Enumerable
|
14
|
+
extend Forwardable
|
15
|
+
|
16
|
+
def_delegators :@items, :size, :empty?, :[]
|
17
|
+
|
18
|
+
def initialize(items=[], **rest)
|
19
|
+
@items = items.map {|element| validate_node(element) }
|
20
|
+
super(**rest)
|
21
|
+
end
|
13
22
|
|
14
23
|
def each(&block)
|
15
|
-
items.each(&block)
|
24
|
+
@items.each(&block)
|
16
25
|
self
|
17
26
|
end
|
18
27
|
|
19
|
-
def size; items.size end
|
20
|
-
def empty?; items.empty? end
|
21
|
-
|
22
28
|
def <<(node)
|
23
|
-
items << validate_node(node)
|
29
|
+
@items << validate_node(node)
|
24
30
|
self
|
25
31
|
end
|
32
|
+
|
33
|
+
def concat(enumerable)
|
34
|
+
enumerable.each {|it| @items << validate_node(it) }
|
35
|
+
self
|
36
|
+
end
|
37
|
+
|
38
|
+
def []=(*args)
|
39
|
+
value = args[-1]
|
40
|
+
value = case value
|
41
|
+
when Enumerable
|
42
|
+
value.map {|v| validate_node(v) }
|
43
|
+
else
|
44
|
+
validate_node(value)
|
45
|
+
end
|
46
|
+
args[-1] = value
|
47
|
+
@items.send(:[]=, *args)
|
48
|
+
end
|
26
49
|
end
|
27
50
|
|
28
51
|
class Fragment < Node
|
29
52
|
end
|
30
53
|
|
54
|
+
module Comment
|
55
|
+
class Base < Fragment
|
56
|
+
end
|
57
|
+
|
58
|
+
# `// ...`
|
59
|
+
class Single < Base
|
60
|
+
attr_reader :body
|
61
|
+
|
62
|
+
def initialize(body, **rest)
|
63
|
+
@body = body.dup
|
64
|
+
super **rest
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# `/* ... */`
|
69
|
+
class Multi < Base
|
70
|
+
attr_reader :lines
|
71
|
+
|
72
|
+
def initialize(body, **rest)
|
73
|
+
@lines = case body
|
74
|
+
when String
|
75
|
+
body.split(/\n/)
|
76
|
+
else
|
77
|
+
body.to_a
|
78
|
+
end
|
79
|
+
super **rest
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
31
85
|
module Syntax
|
32
|
-
Fragment = Any.new('Fragment', [Fragment, String])
|
33
86
|
end
|
34
87
|
|
35
88
|
class FragmentList < Node
|
36
89
|
include NodeList
|
37
90
|
|
38
|
-
def initialize(**rest)
|
39
|
-
@fragments = []
|
40
|
-
super(**rest)
|
41
|
-
end
|
42
|
-
|
43
91
|
private
|
44
|
-
def items; @fragments end
|
45
92
|
def validate_node(node); Syntax::Fragment.ensure(node) end
|
46
93
|
end
|
47
94
|
|
@@ -60,19 +107,98 @@ module Chelsy
|
|
60
107
|
end
|
61
108
|
end
|
62
109
|
|
63
|
-
class
|
64
|
-
|
110
|
+
class Declarative < Element
|
111
|
+
attr_reader :storage
|
65
112
|
|
66
|
-
|
67
|
-
|
68
|
-
@extern = !!extern
|
69
|
-
@static = !!static
|
113
|
+
def initialize(storage: nil, **rest)
|
114
|
+
@storage = Syntax::Storage.ensure(storage) if storage
|
70
115
|
|
71
116
|
super(**rest)
|
72
117
|
end
|
73
118
|
|
74
|
-
def extern?; @extern end
|
75
|
-
def static?; @static end
|
119
|
+
def extern?; @storage == :extern end
|
120
|
+
def static?; @storage == :static end
|
121
|
+
def init; nil end
|
122
|
+
end
|
123
|
+
|
124
|
+
# Struct or Union member with bit-field
|
125
|
+
#
|
126
|
+
# Unnamed bit-field ::
|
127
|
+
# A bit-field declaration with no declarator, but only a colon and a width
|
128
|
+
class BitField < Element
|
129
|
+
attr_reader :declaration, :bits
|
130
|
+
|
131
|
+
def initialize(bits, declaration=nil, **rest)
|
132
|
+
@declaration = Syntax::Declaration.ensure(declaration) if declaration
|
133
|
+
@bits = bits && Syntax::BitField.ensure(bits)
|
134
|
+
|
135
|
+
super **rest
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
class EnumMember < Element
|
140
|
+
attr_reader :name, :init
|
141
|
+
|
142
|
+
def initialize(name, init=nil, **rest)
|
143
|
+
@name = name.to_sym
|
144
|
+
@init = init
|
145
|
+
super **rest
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
class StructOrUnionMemberList < Element
|
150
|
+
include NodeList
|
151
|
+
|
152
|
+
private
|
153
|
+
def validate_node(node); Syntax::StructOrUnionMember.ensure(node) end
|
154
|
+
end
|
155
|
+
|
156
|
+
class EnumMemberList < Element
|
157
|
+
include NodeList
|
158
|
+
|
159
|
+
private
|
160
|
+
def validate_node(node); Syntax::EnumMember.ensure(node) end
|
161
|
+
end
|
162
|
+
|
163
|
+
# === 6.7.8 Initialization
|
164
|
+
class Designator < Element
|
165
|
+
end
|
166
|
+
|
167
|
+
# { [1] = 10, [2] = 20, ...}
|
168
|
+
class IndexDesignator < Designator
|
169
|
+
attr_reader :index
|
170
|
+
|
171
|
+
def initialize(index, **rest)
|
172
|
+
@index = Syntax::Expr.ensure(index)
|
173
|
+
super **rest
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
# { .a = 10, .b = 20, ...}
|
178
|
+
class MemberDesignator < Designator
|
179
|
+
attr_reader :name
|
180
|
+
|
181
|
+
def initialize(name, **rest)
|
182
|
+
@name = Syntax::Ident.ensure(name)
|
183
|
+
super **rest
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
class Initializer < Element
|
188
|
+
attr_reader :designator, :value
|
189
|
+
|
190
|
+
def initialize(value, designator=nil, **rest)
|
191
|
+
@value = value
|
192
|
+
@designator = designator
|
193
|
+
super **rest
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
class InitializerList < Element
|
198
|
+
include NodeList
|
199
|
+
|
200
|
+
private
|
201
|
+
def validate_node(node); Syntax::Initializer.ensure(node) end
|
76
202
|
end
|
77
203
|
|
78
204
|
class Expr < Element
|
@@ -82,45 +208,76 @@ module Chelsy
|
|
82
208
|
end
|
83
209
|
|
84
210
|
module Syntax
|
85
|
-
Ident = Any.new('Identifier', [Symbol])
|
86
|
-
Expr = Any.new('Expression', [Expr, Symbol])
|
87
|
-
TopLevel = Any.new('TopLevel', [Definition, Declaration])
|
88
211
|
end
|
89
212
|
|
90
213
|
# `Document` represents a _translation unit_ (file).
|
91
214
|
class Document < Element
|
92
215
|
include NodeList
|
93
216
|
|
94
|
-
def initialize(**rest)
|
95
|
-
@items = []
|
96
|
-
super(**rest)
|
97
|
-
end
|
98
|
-
|
99
217
|
private
|
100
|
-
def items; @items end
|
101
218
|
def validate_node(node); Syntax::TopLevel.ensure(node) end
|
102
219
|
end
|
103
220
|
|
104
221
|
# = 6.2.5 Types
|
105
222
|
module Type
|
106
223
|
class Base < Element
|
107
|
-
def initialize(const: false,
|
224
|
+
def initialize(const: false, volatile: false, **rest)
|
108
225
|
@const = !!const
|
109
|
-
@restrict = !!restrict
|
110
226
|
@volatile = !!volatile
|
111
227
|
|
112
228
|
super(**rest)
|
113
229
|
end
|
114
230
|
|
115
231
|
def const?; @const end
|
116
|
-
def restrict?; @restrict end
|
117
232
|
def volatile?; @volatile end
|
118
233
|
|
119
234
|
def qualified?
|
120
|
-
@const || @
|
235
|
+
@const || @volatile
|
121
236
|
end
|
122
237
|
end
|
123
238
|
|
239
|
+
end
|
240
|
+
|
241
|
+
module Syntax
|
242
|
+
end
|
243
|
+
|
244
|
+
# Function and prototype params
|
245
|
+
class Param < Element
|
246
|
+
attr_reader :name, :type
|
247
|
+
|
248
|
+
def initialize(name, type, register: false, **rest)
|
249
|
+
@name = Syntax::Ident.ensure(name)
|
250
|
+
@type = Syntax::Type.ensure(type)
|
251
|
+
|
252
|
+
super(**rest)
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
module Syntax
|
257
|
+
end
|
258
|
+
|
259
|
+
class IdentList < Element
|
260
|
+
include NodeList
|
261
|
+
|
262
|
+
private
|
263
|
+
def validate_node(node); Syntax::Ident.ensure(node) end
|
264
|
+
end
|
265
|
+
|
266
|
+
class ParamList < Element
|
267
|
+
include NodeList
|
268
|
+
|
269
|
+
private
|
270
|
+
def validate_node(node); Syntax::Param.ensure(node) end
|
271
|
+
end
|
272
|
+
|
273
|
+
class ProtoParamList < Element
|
274
|
+
include NodeList
|
275
|
+
|
276
|
+
private
|
277
|
+
def validate_node(node); Syntax::ProtoParam.ensure(node) end
|
278
|
+
end
|
279
|
+
|
280
|
+
module Type
|
124
281
|
class Numeric < Base
|
125
282
|
end
|
126
283
|
|
@@ -186,33 +343,108 @@ module Chelsy
|
|
186
343
|
class Pointer < Derived
|
187
344
|
attr_reader :pointee
|
188
345
|
|
189
|
-
def initialize(pointee, **rest)
|
346
|
+
def initialize(pointee, restrict: false, **rest)
|
190
347
|
@pointee = Syntax::Type.ensure(pointee)
|
348
|
+
@restrict = !!restrict
|
349
|
+
|
191
350
|
super(**rest)
|
192
351
|
end
|
352
|
+
|
353
|
+
def restrict?; @restrict end
|
354
|
+
|
355
|
+
def qualified?
|
356
|
+
@restrict || super
|
357
|
+
end
|
358
|
+
|
359
|
+
def termination_type
|
360
|
+
pointee = self.pointee
|
361
|
+
while pointee.is_a?(Type::Pointer)
|
362
|
+
pointee = pointee.pointee
|
363
|
+
end
|
364
|
+
pointee
|
365
|
+
end
|
193
366
|
end
|
194
367
|
|
368
|
+
# From: 6.7.5.3 Function declarators (including prototypes)
|
369
|
+
#
|
370
|
+
# qualifier in parameter array declarator
|
371
|
+
#
|
372
|
+
# > A declaration of a parameter as ‘‘array of type’’ shall be adjusted to
|
373
|
+
# > ‘‘qualified pointer to type’’, where the type qualifiers (if any) are
|
374
|
+
# > those specified within the [ and ] of the array type derivation.
|
375
|
+
#
|
376
|
+
# `static` in parameter array declarator
|
377
|
+
#
|
378
|
+
# > If the keyword static also appears within the [ and ] of the array type derivation,
|
379
|
+
# > then for each call to the function, the value of the corresponding actual argument shall
|
380
|
+
# > provide access to the first element of an array with at least as many elements as
|
381
|
+
# > specified by the size expression.
|
195
382
|
class Array < Derived
|
196
383
|
attr_reader :element_type, :size
|
197
384
|
|
198
|
-
def initialize(element_type, size = nil, **rest)
|
385
|
+
def initialize(element_type, size = nil, static: false, **rest)
|
199
386
|
@element_type = element_type
|
200
|
-
@size = size
|
387
|
+
@size = size && Syntax::ArraySize.ensure(size)
|
388
|
+
@static = !!static
|
201
389
|
|
202
390
|
super(**rest)
|
203
391
|
end
|
204
392
|
|
205
393
|
# An array type of unknown size is an incomplete type.
|
206
394
|
def incomplete?; @size.nil? end
|
395
|
+
def variable?; @size == :* end
|
396
|
+
|
397
|
+
def static?; @static end
|
207
398
|
end
|
208
399
|
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
400
|
+
class Function < Derived
|
401
|
+
attr_reader :return_type, :params
|
402
|
+
|
403
|
+
def initialize(return_type, params, **rest)
|
404
|
+
@return_type = Syntax::Type.ensure(return_type)
|
405
|
+
@params = ProtoParamList.new(params)
|
406
|
+
|
407
|
+
super(**rest)
|
408
|
+
end
|
409
|
+
end
|
410
|
+
|
411
|
+
# Struct, Unicon, Enum
|
412
|
+
|
413
|
+
class Taggable < Derived
|
414
|
+
attr_reader :tag
|
415
|
+
|
416
|
+
def initialize(tag, **rest)
|
417
|
+
@tag = tag.to_sym
|
418
|
+
super **rest
|
419
|
+
end
|
420
|
+
end
|
421
|
+
|
422
|
+
module StructOrUnion
|
423
|
+
attr_reader :members
|
424
|
+
|
425
|
+
def initialize(tag, members=nil, **rest)
|
426
|
+
@members = StructOrUnionMemberList.new(members) if members
|
427
|
+
super tag, **rest
|
428
|
+
end
|
429
|
+
end
|
430
|
+
|
431
|
+
class Struct < Taggable
|
432
|
+
include StructOrUnion
|
433
|
+
end
|
434
|
+
|
435
|
+
class Union < Taggable
|
436
|
+
include StructOrUnion
|
437
|
+
end
|
438
|
+
|
439
|
+
class Enum < Taggable
|
440
|
+
attr_reader :members
|
441
|
+
|
442
|
+
def initialize(tag, members=nil, **rest)
|
443
|
+
@members = EnumMemberList.new(members) if members
|
444
|
+
super tag, **rest
|
445
|
+
end
|
446
|
+
end
|
213
447
|
|
214
|
-
module Syntax
|
215
|
-
Type = Any.new('TypeSpecifier', [Chelsy::Type::Base, :void])
|
216
448
|
end
|
217
449
|
|
218
450
|
# 6.4.4.1 Integer constants
|
@@ -247,6 +479,9 @@ module Chelsy
|
|
247
479
|
|
248
480
|
end
|
249
481
|
|
482
|
+
module Syntax
|
483
|
+
end
|
484
|
+
|
250
485
|
# 6.4.5 String literals
|
251
486
|
module Constant
|
252
487
|
|
@@ -267,20 +502,420 @@ module Chelsy
|
|
267
502
|
|
268
503
|
end
|
269
504
|
|
270
|
-
|
271
|
-
|
272
|
-
|
505
|
+
module Operator
|
506
|
+
class Base < Expr
|
507
|
+
def self.operator; nil end
|
508
|
+
end
|
273
509
|
|
274
|
-
|
275
|
-
|
276
|
-
@args = args.map {|a| Syntax::Expr.ensure(a) }
|
510
|
+
class Unary < Base
|
511
|
+
attr_reader :operand
|
277
512
|
|
278
|
-
|
513
|
+
def initialize(operand, **rest)
|
514
|
+
# `sizeof` operator accepts expr or type as its operand.
|
515
|
+
@operand = operand
|
516
|
+
super **rest
|
517
|
+
end
|
518
|
+
end
|
519
|
+
|
520
|
+
class Postfix < Unary
|
521
|
+
def initialize(operand, **rest)
|
522
|
+
super Syntax::Expr.ensure(operand), **rest
|
523
|
+
end
|
524
|
+
end
|
525
|
+
|
526
|
+
class Prefix < Unary
|
527
|
+
def initialize(operand, **rest)
|
528
|
+
super Syntax::Expr.ensure(operand), **rest
|
529
|
+
end
|
530
|
+
end
|
531
|
+
|
532
|
+
class Binary < Base
|
533
|
+
attr_reader :lhs, :rhs
|
534
|
+
|
535
|
+
def initialize(lhs, rhs, **rest)
|
536
|
+
@lhs = Syntax::Expr.ensure(lhs)
|
537
|
+
@rhs = Syntax::Expr.ensure(rhs)
|
538
|
+
super **rest
|
539
|
+
end
|
540
|
+
end
|
541
|
+
|
542
|
+
# Ternary conditional
|
543
|
+
class Conditional < Base
|
544
|
+
attr_reader :condition, :then, :else
|
545
|
+
|
546
|
+
def self.operator; :"?:" end
|
547
|
+
|
548
|
+
def initialize(condition, then_expr, else_expr, **rest)
|
549
|
+
@condition = Syntax::Expr.ensure(condition)
|
550
|
+
@then = Syntax::Expr.ensure(then_expr)
|
551
|
+
@else = Syntax::Expr.ensure(else_expr)
|
552
|
+
|
553
|
+
super **rest
|
554
|
+
end
|
555
|
+
end
|
556
|
+
|
557
|
+
# === 6.5.2.1 Array subscripting
|
558
|
+
class Subscription < Postfix
|
559
|
+
attr_reader :index
|
560
|
+
|
561
|
+
def self.operator; :"[]" end
|
562
|
+
|
563
|
+
def initialize(subscriptee, index, **rest)
|
564
|
+
@index = Syntax::Expr.ensure(index)
|
565
|
+
super subscriptee, **rest
|
566
|
+
end
|
567
|
+
|
568
|
+
def subscriptee; operand end
|
569
|
+
end
|
570
|
+
|
571
|
+
# === 6.5.2.2 Function calls
|
572
|
+
class Call < Postfix
|
573
|
+
attr_reader :args
|
574
|
+
|
575
|
+
def self.operator; :"()" end
|
576
|
+
|
577
|
+
def initialize(callee, args, **rest)
|
578
|
+
@args = args.map {|a| Syntax::Expr.ensure(a) }
|
579
|
+
|
580
|
+
super callee, **rest
|
581
|
+
end
|
582
|
+
|
583
|
+
def callee; operand end
|
584
|
+
end
|
585
|
+
|
586
|
+
# === 6.5.2.3 Structure and union members
|
587
|
+
class Access < Postfix
|
588
|
+
attr_reader :name
|
589
|
+
|
590
|
+
def self.operator; :"." end
|
591
|
+
|
592
|
+
def initialize(object, name, **rest)
|
593
|
+
@name = Syntax::Ident.ensure(name)
|
594
|
+
super object, **rest
|
595
|
+
end
|
596
|
+
|
597
|
+
def object; operand end
|
598
|
+
end
|
599
|
+
|
600
|
+
class IndirectAccess < Access
|
601
|
+
def self.operator; :"->" end
|
602
|
+
end
|
603
|
+
|
604
|
+
# === 6.5.2.4 Postfix increment and decrement operators
|
605
|
+
class PostfixIncrement < Postfix
|
606
|
+
def self.operator; :"++" end
|
607
|
+
end
|
608
|
+
|
609
|
+
class PostfixDecrement < Postfix
|
610
|
+
def self.operator; :"--" end
|
611
|
+
end
|
612
|
+
|
613
|
+
# === 6.5.3 Unary operators
|
614
|
+
class PrefixIncrement < Prefix
|
615
|
+
def self.operator; :"++" end
|
616
|
+
end
|
617
|
+
|
618
|
+
class PrefixDecrement < Prefix
|
619
|
+
def self.operator; :"--" end
|
620
|
+
end
|
621
|
+
|
622
|
+
# Unary plus
|
623
|
+
class Plus < Prefix
|
624
|
+
def self.operator; :"+" end
|
625
|
+
end
|
626
|
+
|
627
|
+
# Unary minus
|
628
|
+
class Minus < Prefix
|
629
|
+
def self.operator; :"-" end
|
630
|
+
end
|
631
|
+
|
632
|
+
# Logical NOT
|
633
|
+
class Not < Prefix
|
634
|
+
def self.operator; :"!" end
|
635
|
+
end
|
636
|
+
|
637
|
+
# Bitwise NOT
|
638
|
+
class BitwiseNot < Prefix
|
639
|
+
def self.operator; :"~" end
|
640
|
+
end
|
641
|
+
|
642
|
+
# Indirection (dereference)
|
643
|
+
class Dereference < Prefix
|
644
|
+
def self.operator; :"*" end
|
645
|
+
end
|
646
|
+
|
647
|
+
# Address-of
|
648
|
+
class Address < Prefix
|
649
|
+
def self.operator; :"&" end
|
650
|
+
end
|
651
|
+
|
652
|
+
# Type cast
|
653
|
+
class Cast < Prefix
|
654
|
+
attr_reader :type
|
655
|
+
|
656
|
+
def self.operator; :"()" end
|
657
|
+
|
658
|
+
def initialize(operand, type, **rest)
|
659
|
+
@type = Syntax::Type.ensure(type)
|
660
|
+
super operand, **rest
|
661
|
+
end
|
662
|
+
end
|
663
|
+
|
664
|
+
# Size-of
|
665
|
+
class SizeOf < Unary
|
666
|
+
def self.operator; :"sizeof" end
|
667
|
+
|
668
|
+
def initialize(operand, **rest)
|
669
|
+
super Syntax::ExprOrType.ensure(operand), **rest
|
670
|
+
end
|
671
|
+
end
|
672
|
+
|
673
|
+
# `defined` unary operator in conditional macro.
|
674
|
+
class Defined < Unary
|
675
|
+
def self.operator; :"defined" end
|
676
|
+
|
677
|
+
def initialize(operand, **rest)
|
678
|
+
super Syntax::Ident.ensure(operand), **rest
|
679
|
+
end
|
680
|
+
end
|
681
|
+
|
682
|
+
# == 6.5.5 Multiplicative operators
|
683
|
+
|
684
|
+
# Multiplication
|
685
|
+
class Mul < Binary
|
686
|
+
def self.operator; :* end
|
687
|
+
end
|
688
|
+
|
689
|
+
# Division
|
690
|
+
class Div < Binary
|
691
|
+
def self.operator; :/ end
|
692
|
+
end
|
693
|
+
|
694
|
+
# Remainder
|
695
|
+
class Rem < Binary
|
696
|
+
def self.operator; :% end
|
697
|
+
end
|
698
|
+
|
699
|
+
# Addition
|
700
|
+
class Add < Binary
|
701
|
+
def self.operator; :+ end
|
702
|
+
end
|
703
|
+
|
704
|
+
# Subtraction
|
705
|
+
class Sub < Binary
|
706
|
+
def self.operator; :- end
|
707
|
+
end
|
708
|
+
|
709
|
+
# Bitwise left shift and right shift
|
710
|
+
class BitwiseLeftShift < Binary
|
711
|
+
def self.operator; :<< end
|
712
|
+
end
|
713
|
+
|
714
|
+
class BitwiseRightShift < Binary
|
715
|
+
def self.operator; :>> end
|
716
|
+
end
|
717
|
+
|
718
|
+
# For relational operators < and ≤ respectively
|
719
|
+
class LessThan < Binary
|
720
|
+
def self.operator; :< end
|
721
|
+
end
|
722
|
+
|
723
|
+
class LessThanOrEqual < Binary
|
724
|
+
def self.operator; :<= end
|
725
|
+
end
|
726
|
+
|
727
|
+
# For relational operators > and ≥ respectively
|
728
|
+
class GreaterThan < Binary
|
729
|
+
def self.operator; :> end
|
730
|
+
end
|
731
|
+
|
732
|
+
class GreaterThanOrEqual < Binary
|
733
|
+
def self.operator; :>= end
|
734
|
+
end
|
735
|
+
|
736
|
+
# For relational = and ≠ respectively
|
737
|
+
class Equal < Binary
|
738
|
+
def self.operator; :== end
|
739
|
+
end
|
740
|
+
|
741
|
+
class NotEqual < Binary
|
742
|
+
def self.operator; :"!=" end
|
743
|
+
end
|
744
|
+
|
745
|
+
# Bitwise AND, XOR, OR
|
746
|
+
class BitwiseAnd < Binary
|
747
|
+
def self.operator; :& end
|
748
|
+
end
|
749
|
+
|
750
|
+
class BitwiseXor < Binary
|
751
|
+
def self.operator; :"^" end
|
752
|
+
end
|
753
|
+
|
754
|
+
class BitwiseOr < Binary
|
755
|
+
def self.operator; :"|" end
|
756
|
+
end
|
757
|
+
|
758
|
+
# Logical AND, OR
|
759
|
+
class And < Binary
|
760
|
+
def self.operator; :"&&" end
|
761
|
+
end
|
762
|
+
|
763
|
+
class Or < Binary
|
764
|
+
def self.operator; :"||" end
|
765
|
+
end
|
766
|
+
|
767
|
+
# === 6.5.16 Assignment operators
|
768
|
+
|
769
|
+
class Assign < Binary
|
770
|
+
def self.operator; :"=" end
|
771
|
+
end
|
772
|
+
|
773
|
+
class AssignAdd < Binary
|
774
|
+
def self.operator; :"+=" end
|
775
|
+
end
|
776
|
+
|
777
|
+
class AssignSub < Binary
|
778
|
+
def self.operator; :"-=" end
|
779
|
+
end
|
780
|
+
|
781
|
+
class AssignMul < Binary
|
782
|
+
def self.operator; :"*=" end
|
783
|
+
end
|
784
|
+
|
785
|
+
class AssignDiv < Binary
|
786
|
+
def self.operator; :"/=" end
|
787
|
+
end
|
788
|
+
|
789
|
+
class AssignRem < Binary
|
790
|
+
def self.operator; :"%=" end
|
791
|
+
end
|
792
|
+
|
793
|
+
class AssignBitwiseLeftShift < Binary
|
794
|
+
def self.operator; :"<<=" end
|
795
|
+
end
|
796
|
+
|
797
|
+
class AssignBitwiseLeftRight < Binary
|
798
|
+
def self.operator; :">>=" end
|
799
|
+
end
|
800
|
+
|
801
|
+
class AssignBitwiseAnd < Binary
|
802
|
+
def self.operator; :"&=" end
|
803
|
+
end
|
804
|
+
|
805
|
+
class AssignBitwiseXor < Binary
|
806
|
+
def self.operator; :"^=" end
|
807
|
+
end
|
808
|
+
|
809
|
+
class AssignBitwiseOr < Binary
|
810
|
+
def self.operator; :"|=" end
|
811
|
+
end
|
812
|
+
|
813
|
+
class Comma < Binary
|
814
|
+
def self.operator; :"," end
|
815
|
+
end
|
816
|
+
|
817
|
+
end
|
818
|
+
|
819
|
+
module Operator
|
820
|
+
# --- Operator precedence
|
821
|
+
# The following table lists the precedence of operators.
|
822
|
+
# Operators are listed top to bottom, in descending precedence.
|
823
|
+
|
824
|
+
PRECEDENCE_TABLE = [
|
825
|
+
# -- highest
|
826
|
+
[
|
827
|
+
PostfixIncrement, PostfixDecrement,
|
828
|
+
Call,
|
829
|
+
Subscription,
|
830
|
+
Access,
|
831
|
+
# Compound Literal
|
832
|
+
],
|
833
|
+
[
|
834
|
+
PrefixIncrement, PrefixDecrement,
|
835
|
+
Plus, Minus,
|
836
|
+
Not, BitwiseNot,
|
837
|
+
Cast,
|
838
|
+
Dereference,
|
839
|
+
Address,
|
840
|
+
SizeOf,
|
841
|
+
Defined,
|
842
|
+
],
|
843
|
+
[
|
844
|
+
Mul, Div, Rem,
|
845
|
+
],
|
846
|
+
[
|
847
|
+
Add, Sub,
|
848
|
+
],
|
849
|
+
[
|
850
|
+
BitwiseLeftShift, BitwiseRightShift,
|
851
|
+
],
|
852
|
+
[
|
853
|
+
LessThan, LessThanOrEqual,
|
854
|
+
GreaterThan, GreaterThanOrEqual,
|
855
|
+
],
|
856
|
+
[
|
857
|
+
Equal, NotEqual,
|
858
|
+
],
|
859
|
+
[
|
860
|
+
BitwiseAnd,
|
861
|
+
],
|
862
|
+
[
|
863
|
+
BitwiseXor,
|
864
|
+
],
|
865
|
+
[
|
866
|
+
BitwiseOr,
|
867
|
+
],
|
868
|
+
[
|
869
|
+
And,
|
870
|
+
],
|
871
|
+
[
|
872
|
+
Or,
|
873
|
+
],
|
874
|
+
[
|
875
|
+
Conditional,
|
876
|
+
],
|
877
|
+
[
|
878
|
+
Assign,
|
879
|
+
AssignAdd, AssignSub,
|
880
|
+
AssignMul, AssignDiv, AssignRem,
|
881
|
+
AssignBitwiseLeftShift, AssignBitwiseLeftRight,
|
882
|
+
AssignBitwiseAnd, AssignBitwiseXor, AssignBitwiseOr,
|
883
|
+
],
|
884
|
+
[
|
885
|
+
Comma,
|
886
|
+
],
|
887
|
+
]
|
888
|
+
|
889
|
+
# This hash contains precedence value (Fixnum) by Operator::Base classes.
|
890
|
+
# Higher precedence has higher value.
|
891
|
+
OPERATOR_PRECEDENCE = {}.tap do |table|
|
892
|
+
PRECEDENCE_TABLE.reverse.each_with_index do |op_classes, precedence|
|
893
|
+
op_classes.each do |klass|
|
894
|
+
table[klass] = precedence
|
895
|
+
end
|
896
|
+
end
|
897
|
+
end
|
898
|
+
|
899
|
+
class Base
|
900
|
+
def self.precedence
|
901
|
+
OPERATOR_PRECEDENCE[self] or raise NotImplementedError
|
902
|
+
end
|
279
903
|
end
|
280
904
|
end
|
281
905
|
|
282
906
|
# = 6.8 Statements and blocks
|
283
907
|
|
908
|
+
# == 6.8.1 Labeled statements
|
909
|
+
class Labeled < Stmt
|
910
|
+
attr_reader :label, :stmt
|
911
|
+
|
912
|
+
def initialize(label, stmt, **rest)
|
913
|
+
@label = Syntax::Ident.ensure(label)
|
914
|
+
@stmt = Syntax::Stmt.ensure(stmt)
|
915
|
+
super **rest
|
916
|
+
end
|
917
|
+
end
|
918
|
+
|
284
919
|
# == 6.8.3 Expression and null statements
|
285
920
|
|
286
921
|
# A null statement (consisting of just a semicolon) performs no operations.
|
@@ -298,31 +933,102 @@ module Chelsy
|
|
298
933
|
end
|
299
934
|
|
300
935
|
# == 6.8.2 Compound statement
|
301
|
-
module Syntax
|
302
|
-
BlockItem = Any.new('BlockItem', [Stmt, Declaration])
|
303
|
-
end
|
304
936
|
|
305
937
|
class Block < Stmt
|
306
938
|
include NodeList
|
307
939
|
|
308
|
-
def initialize(**rest)
|
309
|
-
@items = []
|
310
|
-
super(**rest)
|
311
|
-
end
|
312
|
-
|
313
940
|
private
|
314
|
-
def items; @items end
|
315
941
|
|
316
|
-
# Implicit convertion from Expr to ExprStmt
|
317
942
|
def validate_node(node)
|
318
|
-
|
319
|
-
|
943
|
+
Syntax::BlockItem.ensure(node)
|
944
|
+
end
|
945
|
+
end
|
946
|
+
|
947
|
+
# === 6.8.4.1 The if statement
|
948
|
+
class If < Stmt
|
949
|
+
attr_reader :condition, :then, :else
|
320
950
|
|
321
|
-
|
951
|
+
def initialize(condition_expr, then_stmt, else_stmt=nil, **rest)
|
952
|
+
@condition = Syntax::Expr.ensure(condition_expr)
|
953
|
+
@then = Syntax::Stmt::ensure(then_stmt)
|
954
|
+
@else = Syntax::Stmt::ensure(else_stmt) if else_stmt
|
955
|
+
|
956
|
+
super **rest
|
957
|
+
end
|
958
|
+
end
|
959
|
+
|
960
|
+
# === 6.8.4.2 Theswitchstatement
|
961
|
+
class Switch < Stmt
|
962
|
+
attr_reader :expr, :stmt
|
963
|
+
|
964
|
+
def initialize(expr, stmt, **rest)
|
965
|
+
@expr = Syntax::Expr.ensure(expr)
|
966
|
+
@stmt = Syntax::Stmt.ensure(stmt)
|
967
|
+
super **rest
|
968
|
+
end
|
969
|
+
end
|
970
|
+
|
971
|
+
class Case < Labeled
|
972
|
+
attr_reader :expr
|
973
|
+
|
974
|
+
def initialize(expr, stmt, **rest)
|
975
|
+
@expr = Syntax::Expr.ensure(expr)
|
976
|
+
super :case, stmt, **rest
|
977
|
+
end
|
978
|
+
end
|
979
|
+
|
980
|
+
# == 6.8.5 Iteration statements
|
981
|
+
class While < Stmt
|
982
|
+
attr_reader :condition, :body
|
983
|
+
|
984
|
+
def initialize(condition_expr, body_stmt, **rest)
|
985
|
+
@condition = Syntax::Expr.ensure(condition_expr)
|
986
|
+
@body = Syntax::Stmt::ensure(body_stmt)
|
987
|
+
|
988
|
+
super **rest
|
322
989
|
end
|
323
990
|
end
|
324
991
|
|
325
|
-
|
992
|
+
class DoWhile < Stmt
|
993
|
+
attr_reader :condition, :body
|
994
|
+
|
995
|
+
def initialize(condition_expr, body_stmt, **rest)
|
996
|
+
@condition = Syntax::Expr.ensure(condition_expr)
|
997
|
+
@body = Syntax::Stmt::ensure(body_stmt)
|
998
|
+
|
999
|
+
super **rest
|
1000
|
+
end
|
1001
|
+
end
|
1002
|
+
|
1003
|
+
class For < Stmt
|
1004
|
+
attr_reader :init, :condition, :loop, :body
|
1005
|
+
|
1006
|
+
def initialize(init_stmt=nil, condition_expr=nil, loop_expr=nil, body_stmt, **rest)
|
1007
|
+
@init = Syntax::BlockItem::ensure(init_stmt) if init_stmt
|
1008
|
+
@condition = Syntax::Expr.ensure(condition_expr) if condition_expr
|
1009
|
+
@loop = Syntax::Expr.ensure(loop_expr) if loop_expr
|
1010
|
+
@body = Syntax::Stmt::ensure(body_stmt)
|
1011
|
+
|
1012
|
+
super **rest
|
1013
|
+
end
|
1014
|
+
end
|
1015
|
+
|
1016
|
+
class Goto < Stmt
|
1017
|
+
attr_reader :label
|
1018
|
+
|
1019
|
+
def initialize(label, **rest)
|
1020
|
+
@label = Syntax::Ident.ensure(label)
|
1021
|
+
super **rest
|
1022
|
+
end
|
1023
|
+
end
|
1024
|
+
|
1025
|
+
class Continue < Stmt
|
1026
|
+
end
|
1027
|
+
|
1028
|
+
class Break < Stmt
|
1029
|
+
end
|
1030
|
+
|
1031
|
+
# === 6.8.6.4 The return statement
|
326
1032
|
class Return < Stmt
|
327
1033
|
attr_reader :expr
|
328
1034
|
|
@@ -333,53 +1039,51 @@ module Chelsy
|
|
333
1039
|
end
|
334
1040
|
end
|
335
1041
|
|
336
|
-
#
|
337
|
-
|
338
|
-
# == 6.9.1 Function definition
|
339
|
-
|
340
|
-
# Param-List ::
|
341
|
-
# [] |
|
342
|
-
# [:void] |
|
343
|
-
# [Param] |
|
344
|
-
# [Param, ..., :"..."]
|
345
|
-
class Param < Element
|
1042
|
+
# 6.7 Declarations
|
1043
|
+
class Declaration < Declarative
|
346
1044
|
attr_reader :name, :type
|
347
1045
|
|
348
|
-
def initialize(name, type,
|
1046
|
+
def initialize(name, type, init=nil, **rest)
|
349
1047
|
@name = Syntax::Ident.ensure(name)
|
350
1048
|
@type = Syntax::Type.ensure(type)
|
1049
|
+
@init = case init
|
1050
|
+
when nil
|
1051
|
+
nil
|
1052
|
+
when Enumerable
|
1053
|
+
InitializerList.new(init)
|
1054
|
+
else
|
1055
|
+
Syntax::Expr.ensure(init)
|
1056
|
+
end
|
351
1057
|
|
352
1058
|
super(**rest)
|
353
1059
|
end
|
354
|
-
end
|
355
1060
|
|
356
|
-
|
357
|
-
Param = Any.new('Parameter', [Param, :void, :"..."])
|
1061
|
+
def init; @init end
|
358
1062
|
end
|
359
1063
|
|
360
|
-
class
|
361
|
-
|
1064
|
+
class Typedef < Declarative
|
1065
|
+
attr_reader :name, :type
|
362
1066
|
|
363
|
-
def initialize(**rest)
|
364
|
-
@
|
1067
|
+
def initialize(name, type, **rest)
|
1068
|
+
@name = Syntax::Ident.ensure(name)
|
1069
|
+
@type = Syntax::Type.ensure(type)
|
1070
|
+
|
1071
|
+
rest[:storage] = :typedef
|
365
1072
|
super(**rest)
|
366
1073
|
end
|
367
|
-
|
368
|
-
private
|
369
|
-
def items; @params end
|
370
|
-
def validate_node(node); Syntax::Param.ensure(node) end
|
371
1074
|
end
|
372
1075
|
|
373
|
-
|
1076
|
+
# = 6.9 External definitions
|
1077
|
+
|
1078
|
+
# == 6.9.1 Function definition
|
1079
|
+
|
1080
|
+
class Function < Declarative
|
374
1081
|
attr_reader :name, :return_type, :params, :body
|
375
1082
|
|
376
1083
|
def initialize(name, return_type, params, inline: false, **rest, &block)
|
377
1084
|
@name = Syntax::Ident.ensure(name)
|
378
1085
|
@return_type = Syntax::Type.ensure(return_type)
|
379
|
-
|
380
|
-
@params = ParamList.new.tap do |list|
|
381
|
-
params.map {|p| list << p }
|
382
|
-
end
|
1086
|
+
@params = ParamList.new(params)
|
383
1087
|
|
384
1088
|
@body = Block.new
|
385
1089
|
block.call(@body)
|
@@ -399,13 +1103,140 @@ module Chelsy
|
|
399
1103
|
def initialize(location, system: false, **rest)
|
400
1104
|
@location = location.to_s.dup
|
401
1105
|
@system = !!system
|
1106
|
+
|
1107
|
+
super **rest
|
402
1108
|
end
|
403
1109
|
|
404
1110
|
# If `true`, this fragment forms `#include <...>`.
|
405
1111
|
# otherwise, this fragment forms `#include "..."`.
|
406
1112
|
def system?; @system end
|
407
1113
|
end
|
1114
|
+
|
1115
|
+
# `#define`
|
1116
|
+
#
|
1117
|
+
# - `params` - [symbol]
|
1118
|
+
# - `replacement` - string
|
1119
|
+
class Define < Base
|
1120
|
+
attr_reader :name, :params, :replacement
|
1121
|
+
|
1122
|
+
def initialize(name, params=nil, replacement, **rest)
|
1123
|
+
@name = Syntax::Ident.ensure(name)
|
1124
|
+
@params = IdentList.new(params) if params
|
1125
|
+
@replacement = Syntax::Raw.ensure(replacement)
|
1126
|
+
|
1127
|
+
super **rest
|
1128
|
+
end
|
1129
|
+
end
|
1130
|
+
|
1131
|
+
# `#undef`
|
1132
|
+
class Undef < Base
|
1133
|
+
attr_reader :name
|
1134
|
+
|
1135
|
+
def initialize(name, **rest)
|
1136
|
+
@name = Syntax::Ident.ensure(name)
|
1137
|
+
super **rest
|
1138
|
+
end
|
1139
|
+
end
|
1140
|
+
|
1141
|
+
# `#if`
|
1142
|
+
class If < Base
|
1143
|
+
attr_reader :condition
|
1144
|
+
|
1145
|
+
def initialize(condition_expr, **rest)
|
1146
|
+
@condition = Syntax::Expr.ensure(condition_expr)
|
1147
|
+
super **rest
|
1148
|
+
end
|
1149
|
+
end
|
1150
|
+
|
1151
|
+
# `#elif`
|
1152
|
+
class ElseIf < Base
|
1153
|
+
attr_reader :condition
|
1154
|
+
|
1155
|
+
def initialize(condition_expr, **rest)
|
1156
|
+
@condition = Syntax::Expr.ensure(condition_expr)
|
1157
|
+
super **rest
|
1158
|
+
end
|
1159
|
+
end
|
1160
|
+
|
1161
|
+
# `#else`
|
1162
|
+
class Else < Base
|
1163
|
+
end
|
1164
|
+
|
1165
|
+
# `#endif`
|
1166
|
+
class EndIf < Base
|
1167
|
+
end
|
1168
|
+
|
1169
|
+
# `#line`
|
1170
|
+
#
|
1171
|
+
# #line digits ["filename"]
|
1172
|
+
#
|
1173
|
+
class Line < Base
|
1174
|
+
attr_reader :lineno, :filename
|
1175
|
+
|
1176
|
+
def initialize(lineno, filename=nil, **rest)
|
1177
|
+
@lineno = Syntax::Int.ensure(lineno)
|
1178
|
+
@filename = Syntax::Raw.ensure(filename) if filename
|
1179
|
+
|
1180
|
+
super **rest
|
1181
|
+
end
|
1182
|
+
end
|
1183
|
+
|
1184
|
+
# `#pragma`
|
1185
|
+
class Pragma < Base
|
1186
|
+
attr_reader :pragma
|
1187
|
+
|
1188
|
+
def initialize(pragma, **rest)
|
1189
|
+
@pragma = Syntax::Raw.ensure(pragma)
|
1190
|
+
super **rest
|
1191
|
+
end
|
1192
|
+
end
|
1193
|
+
|
1194
|
+
# `STDC` pragma
|
1195
|
+
#
|
1196
|
+
# #pragma STDC FP_CONTRACT on-off-switch
|
1197
|
+
# #pragma STDC FENV_ACCESS on-off-switch
|
1198
|
+
# #pragma STDC CX_LIMITED_RANGE on-off-switch
|
1199
|
+
class StdcPragma < Pragma
|
1200
|
+
attr_reader :name, :state
|
1201
|
+
|
1202
|
+
def initialize(name, state, **rest)
|
1203
|
+
@name = Syntax::StdcPragma.ensure(name)
|
1204
|
+
@state = Syntax::StdcPragmaState.ensure(state)
|
1205
|
+
|
1206
|
+
super "STDC #{name} #{state}", **rest
|
1207
|
+
end
|
1208
|
+
end
|
1209
|
+
|
408
1210
|
end
|
409
1211
|
|
1212
|
+
end
|
410
1213
|
|
1214
|
+
module Chelsy
|
1215
|
+
module Syntax
|
1216
|
+
TopLevel = Any.new('TopLevel', [Declarative])
|
1217
|
+
Type = Any.new('TypeSpecifier', [Chelsy::Type::Base, :void])
|
1218
|
+
Raw = Any.new('Raw', [String])
|
1219
|
+
Int = Any.new('Int', [::Integer])
|
1220
|
+
Ident = Any.new('Identifier', [Symbol])
|
1221
|
+
Expr = Any.new('Expression', [Chelsy::Expr, Syntax::Ident])
|
1222
|
+
ExprOrType = Any.new('Expression-Or-Type', [Syntax::Expr, Syntax::Type])
|
1223
|
+
Fragment = Any.new('Fragment', [Fragment, String])
|
1224
|
+
Storage = Any.new('Storage-class specifiers', [:typedef, :extern, :static])
|
1225
|
+
Param = Any.new('Parameter', [Chelsy::Param, :void, :"..."])
|
1226
|
+
ProtoParam = Any.new('Prototype Parameter', [Syntax::Param, Symbol, Chelsy::Type::Base])
|
1227
|
+
ArraySize = Any.new('ArraySize', [Syntax::Expr])
|
1228
|
+
BitField = Any.new('BitField', [Chelsy::Constant::Integral])
|
1229
|
+
StructOrUnionMember = Any.new('StructOrUnionMember', [Chelsy::Declaration, Chelsy::BitField])
|
1230
|
+
EnumMember = Any.new('EnumMember', [Chelsy::EnumMember, Symbol])
|
1231
|
+
Initializer = Any.new('Initializer', [Syntax::Expr, Chelsy::Initializer, Chelsy::InitializerList])
|
1232
|
+
Stmt = Any.new('Statement', [
|
1233
|
+
Syntax::Expr, # Treats Expr as ExprStmt
|
1234
|
+
Chelsy::Stmt])
|
1235
|
+
BlockItem = Any.new('BlockItem', [
|
1236
|
+
Syntax::Stmt,
|
1237
|
+
Chelsy::Declarative])
|
1238
|
+
Declaration = Any.new('Declaration', [Chelsy::Declaration])
|
1239
|
+
StdcPragma = Any.new('STDC Pragma', [:FP_CONTRACT, :FENV_ACCESS, :CX_LIMITED_RANGE])
|
1240
|
+
StdcPragmaState = Any.new('STDC Pragma State', [:ON, :OFF, :DEFAULT])
|
1241
|
+
end
|
411
1242
|
end
|