-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path9cc.h
240 lines (205 loc) · 5.3 KB
/
9cc.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
#define _GNU_SOURCE
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Type Type;
/* tokenize.c */
// NOTE: enum は定数を一括で宣言できる型
typedef enum
{
TK_RESERVED, // 記号
TK_IDENT, // 識別子
TK_STR, // 文字リテラル
TK_NUM, // 整数トークン
TK_EOF // 入力の終わりを表すトークン
} TokenKind;
/*
NOTE: typedef で struct Token を通常の名前空間で変数宣言できるようにする
struct Token { ... };
struct Token token; => OK
Token token; => Error
typedef struct Token token_t;
token_t token; => OK
*/
typedef struct Token Token;
struct Token
{
TokenKind kind; // トークンの型
Token *next; // 次の入力トークン
int val; // kindがTK_NUMの場合、その数値
char *str; // トークン文字列
int len; // トークンの長さ ※ 数値の長さではない
char *contents; // 文字リテラル
char cont_len; // 文字リテラルの長さ
};
Token *token;
void error(char *fmt, ...);
void error_at(char *loc, char *fmt, ...);
void error_tok(Token *tok, char *fmt, ...);
Token *new_token(TokenKind kind, Token *cur, char *str, int len);
bool start_with(char *lhs, char *rhs);
bool is_alpha(char c);
Token *tokenize();
/* parse.c */
typedef enum
{
ND_ASSIGN, // =
ND_EQ, // ==
ND_NE, // !=
ND_LE, // <=
ND_LT, // <
ND_ADD, // num + num
ND_PTR_ADD, // ptr + num || num + ptr
ND_SUB, // num - num
ND_PTR_SUB, // ptr - num || num - ptr
ND_PTR_DIFF, // ptr - ptr
ND_MUL, // *
ND_DIV, // /
ND_ADDR, // unary &
ND_DEREF, // unary *
ND_VAR, // 変数
ND_NUM, // Integer
ND_RETURN, // return keyword
ND_IF, // if keyword
ND_WHILE, // while keyword
ND_FOR, // for keyword
ND_BLOCK, // block
ND_NULL, // empty statement
ND_FUNCALL, // function call
ND_EXPR_STMT, // expression statement
ND_STMT_EXPR // expression statement
} NodeKind;
typedef struct Var Var;
struct Var
{
char *name;
Type *ty;
int len;
bool is_local; // local or global
// local variable
int offset; // offset from RBP
// global variable
char *contents;
int cont_len;
};
typedef struct VarList VarList;
struct VarList
{
VarList *next;
Var *var;
};
typedef struct Node Node;
struct Node
{
NodeKind kind;
Node *lhs;
Node *rhs;
// for "while", "if", "for"
Node *init;
Node *cond;
Node *then;
Node *els;
Node *inc;
Node *body; // statements in block or statement expression
Node *next; // next node
Type *ty; // Type, e.g. int, pointer to int
Token *tok;
// function call
char *funcname;
Node *args;
int val; // ND_NUMの時のみ使う
Var *var; // ND_VARの時のみ使い、変数に関する情報を格納する
};
Token *peek(char *op);
Token *consume(char *op);
Token *consume_ident(void);
void expect(char *op);
int expect_number(void);
char *expect_ident(void);
bool at_eof(void);
Node *new_node(NodeKind kind, Token *tok);
Node *new_binary(NodeKind kind, Node *lhs, Node *rhs, Token *tok);
Node *new_unary(NodeKind kind, Node *lhs, Token *tok);
Node *new_node_num(int val, Token *tok);
Node *new_node_var(Var *lvar, Token *tok);
Var *new_var(char *name, Type *ty, bool is_local);
Var *find_var(Token *tok);
// NODE: 四則演算, 比較表現, 変数は以下で表現される。これをC関数に落とし込む。
// program = stmt*
// stmt = expr ";"
// | return expr ";"
// | "if" "(" expr ")" stmt ("else" stmt)?
// | "while" "(" expr ")" stmt
// | "for" "(" expr? ";" expr? ";" expr? ")" stmt
// | "{" stmt* "}"
// expr = assign
// assign = equality ("=" assign)?
// equality = relational ("==" relational | "!=" relational)*
// relational = add ("<" add | "<=" add | ">" add | ">=" add)*
// add = mul ("+" mul | "-" mul)*
// mul = unary ("*" unary | "/" unary)*
// unary = ("+" | "-" | "*" | "&")? unary
// primary = num | ident args? | "(" expr ")" | "sizeof" unary
// args = "(" ")"
typedef struct Function Function;
struct Function
{
Function *next;
char *name;
VarList *params;
Node *node;
VarList *locals;
int stack_size;
};
typedef struct
{
VarList *globals;
Function *fns;
} Program;
Program *program(void);
void codegen(Program *prog);
Function *function(void);
Node *declaration(void);
Node *stmt(void);
Node *stmt2(void);
Node *expr(void);
Node *assign(void);
Node *equality(void);
Node *relational(void);
Node *add(void);
Node *mul(void);
Node *unary(void);
Node *postfix(void);
Node *primary(void);
/* type.c */
typedef enum
{
TY_CHAR,
TY_INT,
TY_PTR,
TY_ARRAY
} TypeKind;
struct Type
{
TypeKind kind;
size_t size;
Type *base;
size_t array_len;
};
extern Type *char_type;
extern Type *int_type;
bool is_integer(Type *ty);
Type *pointer_to(Type *base);
Type *array_of(Type *base, size_t size);
void add_type(Node *node);
/* codegen.c */
void gen(Node *node);
/* main.c */
char *filename;
char *user_input;
int main(int argc, char **argv);