Break loop.

This commit is contained in:
2025-11-23 13:53:36 +01:00
parent 63f9eb48a4
commit 050e85b72a
17 changed files with 708 additions and 36 deletions
+57 -29
View File
@@ -73,11 +73,20 @@ void statement() {
pc++;
while (pc < MAX_TOK && pc < tk_idx && tokens[pc].type != '}' && tokens[pc].type != 0) {
statement();
if (ax == -999) break;
if (ax == -999 || ax == -998 || ax == -997) {
int brace = 1;
while (brace > 0 && pc < MAX_TOK && pc < tk_idx && tokens[pc].type != 0) {
if (tokens[pc].type == '{') brace++;
if (tokens[pc].type == '}') brace--;
pc++;
}
return;
}
}
match('}');
}
else if (tokens[pc].type == Int || tokens[pc].type == Char) {
else if (tokens[pc].type == Int || tokens[pc].type == Char || tokens[pc].type == Double) {
int var_type = tokens[pc].type;
pc++;
while (pc < MAX_TOK && pc < tk_idx && tokens[pc].type != ';') {
while (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == '*') pc++;
@@ -94,6 +103,7 @@ void statement() {
int addr = sp;
Symbol *s = &locals[loc_cnt++];
strncpy(s->name, t->text, t->val); s->name[t->val] = 0;
s->type = var_type;
s->addr = addr;
s->is_array = 0;
@@ -129,42 +139,45 @@ void statement() {
match(')');
if (cond) {
statement();
if (ax == -999) return;
if (ax == -999 || ax == -998 || ax == -997) return;
if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == Else) { pc++; skip_block(); }
} else {
skip_block();
if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == Else) {
pc++;
statement();
if (ax == -999) return;
if (ax == -999 || ax == -998 || ax == -997) return;
}
}
}
else if (tokens[pc].type == While) {
pc++;
int loop_start = pc;
match('(');
long cond = expression();
match(')');
if (!cond) {
skip_block();
} else {
int iteration_count = 0;
while (1) {
if (++iteration_count > 1000000) {
error("Potential infinite loop detected");
}
statement();
if (ax == -999) return;
int save_pc = pc;
if (loop_start >= MAX_TOK || loop_start >= tk_idx) {
error("Loop start out of bounds");
}
pc = loop_start;
match('(');
cond = expression();
match(')');
if (!cond) { pc = save_pc; break; }
int body_start;
int iteration_count = 0;
while (1) {
if (++iteration_count > 1000000) {
error("Potential infinite loop detected");
}
pc = loop_start;
match('(');
long cond = expression();
match(')');
if (!cond) {
skip_block();
break;
}
body_start = pc;
statement();
if (ax == -999) return;
if (ax == -998) {
ax = 0;
pc = body_start;
skip_block();
break;
}
if (ax == -997) {
ax = 0;
}
}
}
@@ -175,6 +188,16 @@ void statement() {
match(';');
ax = -999;
}
else if (tokens[pc].type == Break) {
pc++;
match(';');
ax = -998;
}
else if (tokens[pc].type == Continue) {
pc++;
match(';');
ax = -997;
}
else if (tokens[pc].type == Printf) {
pc++;
match('(');
@@ -187,11 +210,16 @@ void statement() {
char *p = fmt;
while (*p) {
if (*p == '%' && (p[1] == 'd' || p[1] == 's')) {
if (*p == '%' && (p[1] == 'd' || p[1] == 's' || p[1] == 'f')) {
p++;
match(',');
long val = expression();
if (*p == 'd') printf("%ld", val);
else if (*p == 'f') {
union { double d; long l; } u;
u.l = val;
printf("%f", u.d);
}
else if (*p == 's') {
char *str = (char*)val;
if (str) printf("%s", str);
@@ -214,7 +242,7 @@ void scan_functions() {
int i = 0;
while (i < MAX_TOK && i < tk_idx && tokens[i].type != 0) {
if (i + 2 < MAX_TOK && i + 2 < tk_idx &&
(tokens[i].type == Int || tokens[i].type == Char) &&
(tokens[i].type == Int || tokens[i].type == Char || tokens[i].type == Double) &&
tokens[i+1].type == Id && tokens[i+2].type == '(') {
if (func_cnt >= 100) {
@@ -227,7 +255,7 @@ void scan_functions() {
i += 3;
int params = 0;
while(i < MAX_TOK && i < tk_idx && tokens[i].type != ')') {
if (tokens[i].type == Int || tokens[i].type == Char) {
if (tokens[i].type == Int || tokens[i].type == Char || tokens[i].type == Double) {
params++;
i++;
while (i < MAX_TOK && i < tk_idx && tokens[i].type == '*') i++;
+288
View File
@@ -448,6 +448,274 @@ long native_endswith(long *args, int argc) {
return strcmp(str + str_len - suffix_len, suffix) == 0;
}
long native_fopen(long *args, int argc) {
if (!args || argc < 2) {
return 0;
}
char *filename = (char*)args[0];
char *mode = (char*)args[1];
if (!filename || !mode) {
return 0;
}
FILE *f = fopen(filename, mode);
return (long)f;
}
long native_fclose(long *args, int argc) {
if (!args || argc < 1) {
return -1;
}
FILE *f = (FILE*)args[0];
if (!f) {
return -1;
}
return fclose(f);
}
long native_fread(long *args, int argc) {
if (!args || argc < 3) {
return -1;
}
FILE *f = (FILE*)args[0];
int addr = (int)args[1];
int size = (int)args[2];
if (!f || addr < 0 || addr >= MEM_SIZE || size <= 0) {
return -1;
}
if (addr + size > MEM_SIZE) {
size = MEM_SIZE - addr;
}
char temp_buf[8192];
if (size > 8192) size = 8192;
int result = fread(temp_buf, 1, size, f);
if (result > 0) {
for (int i = 0; i < result && addr + i < MEM_SIZE; i++) {
memory[addr + i] = temp_buf[i];
}
}
return result;
}
long native_fwrite(long *args, int argc) {
if (!args || argc < 3) {
return -1;
}
FILE *f = (FILE*)args[0];
long buf_arg = args[1];
int size = (int)args[2];
if (!f || size <= 0) {
return -1;
}
if (buf_arg > MEM_SIZE * 8 || buf_arg < 0) {
return fwrite((char*)buf_arg, 1, size, f);
}
if (buf_arg >= MEM_SIZE) {
return -1;
}
char temp_buf[8192];
if (size > 8192) size = 8192;
if (buf_arg + size > MEM_SIZE) {
size = MEM_SIZE - buf_arg;
}
for (int i = 0; i < size && buf_arg + i < MEM_SIZE; i++) {
temp_buf[i] = (char)memory[buf_arg + i];
}
return fwrite(temp_buf, 1, size, f);
}
long native_fgets(long *args, int argc) {
static char empty_str[] = "";
if (!args || argc < 2) {
return (long)empty_str;
}
FILE *f = (FILE*)args[0];
int max_size = (int)args[1];
if (!f || max_size <= 0) {
return (long)empty_str;
}
if (str_pool_idx >= STR_POOL_SIZE) {
error("String pool overflow");
return (long)empty_str;
}
char *result = &str_pool[str_pool_idx];
if (max_size > STR_POOL_SIZE - str_pool_idx) {
max_size = STR_POOL_SIZE - str_pool_idx;
}
if (fgets(result, max_size, f) == NULL) {
return (long)empty_str;
}
int len = strlen(result);
str_pool_idx += len + 1;
return (long)result;
}
long native_fputs(long *args, int argc) {
if (!args || argc < 2) {
return -1;
}
FILE *f = (FILE*)args[0];
char *str = (char*)args[1];
if (!f || !str) {
return -1;
}
return fputs(str, f);
}
long native_feof(long *args, int argc) {
if (!args || argc < 1) {
return 1;
}
FILE *f = (FILE*)args[0];
if (!f) {
return 1;
}
return feof(f);
}
long native_ftell(long *args, int argc) {
if (!args || argc < 1) {
return -1;
}
FILE *f = (FILE*)args[0];
if (!f) {
return -1;
}
return ftell(f);
}
long native_fseek(long *args, int argc) {
if (!args || argc < 3) {
return -1;
}
FILE *f = (FILE*)args[0];
long offset = args[1];
int whence = (int)args[2];
if (!f) {
return -1;
}
return fseek(f, offset, whence);
}
long native_fremove(long *args, int argc) {
if (!args || argc < 1) {
return -1;
}
char *filename = (char*)args[0];
if (!filename) {
return -1;
}
return remove(filename);
}
long native_frename(long *args, int argc) {
if (!args || argc < 2) {
return -1;
}
char *oldname = (char*)args[0];
char *newname = (char*)args[1];
if (!oldname || !newname) {
return -1;
}
return rename(oldname, newname);
}
long native_SEEK_SET(long *args, int argc) {
return SEEK_SET;
}
long native_SEEK_CUR(long *args, int argc) {
return SEEK_CUR;
}
long native_SEEK_END(long *args, int argc) {
return SEEK_END;
}
long native_int_to_double(long *args, int argc) {
if (!args || argc < 1) {
return 0;
}
union { double d; long l; } u;
u.d = (double)args[0];
return u.l;
}
long native_double_to_int(long *args, int argc) {
if (!args || argc < 1) {
return 0;
}
union { double d; long l; } u;
u.l = args[0];
return (long)u.d;
}
long native_double_add(long *args, int argc) {
if (!args || argc < 2) {
return 0;
}
union { double d; long l; } u1, u2, result;
u1.l = args[0];
u2.l = args[1];
result.d = u1.d + u2.d;
return result.l;
}
long native_double_sub(long *args, int argc) {
if (!args || argc < 2) {
return 0;
}
union { double d; long l; } u1, u2, result;
u1.l = args[0];
u2.l = args[1];
result.d = u1.d - u2.d;
return result.l;
}
long native_double_mul(long *args, int argc) {
if (!args || argc < 2) {
return 0;
}
union { double d; long l; } u1, u2, result;
u1.l = args[0];
u2.l = args[1];
result.d = u1.d * u2.d;
return result.l;
}
long native_double_div(long *args, int argc) {
if (!args || argc < 2) {
return 0;
}
union { double d; long l; } u1, u2, result;
u1.l = args[0];
u2.l = args[1];
if (u2.d != 0.0) {
result.d = u1.d / u2.d;
} else {
result.d = 0.0;
}
return result.l;
}
void register_native_functions() {
register_native_func("socket", native_socket);
register_native_func("bind", native_bind);
@@ -475,4 +743,24 @@ void register_native_functions() {
register_native_func("replace", native_replace);
register_native_func("startswith", native_startswith);
register_native_func("endswith", native_endswith);
register_native_func("fopen", native_fopen);
register_native_func("fclose", native_fclose);
register_native_func("fread", native_fread);
register_native_func("fwrite", native_fwrite);
register_native_func("fgets", native_fgets);
register_native_func("fputs", native_fputs);
register_native_func("feof", native_feof);
register_native_func("ftell", native_ftell);
register_native_func("fseek", native_fseek);
register_native_func("fremove", native_fremove);
register_native_func("frename", native_frename);
register_native_func("SEEK_SET", native_SEEK_SET);
register_native_func("SEEK_CUR", native_SEEK_CUR);
register_native_func("SEEK_END", native_SEEK_END);
register_native_func("int_to_double", native_int_to_double);
register_native_func("double_to_int", native_double_to_int);
register_native_func("double_add", native_double_add);
register_native_func("double_sub", native_double_sub);
register_native_func("double_mul", native_double_mul);
register_native_func("double_div", native_double_div);
}
+27 -1
View File
@@ -35,6 +35,12 @@ long factor() {
pc++;
return t->val;
}
else if (t->type == Dbl) {
pc++;
union { double d; long l; } u;
u.d = t->dval;
return u.l;
}
else if (t->type == Str) {
pc++;
return (long)t->text;
@@ -256,6 +262,26 @@ long relational() {
return val;
}
long logical_and() {
long val = relational();
while (pc < MAX_TOK && tokens[pc].type == And) {
pc++;
long val2 = relational();
val = val && val2;
}
return val;
}
long logical_or() {
long val = logical_and();
while (pc < MAX_TOK && tokens[pc].type == Or) {
pc++;
long val2 = logical_and();
val = val || val2;
}
return val;
}
long expression() {
if (pc >= MAX_TOK) return 0;
if (tokens[pc].type == '*') {
@@ -327,5 +353,5 @@ long expression() {
}
}
return relational();
return logical_or();
}
+2
View File
@@ -2,6 +2,8 @@
#define PARSER_H
long expression();
long logical_or();
long logical_and();
long relational();
long add();
long term();
+17 -3
View File
@@ -34,11 +34,14 @@ void tokenize(char *src) {
if (!strcmp(buf, "int")) t->type = Int;
else if (!strcmp(buf, "char")) t->type = Char;
else if (!strcmp(buf, "double")) t->type = Double;
else if (!strcmp(buf, "if")) t->type = If;
else if (!strcmp(buf, "else")) t->type = Else;
else if (!strcmp(buf, "while")) t->type = While;
else if (!strcmp(buf, "return")) t->type = Return;
else if (!strcmp(buf, "printf")) t->type = Printf;
else if (!strcmp(buf, "break")) t->type = Break;
else if (!strcmp(buf, "continue")) t->type = Continue;
else t->type = Id;
t->val = len;
@@ -46,9 +49,20 @@ void tokenize(char *src) {
continue;
}
if (isdigit(*s)) {
t->type = Num;
t->val = strtol(s, &s, 10);
if (isdigit(*s) || (*s == '.' && s[1] && isdigit(s[1]))) {
char *start = s;
int has_dot = 0;
while (*s && (isdigit(*s) || (*s == '.' && !has_dot))) {
if (*s == '.') has_dot = 1;
s++;
}
if (has_dot) {
t->type = Dbl;
t->dval = strtod(start, NULL);
} else {
t->type = Num;
t->val = strtol(start, NULL, 10);
}
continue;
}
+3 -2
View File
@@ -8,13 +8,14 @@
#define STR_POOL_SIZE 100000
enum {
Num = 128, Str, Id, Int, Char, Else, If, While, Return, Printf,
Assign, Eq, Ne, Lt, Gt, Le, Ge, Or, And, Inc, Dec
Num = 128, Dbl, Str, Id, Int, Char, Double, Else, If, While, Return, Printf,
Assign, Eq, Ne, Lt, Gt, Le, Ge, Or, And, Inc, Dec, Break, Continue
};
typedef struct {
int type;
long val;
double dval;
char *text;
} Token;