rucc 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +55 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +5 -0
  5. data/Gemfile +6 -0
  6. data/Gemfile.lock +46 -0
  7. data/LICENCE +21 -0
  8. data/README.md +82 -0
  9. data/Rakefile +2 -0
  10. data/Vagrantfile +10 -0
  11. data/bin/console +10 -0
  12. data/bin/rspec +2 -0
  13. data/bin/setup +8 -0
  14. data/exe/rucc +7 -0
  15. data/include/8cc.h +48 -0
  16. data/include/float.h +44 -0
  17. data/include/iso646.h +20 -0
  18. data/include/rucc.h +2 -0
  19. data/include/stdalign.h +11 -0
  20. data/include/stdarg.h +52 -0
  21. data/include/stdbool.h +11 -0
  22. data/include/stddef.h +15 -0
  23. data/include/stdnoreturn.h +8 -0
  24. data/lib/rucc.rb +8 -0
  25. data/lib/rucc/case.rb +22 -0
  26. data/lib/rucc/decl.rb +9 -0
  27. data/lib/rucc/enc.rb +9 -0
  28. data/lib/rucc/engine.rb +138 -0
  29. data/lib/rucc/file_io.rb +108 -0
  30. data/lib/rucc/file_io_list.rb +56 -0
  31. data/lib/rucc/gen.rb +1602 -0
  32. data/lib/rucc/int_evaluator.rb +114 -0
  33. data/lib/rucc/k.rb +73 -0
  34. data/lib/rucc/keyword.rb +17 -0
  35. data/lib/rucc/kind.rb +43 -0
  36. data/lib/rucc/label_gen.rb +13 -0
  37. data/lib/rucc/lexer.rb +40 -0
  38. data/lib/rucc/lexer/impl.rb +683 -0
  39. data/lib/rucc/lexer/preprocessor.rb +888 -0
  40. data/lib/rucc/lexer/preprocessor/cond_incl.rb +27 -0
  41. data/lib/rucc/lexer/preprocessor/constructor.rb +54 -0
  42. data/lib/rucc/lexer/preprocessor/pragma.rb +31 -0
  43. data/lib/rucc/lexer/preprocessor/special_macro.rb +110 -0
  44. data/lib/rucc/libc.rb +47 -0
  45. data/lib/rucc/m.rb +7 -0
  46. data/lib/rucc/macro.rb +24 -0
  47. data/lib/rucc/node.rb +530 -0
  48. data/lib/rucc/node/conv.rb +33 -0
  49. data/lib/rucc/op.rb +61 -0
  50. data/lib/rucc/operator.rb +13 -0
  51. data/lib/rucc/option.rb +30 -0
  52. data/lib/rucc/parser.rb +961 -0
  53. data/lib/rucc/parser/break.rb +18 -0
  54. data/lib/rucc/parser/builtin.rb +25 -0
  55. data/lib/rucc/parser/continue.rb +18 -0
  56. data/lib/rucc/parser/do.rb +33 -0
  57. data/lib/rucc/parser/ensure.rb +39 -0
  58. data/lib/rucc/parser/enum.rb +64 -0
  59. data/lib/rucc/parser/expr.rb +493 -0
  60. data/lib/rucc/parser/for.rb +71 -0
  61. data/lib/rucc/parser/func.rb +274 -0
  62. data/lib/rucc/parser/func_call.rb +54 -0
  63. data/lib/rucc/parser/goto.rb +29 -0
  64. data/lib/rucc/parser/if.rb +23 -0
  65. data/lib/rucc/parser/initializer.rb +237 -0
  66. data/lib/rucc/parser/label.rb +31 -0
  67. data/lib/rucc/parser/return.rb +16 -0
  68. data/lib/rucc/parser/struct_and_union.rb +280 -0
  69. data/lib/rucc/parser/switch.rb +117 -0
  70. data/lib/rucc/parser/while.rb +29 -0
  71. data/lib/rucc/pos.rb +11 -0
  72. data/lib/rucc/rmap.rb +22 -0
  73. data/lib/rucc/s.rb +9 -0
  74. data/lib/rucc/static_label_gen.rb +15 -0
  75. data/lib/rucc/t.rb +18 -0
  76. data/lib/rucc/tempname_gen.rb +14 -0
  77. data/lib/rucc/token.rb +114 -0
  78. data/lib/rucc/token_gen.rb +68 -0
  79. data/lib/rucc/type.rb +304 -0
  80. data/lib/rucc/type/check.rb +39 -0
  81. data/lib/rucc/type/conv.rb +29 -0
  82. data/lib/rucc/type_info.rb +21 -0
  83. data/lib/rucc/utf.rb +126 -0
  84. data/lib/rucc/util.rb +111 -0
  85. data/lib/rucc/version.rb +3 -0
  86. data/rucc.gemspec +38 -0
  87. metadata +201 -0
