rucc 0.1.0

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