more const

This commit is contained in:
Yaossg 2024-11-17 17:01:18 +08:00
parent 5670654667
commit e97820d7ef
2 changed files with 52 additions and 58 deletions

View File

@ -43,9 +43,9 @@ $ sh boot.sh
### 关键字 ### 关键字
本语言包含的关键字即为支持的标量类型的关键字和流程控制的关键字。 本语言包含的关键字即为支持的标量类型的关键字和流程控制的关键字,还有 `const`
此外还支持 `const` 关键字,但是行为是直接忽略。这是为了更好兼容 C 程序。 `const` 关键字可以在类型中使用,但会被直接忽略。支持它是为了更好兼容 C 程序。
### 支持六个基本类型 ### 支持六个基本类型
@ -111,6 +111,8 @@ $ sh boot.sh
目前源代码中的常数能够保证自举。 目前源代码中的常数能够保证自举。
如果愿意,完全可以把程序中的各类表改为 `malloc``free` 动态管理,本语言是完全支持的。
## 依赖 ## 依赖
直接依赖下面这些 C 语言库函数,在本语言中提供声明后调用。 直接依赖下面这些 C 语言库函数,在本语言中提供声明后调用。

104
boot.c
View File

@ -55,21 +55,32 @@ const int TOKEN_BRACKET_RIGHT = 53;
const int TOKEN_BRACE_LEFT = 54; const int TOKEN_BRACE_LEFT = 54;
const int TOKEN_BRACE_RIGHT = 55; const int TOKEN_BRACE_RIGHT = 55;
const int TOKEN_STRING = 99;
const int TOKEN_NUMBER = 100; const int TOKEN_NUMBER = 100;
const int TOKEN_ID = 101; const int TOKEN_ID = 101;
const int TOKEN_INT = 102; const int TOKEN_IF = 102;
const int TOKEN_IF = 103; const int TOKEN_ELSE = 103;
const int TOKEN_ELSE = 104; const int TOKEN_WHILE = 104;
const int TOKEN_WHILE = 105; const int TOKEN_FOR = 105;
const int TOKEN_BREAK = 106; const int TOKEN_DO = 106;
const int TOKEN_CONTINUE = 107; const int TOKEN_BREAK = 107;
const int TOKEN_RETURN = 108; const int TOKEN_CONTINUE = 108;
const int TOKEN_VOID = 109; const int TOKEN_RETURN = 109;
const int TOKEN_CONST = 110;
const int TOKEN_CHAR = 111; const int TOKEN_CONST = 127;
const int TOKEN_FOR = 112; const int TOKEN_VOID = 128;
const int TOKEN_DO = 113; const int TOKEN_INT = 129;
const int TOKEN_STRING = 150; const int TOKEN_CHAR = 130;
const int TYPE_VOID = 0;
const int TYPE_INT = 1;
const int TYPE_CHAR = 2;
const int TYPE_VOID_PTR = 16;
const int TYPE_INT_PTR = 17;
const int TYPE_CHAR_PTR = 18;
const int TYPE_PTR_MASK = 16;
const int TYPE_TOKEN_MASK = 128;
int parse_int(int ch) { int parse_int(int ch) {
int num = ch - '0'; int num = ch - '0';
@ -390,39 +401,24 @@ void expect_token(int expected_type) {
} }
} }
const int TYPE_VOID = 0; void ignore_const() {
const int TYPE_INT = 1;
const int TYPE_CHAR = 2;
const int TYPE_VOID_PTR = 16;
const int TYPE_INT_PTR = 17;
const int TYPE_CHAR_PTR = 18;
const int TYPE_PTR_MASK = 16;
int parse_type() {
if (token_type == TOKEN_CONST) { if (token_type == TOKEN_CONST) {
next_token(); next_token();
} }
if (token_type == TOKEN_INT) { }
int parse_type() {
ignore_const();
if (token_type == TOKEN_INT || token_type == TOKEN_CHAR || token_type == TOKEN_VOID) {
int type = token_type & ~TYPE_TOKEN_MASK;
next_token(); next_token();
ignore_const();
if (token_type == TOKEN_STAR) { if (token_type == TOKEN_STAR) {
return TYPE_INT_PTR; ignore_const();
return type | TYPE_PTR_MASK;
} }
unget_token(); unget_token();
return TYPE_INT; return type;
} else if (token_type == TOKEN_CHAR) {
next_token();
if (token_type == TOKEN_STAR) {
return TYPE_CHAR_PTR;
}
unget_token();
return TYPE_CHAR;
} else if (token_type == TOKEN_VOID) {
next_token();
if (token_type == TOKEN_STAR) {
return TYPE_VOID_PTR;
}
unget_token();
return TYPE_VOID;
} else { } else {
return -1; return -1;
} }
@ -553,8 +549,7 @@ void load(int rd, int id) {
const char* op = "lw"; // int const char* op = "lw"; // int
if (type == TYPE_CHAR) { if (type == TYPE_CHAR) {
op = "lb"; op = "lb";
} } else if (type & TYPE_PTR_MASK) {
if (type & TYPE_PTR_MASK) {
op = "ld"; op = "ld";
} }
printf(" %s t%d, 0(t%d) # id: type %d\n", op, rd, rd, type); printf(" %s t%d, 0(t%d) # id: type %d\n", op, rd, rd, type);
@ -566,8 +561,7 @@ void store_t0(int id) {
const char* op = "sw"; // int const char* op = "sw"; // int
if (type == TYPE_CHAR) { if (type == TYPE_CHAR) {
op = "sb"; op = "sb";
} } else if (type & TYPE_PTR_MASK) {
if (type & TYPE_PTR_MASK) {
op = "sd"; op = "sd";
} }
printf(" %s t0, 0(t1) # id: type %d\n", op, type); printf(" %s t0, 0(t1) # id: type %d\n", op, type);
@ -1356,7 +1350,12 @@ void parse_global_variable(int id, const char* name, int type) {
expect_token(TOKEN_SEMICOLON); expect_token(TOKEN_SEMICOLON);
} }
void parse_decl(int type) { void parse_global_declaration() {
int type = parse_type();
if (type < 0) {
eprintf("unexpected token: %d\n", token_type);
exit(1);
}
expect_token(TOKEN_ID); expect_token(TOKEN_ID);
int id = token_data; int id = token_data;
char* name = id_table + id_lut[id]; char* name = id_table + id_lut[id];
@ -1372,15 +1371,9 @@ void parse_decl(int type) {
void parse_top_level() { void parse_top_level() {
next_token(); next_token();
int decl_type; if (token_type == TOKEN_EOF)
if (token_type == TOKEN_EOF) {
return; return;
} else if ((decl_type = parse_type()) >= 0) { parse_global_declaration();
parse_decl(decl_type);
} else {
eprintf("unexpected token: %d\n", token_type);
exit(1);
}
parse_top_level(); parse_top_level();
} }
@ -1388,9 +1381,9 @@ void dump_string_table() {
printf(".data\n"); printf(".data\n");
for (int i = 0; i < string_lut_size; ++i) { for (int i = 0; i < string_lut_size; ++i) {
printf(".LC%d: .string \"", i); printf(".LC%d: .string \"", i);
int offset = 0; int offset = string_lut[i];
int ch; int ch;
while ((ch = string_table[string_lut[i] + offset]) != 0) { while ((ch = string_table[offset++]) != 0) {
if (ch == '\n') { if (ch == '\n') {
printf("\\n"); printf("\\n");
} else if (ch == '\t') { } else if (ch == '\t') {
@ -1408,7 +1401,6 @@ void dump_string_table() {
} else { } else {
printf("%c", ch); printf("%c", ch);
} }
offset++;
} }
printf("\"\n"); printf("\"\n");
} }