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.
- checksums.yaml +7 -0
- data/.gitignore +55 -0
- data/.rspec +1 -0
- data/.travis.yml +5 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +46 -0
- data/LICENCE +21 -0
- data/README.md +82 -0
- data/Rakefile +2 -0
- data/Vagrantfile +10 -0
- data/bin/console +10 -0
- data/bin/rspec +2 -0
- data/bin/setup +8 -0
- data/exe/rucc +7 -0
- data/include/8cc.h +48 -0
- data/include/float.h +44 -0
- data/include/iso646.h +20 -0
- data/include/rucc.h +2 -0
- data/include/stdalign.h +11 -0
- data/include/stdarg.h +52 -0
- data/include/stdbool.h +11 -0
- data/include/stddef.h +15 -0
- data/include/stdnoreturn.h +8 -0
- data/lib/rucc.rb +8 -0
- data/lib/rucc/case.rb +22 -0
- data/lib/rucc/decl.rb +9 -0
- data/lib/rucc/enc.rb +9 -0
- data/lib/rucc/engine.rb +138 -0
- data/lib/rucc/file_io.rb +108 -0
- data/lib/rucc/file_io_list.rb +56 -0
- data/lib/rucc/gen.rb +1602 -0
- data/lib/rucc/int_evaluator.rb +114 -0
- data/lib/rucc/k.rb +73 -0
- data/lib/rucc/keyword.rb +17 -0
- data/lib/rucc/kind.rb +43 -0
- data/lib/rucc/label_gen.rb +13 -0
- data/lib/rucc/lexer.rb +40 -0
- data/lib/rucc/lexer/impl.rb +683 -0
- data/lib/rucc/lexer/preprocessor.rb +888 -0
- data/lib/rucc/lexer/preprocessor/cond_incl.rb +27 -0
- data/lib/rucc/lexer/preprocessor/constructor.rb +54 -0
- data/lib/rucc/lexer/preprocessor/pragma.rb +31 -0
- data/lib/rucc/lexer/preprocessor/special_macro.rb +110 -0
- data/lib/rucc/libc.rb +47 -0
- data/lib/rucc/m.rb +7 -0
- data/lib/rucc/macro.rb +24 -0
- data/lib/rucc/node.rb +530 -0
- data/lib/rucc/node/conv.rb +33 -0
- data/lib/rucc/op.rb +61 -0
- data/lib/rucc/operator.rb +13 -0
- data/lib/rucc/option.rb +30 -0
- data/lib/rucc/parser.rb +961 -0
- data/lib/rucc/parser/break.rb +18 -0
- data/lib/rucc/parser/builtin.rb +25 -0
- data/lib/rucc/parser/continue.rb +18 -0
- data/lib/rucc/parser/do.rb +33 -0
- data/lib/rucc/parser/ensure.rb +39 -0
- data/lib/rucc/parser/enum.rb +64 -0
- data/lib/rucc/parser/expr.rb +493 -0
- data/lib/rucc/parser/for.rb +71 -0
- data/lib/rucc/parser/func.rb +274 -0
- data/lib/rucc/parser/func_call.rb +54 -0
- data/lib/rucc/parser/goto.rb +29 -0
- data/lib/rucc/parser/if.rb +23 -0
- data/lib/rucc/parser/initializer.rb +237 -0
- data/lib/rucc/parser/label.rb +31 -0
- data/lib/rucc/parser/return.rb +16 -0
- data/lib/rucc/parser/struct_and_union.rb +280 -0
- data/lib/rucc/parser/switch.rb +117 -0
- data/lib/rucc/parser/while.rb +29 -0
- data/lib/rucc/pos.rb +11 -0
- data/lib/rucc/rmap.rb +22 -0
- data/lib/rucc/s.rb +9 -0
- data/lib/rucc/static_label_gen.rb +15 -0
- data/lib/rucc/t.rb +18 -0
- data/lib/rucc/tempname_gen.rb +14 -0
- data/lib/rucc/token.rb +114 -0
- data/lib/rucc/token_gen.rb +68 -0
- data/lib/rucc/type.rb +304 -0
- data/lib/rucc/type/check.rb +39 -0
- data/lib/rucc/type/conv.rb +29 -0
- data/lib/rucc/type_info.rb +21 -0
- data/lib/rucc/utf.rb +126 -0
- data/lib/rucc/util.rb +111 -0
- data/lib/rucc/version.rb +3 -0
- data/rucc.gemspec +38 -0
- 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
|