@@ -0,0 +1,18 @@
1
+ module Rucc
2
+ class Parser
3
+ module Break
4
+
5
+ private
6
+
7
+ # @param [Token] tok
8
+ # @return [Node]
9
+ def read_break_stmt(tok)
10
+ expect!(';')
11
+ if !@lbreak
12
+ Util.errort!(tok, "stray break statement")
13
+ end
14
+ Node.ast_jump(@lbreak)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,25 @@
1
+ module Rucc
2
+ class Parser
3
+ module Builtin
4
+
5
+ private
6
+
7
+ def define_builtin_functions!
8
+ voidptr = [Type.make_ptr_type(Type::VOID)]
9
+ two_voidptrs = [Type.make_ptr_type(Type::VOID), Type.make_ptr_type(Type::VOID)]
10
+
11
+ define_builtin! "__builtin_return_address", Type.make_ptr_type(Type::VOID), voidptr
12
+ define_builtin! "__builtin_reg_class", Type::INT, voidptr
13
+ define_builtin! "__builtin_va_arg", Type::VOID, two_voidptrs
14
+ define_builtin! "__builtin_va_start", Type::VOID, voidptr
15
+ end
16
+
17
+ # @param [String] name
18
+ # @param [Type] rettype
19
+ # @param [<Type>] paramtypes
20
+ def define_builtin!(name, rettype, paramtypes)
21
+ Node.ast_gvar(Type.make_func_type(rettype, paramtypes, true, false), name, @globalenv)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,18 @@
1
+ module Rucc
2
+ class Parser
3
+ module Continue
4
+
5
+ private
6
+
7
+ # @param [Token] tok
8
+ # @return [Node]
9
+ def read_continue_stmt(tok)
10
+ expect!(';')
11
+ if (!@lcontinue)
12
+ Util.errort!(tok, "stray continue statement")
13
+ end
14
+ Node.ast_jump(@lcontinue)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,33 @@
1
+ module Rucc
2
+ class Parser
3
+ module Do
4
+
5
+ private
6
+
7
+ # @return [Node]
8
+ def read_do_stmt
9
+ b = @label_gen.next
10
+ e = @label_gen.next
11
+ body = nil
12
+ with_jump_labels(b, e) { body = read_stmt }
13
+ tok = get
14
+ if !Token.is_keyword?(tok, K::WHILE)
15
+ Util.errort!(tok, "'while' is expected, but got #{tok}")
16
+ end
17
+ expect!('(')
18
+ cond = read_boolean_expr
19
+ expect!(')')
20
+ expect!(';')
21
+
22
+ v = []
23
+ v.push(Node.ast_dest(b))
24
+ if body
25
+ v.push(body)
26
+ end
27
+ v.push(Node.ast_if(cond, Node.ast_jump(b), nil))
28
+ v.push(Node.ast_dest(e))
29
+ Node.ast_compound_stmt(v)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,39 @@
1
+ module Rucc
2
+ class Parser
3
+ module Ensure
4
+
5
+ private
6
+
7
+ def ensure_not_void!(ty)
8
+ if ty.kind == Kind::VOID
9
+ raise "void is not allowed"
10
+ end
11
+ end
12
+
13
+ # @param [Node] node
14
+ def ensure_lvalue!(node)
15
+ case node.kind
16
+ when AST::LVAR, AST::GVAR, AST::DEREF, AST::STRUCT_REF
17
+ return
18
+ else
19
+ raise "lvalue expected, but got #{node}"
20
+ end
21
+ end
22
+
23
+ def ensure_arithtype!(node)
24
+ if !Type.is_arithtype(node.ty)
25
+ raise "arithmetic type expected, but got #{node}"
26
+ # error("arithmetic type expected, but got %s", node2s(node));
27
+ end
28
+ end
29
+
30
+ # @param [Node] node
31
+ def ensure_inttype!(node)
32
+ if !Type.is_inttype(node.ty)
33
+ raise "integer type expected, but got #{node}"
34
+ # error("integer type expected, but got %s", node2s(node));
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,64 @@
1
+ module Rucc
2
+ class Parser
3
+ module Enum
4
+ # @return [Type]
5
+ def read_enum_def
6
+ tag = nil
7
+ tok = get
8
+
9
+ # Enum is handled as a synonym for int. We only check if the enum
10
+ # is declared.
11
+ if tok.kind == T::IDENT
12
+ tag = tok.sval
13
+ tok = get
14
+ end
15
+ if tag
16
+ ty = @tags[tag]
17
+ if ty && ty.kind != Kind::ENUM
18
+ Util.errort!(tok, "declarations of #{tag} does not match")
19
+ end
20
+ end
21
+ if !Token.is_keyword?(tok, '{')
22
+ if !tag || !@tags[tag]
23
+ Util.errort!(tok, "enum tag #{tag} is not defined")
24
+ end
25
+ @lexer.unget_token(tok)
26
+ return Type::INT
27
+ end
28
+
29
+ # NOTE: read enum declaration
30
+ if tag
31
+ @tags[tag] = Type::ENUM
32
+ end
33
+
34
+ val = 0
35
+ while true
36
+ tok = get
37
+ if Token.is_keyword?(tok, '}')
38
+ break
39
+ end
40
+ if tok.kind != T::IDENT
41
+ Util.errort!(tok, "identifier expected, but got #{tok}")
42
+ end
43
+ name = tok.sval
44
+
45
+ if next_token?('=')
46
+ val = read_intexpr
47
+ end
48
+ constval = Node.ast_inttype(Type::INT, val)
49
+ val += 1
50
+ env[name] = constval
51
+ if next_token?(',')
52
+ next
53
+ end
54
+ if next_token?('}')
55
+ break
56
+ end
57
+ Util.errort!(peek(), "',' or '}' expected, but got #{peek}")
58
+ end
59
+
60
+ Type::INT
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,493 @@
1
+ module Rucc
2
+ class Parser
3
+ module Expr
4
+
5
+ # @return [Node]
6
+ def read_expr
7
+ tok = peek
8
+ r = read_comma_expr
9
+ if r.nil?
10
+ Util.errort!(tok, "expression expected")
11
+ end
12
+ r
13
+ end
14
+
15
+ private
16
+
17
+ # @return [Node]
18
+ def read_expr_opt
19
+ read_comma_expr
20
+ end
21
+
22
+ # @return [Node]
23
+ def read_comma_expr
24
+ node = read_assignment_expr
25
+ while next_token?(',')
26
+ expr = read_assignment_expr
27
+ node = Node.ast_binop(expr.ty, ',', node, expr)
28
+ end
29
+ node
30
+ end
31
+
32
+ def read_assignment_expr
33
+ node = read_logor_expr
34
+ tok = get
35
+ return node if tok.nil?
36
+
37
+ if Token.is_keyword?(tok, '?')
38
+ return do_read_conditional_expr(node)
39
+ end
40
+ cop = get_compound_assign_op(tok)
41
+ if Token.is_keyword?(tok, '=') || !cop.nil?
42
+ value = Node.conv(read_assignment_expr)
43
+ if Token.is_keyword?(tok, '=') || !cop.nil?
44
+ ensure_lvalue!(node)
45
+ end
46
+ right = !cop.nil? ? Node.binop(cop, Node.conv(node), value) : value
47
+ if Type.is_arithtype(node.ty) && node.ty.kind != right.ty.kind
48
+ right = Node.ast_conv(node.ty, right)
49
+ end
50
+ return Node.ast_binop(node.ty, '=', node, right)
51
+ end
52
+ @lexer.unget_token(tok)
53
+ node
54
+ end
55
+
56
+ # @return [Node]
57
+ def read_conditional_expr
58
+ cond = read_logor_expr
59
+ if !next_token?('?')
60
+ return cond
61
+ end
62
+ do_read_conditional_expr(cond)
63
+ end
64
+
65
+ # @param [Node] cond
66
+ # @return [Node]
67
+ def do_read_conditional_expr(cond)
68
+ thn = Node.conv(read_comma_expr)
69
+ expect!(':')
70
+ els = Node.conv(read_conditional_expr)
71
+ # [GNU] Omitting the middle operand is allowed.
72
+ t = thn ? thn.ty : cond.ty
73
+ u = els.ty
74
+ # C11 6.5.15p5: if both types are arithemtic type, the result
75
+ # type is the result of the usual arithmetic conversions.
76
+ if Type.is_arithtype(t) && Type.is_arithtype(u)
77
+ r = Type.usual_arith_conv(t, u)
78
+ Node.ast_ternary(r, cond, (thn ? Node.wrap(r, thn) : nil), Node.wrap(r, els))
79
+ end
80
+ Node.ast_ternary(u, cond, thn, els)
81
+ end
82
+
83
+ # @return [Node]
84
+ def read_logor_expr
85
+ node = read_logand_expr
86
+ while next_token?(OP::LOGOR)
87
+ node = Node.ast_binop(Type::INT, OP::LOGOR, node, read_logand_expr)
88
+ end
89
+ node
90
+ end
91
+
92
+ # @return [Node]
93
+ def read_logand_expr
94
+ node = read_bitor_expr
95
+ while next_token?(OP::LOGAND)
96
+ node = Node.ast_binop(Type::INT, OP::LOGAND, node, read_bitor_expr)
97
+ end
98
+ node
99
+ end
100
+
101
+ # @return [Node]
102
+ def read_bitor_expr
103
+ node = read_bitxor_expr
104
+ while next_token?('|')
105
+ node = Node.binop('|', Node.conv(node), Node.conv(read_bitxor_expr))
106
+ end
107
+ node
108
+ end
109
+
110
+ # @return [Node]
111
+ def read_bitxor_expr
112
+ node = read_bitand_expr
113
+ while next_token?('^')
114
+ node = Node.binop('^', Node.conv(node), Node.conv(read_bitand_expr))
115
+ end
116
+ node
117
+ end
118
+
119
+ # @return [Node]
120
+ def read_bitand_expr
121
+ node = read_equality_expr
122
+ while next_token?('&')
123
+ node = Node.binop('&', Node.conv(node), Node.conv(read_equality_expr))
124
+ end
125
+ node
126
+ end
127
+
128
+ # @return [Node]
129
+ def read_equality_expr
130
+ node = read_relational_expr
131
+ r = nil
132
+ if next_token?(OP::EQ)
133
+ r = Node.binop(OP::EQ, Node.conv(node), Node.conv(read_equality_expr))
134
+ elsif next_token?(OP::NE)
135
+ r = Node.binop(OP::NE, Node.conv(node), Node.conv(read_equality_expr))
136
+ else
137
+ return node
138
+ end
139
+ r.ty = Type::INT
140
+ r
141
+ end
142
+
143
+ # @return [Node]
144
+ def read_relational_expr
145
+ node = read_shift_expr
146
+ while true
147
+ if next_token?('<')
148
+ node = Node.binop('<', Node.conv(node), Node.conv(read_shift_expr))
149
+ elsif next_token?('>')
150
+ node = Node.binop('<', Node.conv(read_shift_expr), Node.conv(node))
151
+ elsif next_token?(OP::LE)
152
+ node = Node.binop(OP::LE, Node.conv(node), Node.conv(read_shift_expr))
153
+ elsif next_token?(OP::GE)
154
+ node = Node.binop(OP::LE, Node.conv(read_shift_expr), Node.conv(node))
155
+ else
156
+ return node
157
+ end
158
+ node.ty = Type::INT
159
+ end
160
+ raise "Must not reach here"
161
+ end
162
+
163
+ # @return [Node]
164
+ def read_shift_expr
165
+ node = read_additive_expr
166
+ while true
167
+ op = nil
168
+ if next_token?(OP::SAL)
169
+ op = OP::SAL
170
+ elsif next_token?(OP::SAR)
171
+ op = node.ty.usig ? OP::SHR : OP::SAR
172
+ else
173
+ break
174
+ end
175
+ right = read_additive_expr
176
+ ensure_inttype!(node)
177
+ ensure_inttype!(right)
178
+ node = Node.ast_binop(node.ty, op, Node.conv(node), Node.conv(right))
179
+ end
180
+ node
181
+ end
182
+
183
+ # @return [Node]
184
+ def read_additive_expr
185
+ node = read_multiplicative_expr
186
+ while true
187
+ if next_token?('+')
188
+ node = Node.binop('+', Node.conv(node), Node.conv(read_multiplicative_expr))
189
+ elsif next_token?('-')
190
+ node = Node.binop('-', Node.conv(node), Node.conv(read_multiplicative_expr))
191
+ else
192
+ return node
193
+ end
194
+ end
195
+ raise "Must not reach here!"
196
+ end
197
+
198
+ # @return [Node]
199
+ def read_multiplicative_expr
200
+ node = read_cast_expr
201
+ while true
202
+ if next_token?('*')
203
+ node = Node.binop('*', Node.conv(node), Node.conv(read_cast_expr))
204
+ elsif next_token?('/')
205
+ node = Node.binop('/', Node.conv(node), Node.conv(read_cast_expr))
206
+ elsif next_token?('%')
207
+ node = Node.binop('%', Node.conv(node), Node.conv(read_cast_expr))
208
+ else
209
+ return node
210
+ end
211
+ end
212
+ raise "Must not reach here!"
213
+ end
214
+
215
+ # @return [Node]
216
+ def read_cast_expr
217
+ tok = get
218
+ if Token.is_keyword?(tok, '(') && is_type?(peek)
219
+ ty = read_cast_type
220
+ expect!(')')
221
+ if Token.is_keyword?(peek, '{')
222
+ node = read_compound_literal(ty)
223
+ return read_postfix_expr_tail(node)
224
+ end
225
+ return Node.ast_uop(OP::CAST, ty, read_cast_expr)
226
+ end
227
+ @lexer.unget_token(tok)
228
+ read_unary_expr
229
+ end
230
+
231
+ # @return [Type]
232
+ def read_cast_type
233
+ ty, _ = read_decl_spec
234
+ read_abstract_declarator(ty)
235
+ end
236
+
237
+ # C11 6.7.7: Type names
238
+ # read_abstract_declarator reads a type name.
239
+ # A type name is a declaration that omits the identifier.
240
+ # A few examples are int* (pointer to int), int() (function returning int),
241
+ # int*() (function returning pointer to int),
242
+ # or int(*)() (pointer to funct$an returning int). Used for casting.
243
+ #
244
+ # @param [Type] basety
245
+ # @return [Type]
246
+ def read_abstract_declarator(basety)
247
+ read_declarator("", basety, [], DECL::CAST)
248
+ end
249
+
250
+ # @return [Node]
251
+ def read_unary_expr
252
+ tok = get
253
+ if tok.kind == T::KEYWORD
254
+ case tok.id
255
+ when K::SIZEOF then return read_sizeof_operand
256
+ when K::ALIGNOF then return read_alignof_operand
257
+ when OP::INC then return read_unary_incdec(OP::PRE_INC)
258
+ when OP::DEC then return read_unary_incdec(OP::PRE_DEC)
259
+ when OP::LOGAND then return read_label_addr(tok)
260
+ when '&' then return read_unary_addr
261
+ when '*' then return read_unary_deref(tok)
262
+ when '+' then return read_cast_expr
263
+ when '-' then return read_unary_minus
264
+ when '~' then return read_unary_bitnot(tok)
265
+ when '!' then return read_unary_lognot
266
+ end
267
+ end
268
+ @lexer.unget_token(tok)
269
+ read_postfix_expr
270
+ end
271
+
272
+ # @return [Node]
273
+ def read_unary_minus
274
+ expr = read_cast_expr
275
+ ensure_arithtype!(expr)
276
+ if Type.is_inttype(expr.ty)
277
+ return Node.binop('-', Node.conv(Node.ast_inttype(expr.ty, 0)), Node.conv(expr))
278
+ end
279
+ Node.binop('-', Node.ast_floattype(expr.ty, 0), expr)
280
+ end
281
+
282
+ # @param [Token] tok
283
+ # @return [Node]
284
+ def read_unary_bitnot(tok)
285
+ operand = read_cast_expr
286
+ operand = Node.conv(operand)
287
+ if !Type.is_inttype(operand.ty)
288
+ Util.errort!(tok, "invalid use of ~: #{expr}")
289
+ end
290
+ Node.ast_uop('~', operand.ty, operand)
291
+ end
292
+
293
+ # @return [Node]
294
+ def read_unary_lognot
295
+ operand = read_cast_expr
296
+ operand = Node.conv(operand)
297
+ Node.ast_uop('!', Type::INT, operand)
298
+ end
299
+
300
+ # @return [Node]
301
+ def read_postfix_expr
302
+ node = read_primary_expr
303
+ read_postfix_expr_tail(node)
304
+ end
305
+
306
+ # @param [Node] node
307
+ # @return [Node]
308
+ def read_postfix_expr_tail(node)
309
+ return nil if node.nil?
310
+
311
+ while true
312
+ if next_token?('(')
313
+ tok = peek
314
+ node = Node.conv(node)
315
+ t = node.ty
316
+ if (t.kind != Kind::PTR) || (t.ptr.kind != Kind::FUNC)
317
+ Util.errort!(tok, "function expected, but got #{node}")
318
+ end
319
+ node = read_funcall(node)
320
+ next
321
+ end
322
+
323
+ if next_token?('[')
324
+ node = read_subscript_expr(node)
325
+ next
326
+ end
327
+
328
+ if next_token?('.')
329
+ node = read_struct_field(node)
330
+ next
331
+ end
332
+
333
+ if next_token?(OP::ARROW)
334
+ if (node.ty.kind != Kind::PTR)
335
+ raise "pointer type expected, but got #{node.ty} #{node}"
336
+ end
337
+ node = Node.ast_uop(AST::DEREF, node.ty.ptr, node)
338
+ node = read_struct_field(node)
339
+ next
340
+ end
341
+
342
+ tok = peek
343
+ if next_token?(OP::INC) || next_token?(OP::DEC)
344
+ ensure_lvalue!(node)
345
+ op = Token.is_keyword?(tok, OP::INC) ? OP::POST_INC : OP::POST_DEC
346
+ return Node.ast_uop(op, node.ty, node)
347
+ end
348
+
349
+ return node
350
+ end
351
+ raise "Must not reach here!"
352
+ end
353
+
354
+ # @param [Node] node
355
+ # @return [Node]
356
+ def read_subscript_expr(node)
357
+ tok = peek
358
+ sub = read_expr
359
+ if !sub
360
+ Util.errort!(tok, "subscription expected")
361
+ end
362
+ expect!(']')
363
+ t = Node.binop('+', Node.conv(node), Node.conv(sub))
364
+ Node.ast_uop(AST::DEREF, t.ty.ptr, t)
365
+ end
366
+
367
+ # @return [Node]
368
+ def read_primary_expr
369
+ tok = get
370
+ return nil if tok.nil?
371
+
372
+ if Token.is_keyword?(tok, '(')
373
+ if next_token?('{')
374
+ return read_stmt_expr
375
+ end
376
+ r = read_expr
377
+ expect!(')')
378
+ return r
379
+ end
380
+
381
+ if Token.is_keyword?(tok, K::GENERIC)
382
+ return read_generic
383
+ end
384
+
385
+ case tok.kind
386
+ when T::IDENT
387
+ return read_var_or_func(tok.sval)
388
+ when T::NUMBER
389
+ return read_number(tok)
390
+ when T::CHAR
391
+ return Node.ast_inttype(Type.char_type(tok.enc), tok.c)
392
+ when T::STRING
393
+ return Node.ast_string(tok.enc, tok.sval)
394
+ when T::KEYWORD
395
+ @lexer.unget_token(tok)
396
+ return nil
397
+ else
398
+ raise "internal error: unknown token kind: #{tok.kind}"
399
+ end
400
+ end
401
+
402
+ # @return [Node]
403
+ def read_stmt_expr
404
+ r = read_compound_stmt
405
+ expect!(')')
406
+ rtype = Type::VOID
407
+ if r.stmts.size > 0
408
+ lastexpr = r.stmts.last
409
+ if lastexpr.ty
410
+ rtype = lastexpr.ty
411
+ end
412
+ end
413
+ r.ty = rtype
414
+ r
415
+ end
416
+
417
+ # @param [Token] tok
418
+ # @return [Node]
419
+ def read_label_addr(tok)
420
+ # [GNU] Labels as values. You can get the address of the a label
421
+ # with unary "&&" operator followed by a label name.
422
+ tok2 = get
423
+ if tok2.kind != T::IDENT
424
+ Util.errort!(tok, "label name expected after &&, but got #{tok2}")
425
+ end
426
+ r = Node.ast_label_addr(tok2.sval)
427
+ @gotos.push(r)
428
+ r
429
+ end
430
+
431
+ # @return [Node]
432
+ def read_unary_addr
433
+ operand = read_cast_expr
434
+ if operand.kind == AST::FUNCDESG
435
+ return Node.conv(operand)
436
+ end
437
+ ensure_lvalue!(operand)
438
+ Node.ast_uop(AST::ADDR, Type.make_ptr_type(operand.ty), operand)
439
+ end
440
+
441
+ # @param [Token] tok
442
+ # @return [Node]
443
+ def read_unary_deref(tok)
444
+ operand = Node.conv(read_cast_expr)
445
+ if operand.ty.kind != Kind::PTR
446
+ Util.errort!(tok, "pointer type expected, but got #{operand}")
447
+ end
448
+ if operand.ty.ptr.kind == Kind::FUNC
449
+ return operand
450
+ end
451
+ Node.ast_uop(AST::DEREF, operand.ty.ptr, operand)
452
+ end
453
+ end
454
+
455
+ # @return [Node]
456
+ def read_sizeof_operand
457
+ ty = read_sizeof_operand_sub
458
+ # Sizeof on void or function type is GNU extension
459
+ size = (ty.kind == Kind::VOID || ty.kind == Kind::FUNC) ? 1 : ty.size
460
+ Util.assert!{ 0 <= size }
461
+ Node.ast_inttype(Type::ULONG, size)
462
+ end
463
+
464
+ # @reutrn [Type]
465
+ def read_sizeof_operand_sub
466
+ tok = get
467
+ if Token.is_keyword?(tok, '(') && is_type?(peek)
468
+ r = read_cast_type
469
+ expect!(')')
470
+ return r
471
+ end
472
+ @lexer.unget_token(tok)
473
+ read_unary_expr.ty
474
+ end
475
+
476
+ # @return [Node]
477
+ def read_alignof_operand
478
+ expect!('(')
479
+ ty = read_cast_type
480
+ expect!(')')
481
+ Node.ast_inttype(Type::ULONG, ty.align)
482
+ end
483
+
484
+ # @param [OP] op
485
+ # @return [Node]
486
+ def read_unary_incdec(op)
487
+ operand = read_unary_expr
488
+ operand = Node.conv(operand)
489
+ ensure_lvalue!(operand)
490
+ Node.ast_uop(op, operand.ty, operand)
491
+ end
492
+ end
493
+ end