-
Notifications
You must be signed in to change notification settings - Fork 0
/
minicc.c
111 lines (94 loc) · 2.45 KB
/
minicc.c
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
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// トークンの型を表す値
enum {
TK_NUM = 256, // 整数トークン
TK_EOF, // 入力の終わりを表すトークン
};
// トークンの型
typedef struct {
int ty; // トークンの型
int val; // tyがTK_NUMの場合、その数値
char *input; // トークン文字列(エラーメッセージ用)
} Token;
// トークナイズした結果のトークン列はこの配列に保存する
// 100個以上のトークンは来ないものとする
Token tokens[100];
// pが指している文字列をトークンに分割してtokensに保存する
void tokenize(char *p) {
int i = 0;
while (*p) {
// 空白文字をスキップ
if (isspace(*p)) {
p++;
continue;
}
if (*p == '+' || *p == '-') {
tokens[i].ty = *p;
tokens[i].input = p;
i++;
p++;
continue;
}
if (isdigit(*p)) {
tokens[i].ty = TK_NUM;
tokens[i].input = p;
tokens[i].val = strtol(p, &p, 10);
i++;
continue;
}
fprintf(stderr, "トークナイズできません: %s\n", p);
exit(1);
}
tokens[i].ty = TK_EOF;
tokens[i].input = p;
}
// エラーを報告するための関数
void error(int i) {
fprintf(stderr, "予期しないトークンです: %s\n",
tokens[i].input);
exit(1);
}
int main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "引数の個数が正しくありません\n");
return 1;
}
// トークナイズする
tokenize(argv[1]);
// アセンブリの前半部分を出力
printf(".intel_syntax noprefix\n");
printf(".global main\n");
printf("main:\n");
// 式の最初は数でなければならないので、それをチェックして
// 最初のmov命令を出力
if (tokens[0].ty != TK_NUM)
error(0);
printf(" mov rax, %d\n", tokens[0].val);
// `+ <数>`あるいは`- <数>`というトークンの並びを消費しつつ
// アセンブリを出力
int i = 1;
while (tokens[i].ty != TK_EOF) {
if (tokens[i].ty == '+') {
i++;
if (tokens[i].ty != TK_NUM)
error(i);
printf(" add rax, %d\n", tokens[i].val);
i++;
continue;
}
if (tokens[i].ty == '-') {
i++;
if (tokens[i].ty != TK_NUM)
error(i);
printf(" sub rax, %d\n", tokens[i].val);
i++;
continue;
}
error(i);
}
printf(" ret\n");
return 0;
}