-
Notifications
You must be signed in to change notification settings - Fork 0
/
004-main.c
136 lines (122 loc) · 3.17 KB
/
004-main.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
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
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <ctype.h>
#include <stdbool.h>
typedef enum {
TK_PUNCT,
TK_NUM,
TK_EOF,
} tokenkind;
typedef struct token token;
struct token {
tokenkind kind;
token *next;
int val;
char *loc;
int len;
};
static char *currentinput;
static void error(char *fmt, ...) {
va_list va;
va_start(va, fmt);
vfprintf(stderr, fmt, va);
fprintf(stderr, "\n");
va_end(va);
exit(1);
}
static void verrorat(char *loc, char *fmt, va_list va) {
fprintf(stderr, "%s\n", currentinput);
int pos = loc - currentinput;
fprintf(stderr, "%*s", pos, "");
fprintf(stderr, "^ ");
vfprintf(stderr, fmt, va);
fprintf(stderr, "\n");
va_end(va);
exit(1);
}
static void errorat(char *loc, char *fmt, ...) {
va_list va;
va_start(va, fmt);
verrorat(loc, fmt, va);
}
static void errortok(token *tok, char *fmt, ...) {
va_list va;
va_start(va, fmt);
verrorat(tok -> loc, fmt, va);
}
static bool equal(token *tok, char *str) {
//把存储区 str1 和存储区 str2 的前 n 个字节进行比较。
return memcmp(tok -> loc, str, tok -> len) == 0 && str[tok -> len] == '\0';
}
static token *skip(token * tok, char *str) {
if (!equal(tok, str))
errortok(tok, "expect '%s'", str);
return tok -> next;
}
static int *getnumber(token *tok) {
if (tok -> kind != TK_NUM)
errortok(tok, "expect a number");
return tok -> val;
}
static token *newtoken(tokenkind kind, char *start, char *end) {
token *tok = calloc(1, sizeof(token));
tok -> kind = kind;
tok -> loc = start;
tok -> len = end - start;
return tok;
}
static token *tokenize() {
char *p = currentinput;
token head = {};
token *cur = &head;
while (*p) {
if (isspace(*p)) {
p++;
continue;
}
if (isdigit(*p)) {
cur -> next = newtoken(TK_NUM, p, p);
cur = cur -> next;
const char *oldptr = p;
// 把参数 str 所指向的字符串根据给定的 base 转换为一个无符号长整数
cur -> val = strtoul(p, &p, 10);
cur -> len = p - oldptr;
continue;
}
if (*p == '+' || *p == '-') {
cur -> next = newtoken(TK_PUNCT, p, p + 1);
cur = cur -> next;
p++;
continue;
}
errorat(p, "invalid token!");
}
cur -> next = newtoken(TK_EOF, p, p);
return head.next;
}
int main(int argc, char **argv) {
if (argc != 2) {
error("%s: invalid number of arguments", argv[0]);
}
currentinput = argv[1];
token *tok = tokenize();
printf(" .globl main\n");
printf("main:\n");
printf(" li a0, %d\n", getnumber(tok));
tok = tok -> next;
while (tok -> kind != TK_EOF) {
if (equal(tok, "+")) {
tok = tok -> next;
printf(" addi a0, a0, %d\n", getnumber(tok));
tok = tok -> next;
continue;
}
tok = skip(tok, "-");
printf(" addi a0, a0, -%d\n", getnumber(tok));
tok = tok -> next;
}
printf(" ret\n");
return 0;
}