Update.
This commit is contained in:
parent
e6d75958c8
commit
bd8d9d819e
Binary file not shown.
BIN
build/main.o
BIN
build/main.o
Binary file not shown.
Binary file not shown.
BIN
build/parser.o
BIN
build/parser.o
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -7,16 +7,25 @@
|
||||
#include "parser.h"
|
||||
|
||||
void error(char *msg) {
|
||||
printf("Error at token %d ('%c'): %s\n", pc, tokens[pc].type, msg);
|
||||
if (pc >= 0 && pc < MAX_TOK && pc < tk_idx) {
|
||||
printf("Error at token %d ('%c'): %s\n", pc, tokens[pc].type, msg);
|
||||
} else {
|
||||
printf("Error at token %d: %s\n", pc, msg);
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void match(int type) {
|
||||
if (pc >= MAX_TOK || pc >= tk_idx) {
|
||||
error("Token index out of bounds in match");
|
||||
}
|
||||
if (tokens[pc].type == type) pc++;
|
||||
else error("Unexpected token");
|
||||
}
|
||||
|
||||
int find_local(char *name, int len) {
|
||||
if (!name || len < 0 || len >= 32) return -1;
|
||||
if (loc_cnt > VAR_MAX) loc_cnt = VAR_MAX;
|
||||
for (int i = loc_cnt - 1; i >= 0; i--) {
|
||||
if (!strncmp(locals[i].name, name, len) && locals[i].name[len] == 0)
|
||||
return i;
|
||||
@ -25,6 +34,8 @@ int find_local(char *name, int len) {
|
||||
}
|
||||
|
||||
int find_func(char *name, int len) {
|
||||
if (!name || len < 0 || len >= 32) return -1;
|
||||
if (func_cnt > 100) func_cnt = 100;
|
||||
for (int i = 0; i < func_cnt; i++) {
|
||||
if (!strncmp(funcs[i].name, name, len) && funcs[i].name[len] == 0)
|
||||
return i;
|
||||
@ -33,6 +44,8 @@ int find_func(char *name, int len) {
|
||||
}
|
||||
|
||||
int find_native_func(char *name, int len) {
|
||||
if (!name || len < 0 || len >= 32) return -1;
|
||||
if (native_func_cnt > 100) native_func_cnt = 100;
|
||||
for (int i = 0; i < native_func_cnt; i++) {
|
||||
if (!strncmp(native_funcs[i].name, name, len) && native_funcs[i].name[len] == 0)
|
||||
return i;
|
||||
@ -43,16 +56,22 @@ int find_native_func(char *name, int len) {
|
||||
void skip_block() {
|
||||
int brace = 0;
|
||||
do {
|
||||
if (pc >= MAX_TOK || pc >= tk_idx) {
|
||||
error("Token index out of bounds in skip_block");
|
||||
}
|
||||
if (tokens[pc].type == '{') brace++;
|
||||
if (tokens[pc].type == '}') brace--;
|
||||
pc++;
|
||||
} while (brace > 0 && tokens[pc].type != 0);
|
||||
} while (brace > 0 && pc < MAX_TOK && pc < tk_idx && tokens[pc].type != 0);
|
||||
}
|
||||
|
||||
void statement() {
|
||||
if (pc >= MAX_TOK || pc >= tk_idx) {
|
||||
error("Token index out of bounds in statement");
|
||||
}
|
||||
if (tokens[pc].type == '{') {
|
||||
pc++;
|
||||
while (tokens[pc].type != '}' && tokens[pc].type != 0) {
|
||||
while (pc < MAX_TOK && pc < tk_idx && tokens[pc].type != '}' && tokens[pc].type != 0) {
|
||||
statement();
|
||||
if (ax == -999) break;
|
||||
}
|
||||
@ -60,32 +79,46 @@ void statement() {
|
||||
}
|
||||
else if (tokens[pc].type == Int || tokens[pc].type == Char) {
|
||||
pc++;
|
||||
while (tokens[pc].type != ';') {
|
||||
while (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++;
|
||||
if (pc >= MAX_TOK || pc >= tk_idx) break;
|
||||
Token *t = &tokens[pc];
|
||||
match(Id);
|
||||
|
||||
if (loc_cnt >= VAR_MAX) {
|
||||
error("Too many local variables");
|
||||
}
|
||||
if (sp >= MEM_SIZE) {
|
||||
error("Stack overflow");
|
||||
}
|
||||
int addr = sp;
|
||||
Symbol *s = &locals[loc_cnt++];
|
||||
strncpy(s->name, t->text, t->val); s->name[t->val] = 0;
|
||||
s->addr = addr;
|
||||
s->is_array = 0;
|
||||
|
||||
if (tokens[pc].type == '[') {
|
||||
if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == '[') {
|
||||
pc++;
|
||||
int size = (int)expression();
|
||||
match(']');
|
||||
s->is_array = 1;
|
||||
if (sp + size >= MEM_SIZE) {
|
||||
error("Stack overflow during array allocation");
|
||||
}
|
||||
sp += size;
|
||||
} else {
|
||||
sp++;
|
||||
}
|
||||
|
||||
if (tokens[pc].type == '=') {
|
||||
if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == '=') {
|
||||
pc++;
|
||||
memory[addr] = expression();
|
||||
if (addr >= 0 && addr < MEM_SIZE) {
|
||||
memory[addr] = expression();
|
||||
} else {
|
||||
error("Memory access out of bounds");
|
||||
}
|
||||
}
|
||||
if (tokens[pc].type == ',') pc++;
|
||||
if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == ',') pc++;
|
||||
}
|
||||
match(';');
|
||||
}
|
||||
@ -97,10 +130,10 @@ void statement() {
|
||||
if (cond) {
|
||||
statement();
|
||||
if (ax == -999) return;
|
||||
if (tokens[pc].type == Else) { pc++; skip_block(); }
|
||||
if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == Else) { pc++; skip_block(); }
|
||||
} else {
|
||||
skip_block();
|
||||
if (tokens[pc].type == Else) {
|
||||
if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == Else) {
|
||||
pc++;
|
||||
statement();
|
||||
if (ax == -999) return;
|
||||
@ -116,10 +149,17 @@ void statement() {
|
||||
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();
|
||||
@ -130,7 +170,7 @@ void statement() {
|
||||
}
|
||||
else if (tokens[pc].type == Return) {
|
||||
pc++;
|
||||
if (tokens[pc].type != ';') ax = expression();
|
||||
if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type != ';') ax = expression();
|
||||
else ax = 0;
|
||||
match(';');
|
||||
ax = -999;
|
||||
@ -138,7 +178,11 @@ void statement() {
|
||||
else if (tokens[pc].type == Printf) {
|
||||
pc++;
|
||||
match('(');
|
||||
if (pc >= MAX_TOK || pc >= tk_idx) {
|
||||
error("Token index out of bounds in printf");
|
||||
}
|
||||
char *fmt = tokens[pc].text;
|
||||
if (!fmt) fmt = "";
|
||||
match(Str);
|
||||
|
||||
char *p = fmt;
|
||||
@ -148,7 +192,10 @@ void statement() {
|
||||
match(',');
|
||||
long val = expression();
|
||||
if (*p == 'd') printf("%ld", val);
|
||||
else if (*p == 's') printf("%s", (char*)val);
|
||||
else if (*p == 's') {
|
||||
char *str = (char*)val;
|
||||
if (str) printf("%s", str);
|
||||
}
|
||||
p++;
|
||||
} else {
|
||||
putchar(*p++);
|
||||
@ -165,34 +212,41 @@ void statement() {
|
||||
|
||||
void scan_functions() {
|
||||
int i = 0;
|
||||
while (tokens[i].type != 0) {
|
||||
if ((tokens[i].type == Int || tokens[i].type == Char) &&
|
||||
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+1].type == Id && tokens[i+2].type == '(') {
|
||||
|
||||
if (func_cnt >= 100) {
|
||||
error("Too many functions defined");
|
||||
}
|
||||
Func *f = &funcs[func_cnt++];
|
||||
Token *name = &tokens[i+1];
|
||||
strncpy(f->name, name->text, name->val); f->name[name->val] = 0;
|
||||
|
||||
i += 3;
|
||||
int params = 0;
|
||||
while(tokens[i].type != ')') {
|
||||
while(i < MAX_TOK && i < tk_idx && tokens[i].type != ')') {
|
||||
if (tokens[i].type == Int || tokens[i].type == Char) {
|
||||
params++;
|
||||
i++;
|
||||
while (tokens[i].type == '*') i++;
|
||||
if (tokens[i].type == Id) i++;
|
||||
while (i < MAX_TOK && i < tk_idx && tokens[i].type == '*') i++;
|
||||
if (i < MAX_TOK && i < tk_idx && tokens[i].type == Id) i++;
|
||||
} else i++;
|
||||
}
|
||||
f->param_count = params;
|
||||
i++;
|
||||
if (i < MAX_TOK && i < tk_idx) i++;
|
||||
f->entry_point = i;
|
||||
|
||||
int brace = 0;
|
||||
do {
|
||||
if (i >= MAX_TOK || i >= tk_idx) {
|
||||
error("Token index out of bounds in scan_functions");
|
||||
}
|
||||
if (tokens[i].type == '{') brace++;
|
||||
if (tokens[i].type == '}') brace--;
|
||||
i++;
|
||||
} while (brace > 0 && tokens[i].type != 0);
|
||||
} while (brace > 0 && i < MAX_TOK && i < tk_idx && tokens[i].type != 0);
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
|
||||
17
src/main.c
17
src/main.c
@ -17,8 +17,15 @@ int main(int argc, char **argv) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
src_code = malloc(MAX_SRC);
|
||||
src_code = malloc(MAX_SRC + 1);
|
||||
if (!src_code) {
|
||||
printf("Memory allocation failed.\n");
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t n = fread(src_code, 1, MAX_SRC, f);
|
||||
if (n >= MAX_SRC) n = MAX_SRC - 1;
|
||||
src_code[n] = 0;
|
||||
fclose(f);
|
||||
|
||||
@ -28,17 +35,23 @@ int main(int argc, char **argv) {
|
||||
scan_functions();
|
||||
|
||||
int main_idx = find_func("main", 4);
|
||||
if (main_idx == -1) {
|
||||
if (main_idx == -1 || main_idx >= func_cnt) {
|
||||
printf("No main function found.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pc = funcs[main_idx].entry_point;
|
||||
|
||||
if (sp + 2 >= MEM_SIZE) {
|
||||
printf("Stack overflow during initialization.\n");
|
||||
return 1;
|
||||
}
|
||||
memory[sp++] = 0;
|
||||
memory[sp++] = 0;
|
||||
|
||||
ax = 0;
|
||||
statement();
|
||||
|
||||
free(src_code);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -12,6 +12,9 @@
|
||||
#include "interpreter.h"
|
||||
|
||||
void register_native_func(char *name, NativeFunc func) {
|
||||
if (!name || !func || native_func_cnt >= 100) {
|
||||
return;
|
||||
}
|
||||
NativeFuncDef *nf = &native_funcs[native_func_cnt++];
|
||||
strncpy(nf->name, name, 31);
|
||||
nf->name[31] = 0;
|
||||
@ -19,6 +22,9 @@ void register_native_func(char *name, NativeFunc func) {
|
||||
}
|
||||
|
||||
long native_socket(long *args, int argc) {
|
||||
if (!args || argc < 3) {
|
||||
return -1;
|
||||
}
|
||||
int domain = (int)args[0];
|
||||
int type = (int)args[1];
|
||||
int protocol = (int)args[2];
|
||||
@ -26,6 +32,9 @@ long native_socket(long *args, int argc) {
|
||||
}
|
||||
|
||||
long native_bind(long *args, int argc) {
|
||||
if (!args || argc < 2) {
|
||||
return -1;
|
||||
}
|
||||
int sockfd = (int)args[0];
|
||||
int port = (int)args[1];
|
||||
|
||||
@ -39,28 +48,46 @@ long native_bind(long *args, int argc) {
|
||||
}
|
||||
|
||||
long native_listen(long *args, int argc) {
|
||||
if (!args || argc < 2) {
|
||||
return -1;
|
||||
}
|
||||
int sockfd = (int)args[0];
|
||||
int backlog = (int)args[1];
|
||||
return listen(sockfd, backlog);
|
||||
}
|
||||
|
||||
long native_accept(long *args, int argc) {
|
||||
if (!args || argc < 1) {
|
||||
return -1;
|
||||
}
|
||||
int sockfd = (int)args[0];
|
||||
return accept(sockfd, NULL, NULL);
|
||||
}
|
||||
|
||||
long native_recv(long *args, int argc) {
|
||||
if (!args || argc < 4) {
|
||||
return -1;
|
||||
}
|
||||
int sockfd = (int)args[0];
|
||||
int addr = (int)args[1];
|
||||
int len = (int)args[2];
|
||||
int flags = (int)args[3];
|
||||
|
||||
if (addr < 0 || addr >= MEM_SIZE) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
char temp_buf[8192];
|
||||
if (len > 8192) len = 8192;
|
||||
if (len < 0) len = 0;
|
||||
|
||||
if (addr + len > MEM_SIZE) {
|
||||
len = MEM_SIZE - addr;
|
||||
}
|
||||
|
||||
int result = recv(sockfd, temp_buf, len, flags);
|
||||
if (result > 0) {
|
||||
for (int i = 0; i < result; i++) {
|
||||
for (int i = 0; i < result && addr + i < MEM_SIZE; i++) {
|
||||
memory[addr + i] = temp_buf[i];
|
||||
}
|
||||
}
|
||||
@ -68,19 +95,34 @@ long native_recv(long *args, int argc) {
|
||||
}
|
||||
|
||||
long native_send(long *args, int argc) {
|
||||
if (!args || argc < 4) {
|
||||
return -1;
|
||||
}
|
||||
int sockfd = (int)args[0];
|
||||
long buf_arg = args[1];
|
||||
int len = (int)args[2];
|
||||
int flags = (int)args[3];
|
||||
|
||||
if (len < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (buf_arg > MEM_SIZE * 8 || buf_arg < 0) {
|
||||
return send(sockfd, (char*)buf_arg, len, flags);
|
||||
}
|
||||
|
||||
if (buf_arg >= MEM_SIZE) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
char temp_buf[8192];
|
||||
if (len > 8192) len = 8192;
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (buf_arg + len > MEM_SIZE) {
|
||||
len = MEM_SIZE - buf_arg;
|
||||
}
|
||||
|
||||
for (int i = 0; i < len && buf_arg + i < MEM_SIZE; i++) {
|
||||
temp_buf[i] = (char)memory[buf_arg + i];
|
||||
}
|
||||
|
||||
@ -88,12 +130,21 @@ long native_send(long *args, int argc) {
|
||||
}
|
||||
|
||||
long native_close(long *args, int argc) {
|
||||
if (!args || argc < 1) {
|
||||
return -1;
|
||||
}
|
||||
int fd = (int)args[0];
|
||||
return close(fd);
|
||||
}
|
||||
|
||||
long native_strlen(long *args, int argc) {
|
||||
if (!args || argc < 1) {
|
||||
return 0;
|
||||
}
|
||||
char *str = (char*)args[0];
|
||||
if (!str) {
|
||||
return 0;
|
||||
}
|
||||
return strlen(str);
|
||||
}
|
||||
|
||||
@ -106,40 +157,70 @@ long native_SOCK_STREAM(long *args, int argc) {
|
||||
}
|
||||
|
||||
long native_sqrt(long *args, int argc) {
|
||||
if (!args || argc < 1) {
|
||||
return 0;
|
||||
}
|
||||
return (long)sqrt((double)args[0]);
|
||||
}
|
||||
|
||||
long native_pow(long *args, int argc) {
|
||||
if (!args || argc < 2) {
|
||||
return 0;
|
||||
}
|
||||
return (long)pow((double)args[0], (double)args[1]);
|
||||
}
|
||||
|
||||
long native_sin(long *args, int argc) {
|
||||
if (!args || argc < 1) {
|
||||
return 0;
|
||||
}
|
||||
return (long)(sin((double)args[0]) * 1000000);
|
||||
}
|
||||
|
||||
long native_cos(long *args, int argc) {
|
||||
if (!args || argc < 1) {
|
||||
return 0;
|
||||
}
|
||||
return (long)(cos((double)args[0]) * 1000000);
|
||||
}
|
||||
|
||||
long native_tan(long *args, int argc) {
|
||||
if (!args || argc < 1) {
|
||||
return 0;
|
||||
}
|
||||
return (long)(tan((double)args[0]) * 1000000);
|
||||
}
|
||||
|
||||
long native_abs(long *args, int argc) {
|
||||
if (!args || argc < 1) {
|
||||
return 0;
|
||||
}
|
||||
return (long)abs((int)args[0]);
|
||||
}
|
||||
|
||||
long native_floor(long *args, int argc) {
|
||||
if (!args || argc < 1) {
|
||||
return 0;
|
||||
}
|
||||
return (long)floor((double)args[0]);
|
||||
}
|
||||
|
||||
long native_ceil(long *args, int argc) {
|
||||
if (!args || argc < 1) {
|
||||
return 0;
|
||||
}
|
||||
return (long)ceil((double)args[0]);
|
||||
}
|
||||
|
||||
long native_strpos(long *args, int argc) {
|
||||
if (!args || argc < 2) {
|
||||
return -1;
|
||||
}
|
||||
char *haystack = (char*)args[0];
|
||||
char *needle = (char*)args[1];
|
||||
if (!haystack || !needle) {
|
||||
return -1;
|
||||
}
|
||||
char *pos = strstr(haystack, needle);
|
||||
if (pos) {
|
||||
return pos - haystack;
|
||||
@ -148,20 +229,33 @@ long native_strpos(long *args, int argc) {
|
||||
}
|
||||
|
||||
long native_substr(long *args, int argc) {
|
||||
static char empty_str[] = "";
|
||||
if (!args || argc < 3) {
|
||||
return (long)empty_str;
|
||||
}
|
||||
char *str = (char*)args[0];
|
||||
if (!str) {
|
||||
return (long)empty_str;
|
||||
}
|
||||
int start = (int)args[1];
|
||||
int length = (int)args[2];
|
||||
|
||||
if (str_pool_idx >= STR_POOL_SIZE) {
|
||||
error("String pool overflow");
|
||||
return (long)empty_str;
|
||||
}
|
||||
|
||||
char *result = &str_pool[str_pool_idx];
|
||||
int str_len = strlen(str);
|
||||
|
||||
if (start < 0) start = 0;
|
||||
if (start >= str_len) return (long)"";
|
||||
if (start >= str_len) return (long)empty_str;
|
||||
if (start + length > str_len) length = str_len - start;
|
||||
if (length < 0) return (long)"";
|
||||
if (length < 0) return (long)empty_str;
|
||||
|
||||
if (str_pool_idx + length + 1 >= STR_POOL_SIZE) {
|
||||
error("String pool overflow");
|
||||
return (long)empty_str;
|
||||
}
|
||||
|
||||
strncpy(result, str + start, length);
|
||||
@ -172,12 +266,26 @@ long native_substr(long *args, int argc) {
|
||||
}
|
||||
|
||||
long native_upper(long *args, int argc) {
|
||||
static char empty_str[] = "";
|
||||
if (!args || argc < 1) {
|
||||
return (long)empty_str;
|
||||
}
|
||||
char *str = (char*)args[0];
|
||||
if (!str) {
|
||||
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];
|
||||
int len = strlen(str);
|
||||
|
||||
if (str_pool_idx + len + 1 >= STR_POOL_SIZE) {
|
||||
error("String pool overflow");
|
||||
return (long)empty_str;
|
||||
}
|
||||
|
||||
for (int i = 0; i <= len; i++) {
|
||||
@ -189,12 +297,26 @@ long native_upper(long *args, int argc) {
|
||||
}
|
||||
|
||||
long native_lower(long *args, int argc) {
|
||||
static char empty_str[] = "";
|
||||
if (!args || argc < 1) {
|
||||
return (long)empty_str;
|
||||
}
|
||||
char *str = (char*)args[0];
|
||||
if (!str) {
|
||||
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];
|
||||
int len = strlen(str);
|
||||
|
||||
if (str_pool_idx + len + 1 >= STR_POOL_SIZE) {
|
||||
error("String pool overflow");
|
||||
return (long)empty_str;
|
||||
}
|
||||
|
||||
for (int i = 0; i <= len; i++) {
|
||||
@ -206,7 +328,20 @@ long native_lower(long *args, int argc) {
|
||||
}
|
||||
|
||||
long native_strip(long *args, int argc) {
|
||||
static char empty_str[] = "";
|
||||
if (!args || argc < 1) {
|
||||
return (long)empty_str;
|
||||
}
|
||||
char *str = (char*)args[0];
|
||||
if (!str) {
|
||||
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];
|
||||
|
||||
while (*str && isspace(*str)) str++;
|
||||
@ -216,6 +351,7 @@ long native_strip(long *args, int argc) {
|
||||
|
||||
if (str_pool_idx + len + 1 >= STR_POOL_SIZE) {
|
||||
error("String pool overflow");
|
||||
return (long)empty_str;
|
||||
}
|
||||
|
||||
strncpy(result, str, len);
|
||||
@ -226,9 +362,21 @@ long native_strip(long *args, int argc) {
|
||||
}
|
||||
|
||||
long native_replace(long *args, int argc) {
|
||||
static char empty_str[] = "";
|
||||
if (!args || argc < 3) {
|
||||
return (long)empty_str;
|
||||
}
|
||||
char *str = (char*)args[0];
|
||||
char *old_str = (char*)args[1];
|
||||
char *new_str = (char*)args[2];
|
||||
if (!str || !old_str || !new_str) {
|
||||
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];
|
||||
char *src = str;
|
||||
@ -236,10 +384,26 @@ long native_replace(long *args, int argc) {
|
||||
int old_len = strlen(old_str);
|
||||
int new_len = strlen(new_str);
|
||||
|
||||
if (old_len == 0) {
|
||||
int str_len = strlen(str);
|
||||
if (str_pool_idx + str_len + 1 >= STR_POOL_SIZE) {
|
||||
error("String pool overflow");
|
||||
return (long)empty_str;
|
||||
}
|
||||
strcpy(result, str);
|
||||
str_pool_idx += str_len + 1;
|
||||
return (long)result;
|
||||
}
|
||||
|
||||
while (*src) {
|
||||
if (strncmp(src, old_str, old_len) == 0) {
|
||||
if (str_pool_idx + (dst - result) + new_len + strlen(src + old_len) + 1 >= STR_POOL_SIZE) {
|
||||
int remaining = strlen(src + old_len);
|
||||
int current_pos = dst - result;
|
||||
if (str_pool_idx + current_pos + new_len + remaining + 1 >= STR_POOL_SIZE) {
|
||||
error("String pool overflow");
|
||||
*dst = 0;
|
||||
str_pool_idx += current_pos + 1;
|
||||
return (long)result;
|
||||
}
|
||||
strcpy(dst, new_str);
|
||||
dst += new_len;
|
||||
@ -256,15 +420,27 @@ long native_replace(long *args, int argc) {
|
||||
}
|
||||
|
||||
long native_startswith(long *args, int argc) {
|
||||
if (!args || argc < 2) {
|
||||
return 0;
|
||||
}
|
||||
char *str = (char*)args[0];
|
||||
char *prefix = (char*)args[1];
|
||||
if (!str || !prefix) {
|
||||
return 0;
|
||||
}
|
||||
int prefix_len = strlen(prefix);
|
||||
return strncmp(str, prefix, prefix_len) == 0;
|
||||
}
|
||||
|
||||
long native_endswith(long *args, int argc) {
|
||||
if (!args || argc < 2) {
|
||||
return 0;
|
||||
}
|
||||
char *str = (char*)args[0];
|
||||
char *suffix = (char*)args[1];
|
||||
if (!str || !suffix) {
|
||||
return 0;
|
||||
}
|
||||
int str_len = strlen(str);
|
||||
int suffix_len = strlen(suffix);
|
||||
|
||||
|
||||
66
src/parser.c
66
src/parser.c
@ -27,6 +27,7 @@ extern int find_native_func(char *name, int len);
|
||||
extern void statement();
|
||||
|
||||
long factor() {
|
||||
if (pc >= MAX_TOK) return 0;
|
||||
Token *t = &tokens[pc];
|
||||
long val = 0;
|
||||
|
||||
@ -45,17 +46,22 @@ long factor() {
|
||||
return val;
|
||||
}
|
||||
else if (t->type == Id) {
|
||||
if (pc + 1 >= MAX_TOK) return 0;
|
||||
if (tokens[pc + 1].type == '(') {
|
||||
int nf_idx = find_native_func(t->text, t->val);
|
||||
|
||||
if (nf_idx != -1) {
|
||||
if (nf_idx < 0 || nf_idx >= native_func_cnt) return 0;
|
||||
pc += 2;
|
||||
long args[10];
|
||||
int argc = 0;
|
||||
|
||||
if (pc >= MAX_TOK) return 0;
|
||||
if (tokens[pc].type != ')') {
|
||||
do {
|
||||
if (argc >= 10) break;
|
||||
args[argc++] = expression();
|
||||
if (pc >= MAX_TOK) return 0;
|
||||
} while (tokens[pc].type == ',' && pc++);
|
||||
}
|
||||
match(')');
|
||||
@ -65,30 +71,42 @@ long factor() {
|
||||
|
||||
int f_idx = find_func(t->text, t->val);
|
||||
if (f_idx == -1) error("Unknown function");
|
||||
if (f_idx < 0 || f_idx >= func_cnt) return 0;
|
||||
pc += 2;
|
||||
|
||||
int old_bp = bp;
|
||||
long args[10];
|
||||
int argc = 0;
|
||||
|
||||
if (pc >= MAX_TOK) return 0;
|
||||
if (tokens[pc].type != ')') {
|
||||
do {
|
||||
if (argc >= 10) break;
|
||||
args[argc++] = expression();
|
||||
if (pc >= MAX_TOK) return 0;
|
||||
} while (tokens[pc].type == ',' && pc++);
|
||||
}
|
||||
match(')');
|
||||
|
||||
int ret_pc = pc;
|
||||
if (sp >= MEM_SIZE) return 0;
|
||||
if (bp < 0 || bp >= MEM_SIZE) return 0;
|
||||
memory[sp] = bp; bp = sp++;
|
||||
if (sp >= MEM_SIZE) return 0;
|
||||
memory[sp++] = ret_pc;
|
||||
for(int i=0; i<argc; i++) memory[sp++] = args[i];
|
||||
for(int i=0; i<argc; i++) {
|
||||
if (sp >= MEM_SIZE) break;
|
||||
memory[sp++] = args[i];
|
||||
}
|
||||
|
||||
pc = funcs[f_idx].entry_point;
|
||||
statement();
|
||||
|
||||
val = ax;
|
||||
|
||||
if (bp < 0 || bp >= MEM_SIZE) return 0;
|
||||
sp = bp;
|
||||
if (sp < 0 || sp >= MEM_SIZE) return 0;
|
||||
bp = memory[sp];
|
||||
pc = ret_pc;
|
||||
return val;
|
||||
@ -96,19 +114,23 @@ long factor() {
|
||||
else {
|
||||
int idx = find_local(t->text, t->val);
|
||||
if (idx == -1) error("Undefined variable");
|
||||
if (idx < 0 || idx >= loc_cnt) return 0;
|
||||
pc++;
|
||||
|
||||
Symbol *sym = &locals[idx];
|
||||
|
||||
if (pc >= MAX_TOK) return 0;
|
||||
if (tokens[pc].type == '[') {
|
||||
pc++;
|
||||
long start_or_index = expression();
|
||||
|
||||
if (pc >= MAX_TOK) return 0;
|
||||
if (tokens[pc].type == ':') {
|
||||
pc++;
|
||||
long end = expression();
|
||||
match(']');
|
||||
|
||||
if (sym->addr < 0 || sym->addr >= MEM_SIZE) return 0;
|
||||
long val = memory[sym->addr];
|
||||
if (is_string_ptr(val)) {
|
||||
return slice_string(val, start_or_index, end);
|
||||
@ -117,7 +139,9 @@ long factor() {
|
||||
}
|
||||
} else {
|
||||
match(']');
|
||||
return memory[sym->addr + start_or_index];
|
||||
long addr = sym->addr + start_or_index;
|
||||
if (addr < 0 || addr >= MEM_SIZE) return 0;
|
||||
return memory[addr];
|
||||
}
|
||||
}
|
||||
|
||||
@ -125,6 +149,7 @@ long factor() {
|
||||
return sym->addr;
|
||||
}
|
||||
|
||||
if (sym->addr < 0 || sym->addr >= MEM_SIZE) return 0;
|
||||
return memory[sym->addr];
|
||||
}
|
||||
}
|
||||
@ -132,20 +157,24 @@ long factor() {
|
||||
}
|
||||
|
||||
long unary() {
|
||||
if (pc >= MAX_TOK) return 0;
|
||||
if (tokens[pc].type == '*') {
|
||||
pc++;
|
||||
int addr = unary();
|
||||
if (addr > MEM_SIZE * 8 || addr < 0) {
|
||||
return *(char*)addr;
|
||||
}
|
||||
if (addr < 0 || addr >= MEM_SIZE) return 0;
|
||||
return memory[addr];
|
||||
}
|
||||
else if (tokens[pc].type == '&') {
|
||||
pc++;
|
||||
if (pc >= MAX_TOK) return 0;
|
||||
Token *t = &tokens[pc];
|
||||
if (t->type != Id) error("Expected identifier after &");
|
||||
int idx = find_local(t->text, t->val);
|
||||
if (idx == -1) error("Undefined variable");
|
||||
if (idx < 0 || idx >= loc_cnt) return 0;
|
||||
pc++;
|
||||
return locals[idx].addr;
|
||||
}
|
||||
@ -158,18 +187,21 @@ long unary() {
|
||||
|
||||
long term() {
|
||||
long val = unary();
|
||||
while (tokens[pc].type == '*' || tokens[pc].type == '/') {
|
||||
while (pc < MAX_TOK && (tokens[pc].type == '*' || tokens[pc].type == '/')) {
|
||||
int op = tokens[pc++].type;
|
||||
long val2 = unary();
|
||||
if (op == '*') val = val * val2;
|
||||
else val = val / val2;
|
||||
else {
|
||||
if (val2 != 0) val = val / val2;
|
||||
else val = 0;
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
long add() {
|
||||
long val = term();
|
||||
while (tokens[pc].type == '+' || tokens[pc].type == '-') {
|
||||
while (pc < MAX_TOK && (tokens[pc].type == '+' || tokens[pc].type == '-')) {
|
||||
int op = tokens[pc++].type;
|
||||
long val2 = term();
|
||||
if (op == '+') {
|
||||
@ -187,7 +219,7 @@ long add() {
|
||||
|
||||
long relational() {
|
||||
long val = add();
|
||||
while (tokens[pc].type >= Eq && tokens[pc].type <= Ge) {
|
||||
while (pc < MAX_TOK && tokens[pc].type >= Eq && tokens[pc].type <= Ge) {
|
||||
int op = tokens[pc++].type;
|
||||
long val2 = add();
|
||||
if (op == Eq) val = val == val2;
|
||||
@ -199,9 +231,11 @@ long relational() {
|
||||
}
|
||||
|
||||
long expression() {
|
||||
if (pc >= MAX_TOK) return 0;
|
||||
if (tokens[pc].type == '*') {
|
||||
int save_pc = pc;
|
||||
unary();
|
||||
if (pc >= MAX_TOK) return 0;
|
||||
if (tokens[pc].type == '=') {
|
||||
pc = save_pc;
|
||||
pc++;
|
||||
@ -214,18 +248,23 @@ long expression() {
|
||||
pc = save_pc;
|
||||
}
|
||||
|
||||
if (pc >= MAX_TOK) return 0;
|
||||
if (tokens[pc].type == Id) {
|
||||
if (pc + 1 >= MAX_TOK) return 0;
|
||||
if (tokens[pc+1].type == '[') {
|
||||
int idx = find_local(tokens[pc].text, tokens[pc].val);
|
||||
if (idx == -1) error("Assign to unknown var");
|
||||
if (idx < 0 || idx >= loc_cnt) return 0;
|
||||
pc += 2;
|
||||
long start_or_index = expression();
|
||||
|
||||
if (pc >= MAX_TOK) return 0;
|
||||
if (tokens[pc].type == ':') {
|
||||
pc++;
|
||||
long end = expression();
|
||||
match(']');
|
||||
|
||||
if (locals[idx].addr < 0 || locals[idx].addr >= MEM_SIZE) return 0;
|
||||
long val = memory[locals[idx].addr];
|
||||
if (is_string_ptr(val)) {
|
||||
return slice_string(val, start_or_index, end);
|
||||
@ -236,19 +275,28 @@ long expression() {
|
||||
|
||||
match(']');
|
||||
int addr = locals[idx].addr;
|
||||
if (pc >= MAX_TOK) return 0;
|
||||
if (tokens[pc].type == '=') {
|
||||
pc++;
|
||||
long val = expression();
|
||||
memory[addr + start_or_index] = val;
|
||||
long target_addr = addr + start_or_index;
|
||||
if (target_addr >= 0 && target_addr < MEM_SIZE) {
|
||||
memory[target_addr] = val;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
return memory[addr + start_or_index];
|
||||
long read_addr = addr + start_or_index;
|
||||
if (read_addr < 0 || read_addr >= MEM_SIZE) return 0;
|
||||
return memory[read_addr];
|
||||
} else if (tokens[pc+1].type == '=') {
|
||||
int idx = find_local(tokens[pc].text, tokens[pc].val);
|
||||
if (idx == -1) error("Assign to unknown var");
|
||||
if (idx < 0 || idx >= loc_cnt) return 0;
|
||||
pc += 2;
|
||||
long val = expression();
|
||||
memory[locals[idx].addr] = val;
|
||||
if (locals[idx].addr >= 0 && locals[idx].addr < MEM_SIZE) {
|
||||
memory[locals[idx].addr] = val;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,12 +4,29 @@
|
||||
#include "interpreter.h"
|
||||
|
||||
int is_string_ptr(long val) {
|
||||
return val > MEM_SIZE * 8;
|
||||
if (val < 0) {
|
||||
return 0;
|
||||
}
|
||||
if (val > MEM_SIZE * 8) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
long concat_strings(long ptr1, long ptr2) {
|
||||
static char empty_str[] = "";
|
||||
char *s1 = (char*)ptr1;
|
||||
char *s2 = (char*)ptr2;
|
||||
|
||||
if (!s1 || !s2) {
|
||||
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];
|
||||
|
||||
int len1 = strlen(s1);
|
||||
@ -17,6 +34,7 @@ long concat_strings(long ptr1, long ptr2) {
|
||||
|
||||
if (str_pool_idx + len1 + len2 + 1 >= STR_POOL_SIZE) {
|
||||
error("String pool overflow");
|
||||
return (long)empty_str;
|
||||
}
|
||||
|
||||
strcpy(result, s1);
|
||||
@ -28,7 +46,18 @@ long concat_strings(long ptr1, long ptr2) {
|
||||
}
|
||||
|
||||
long slice_string(long str_ptr, int start, int end) {
|
||||
static char empty_str[] = "";
|
||||
char *str = (char*)str_ptr;
|
||||
|
||||
if (!str) {
|
||||
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];
|
||||
int str_len = strlen(str);
|
||||
|
||||
@ -36,14 +65,19 @@ long slice_string(long str_ptr, int start, int end) {
|
||||
if (end < 0) end = str_len;
|
||||
if (end > str_len) end = str_len;
|
||||
if (start > end) start = end;
|
||||
if (start > str_len) start = str_len;
|
||||
|
||||
int length = end - start;
|
||||
if (length < 0) length = 0;
|
||||
|
||||
if (str_pool_idx + length + 1 >= STR_POOL_SIZE) {
|
||||
error("String pool overflow");
|
||||
return (long)empty_str;
|
||||
}
|
||||
|
||||
strncpy(result, str + start, length);
|
||||
if (length > 0 && start < str_len) {
|
||||
strncpy(result, str + start, length);
|
||||
}
|
||||
result[length] = 0;
|
||||
|
||||
str_pool_idx += length + 1;
|
||||
|
||||
@ -6,13 +6,19 @@
|
||||
|
||||
void tokenize(char *src) {
|
||||
char *s = src;
|
||||
if (!src) return;
|
||||
|
||||
while (*s) {
|
||||
if (isspace(*s)) { s++; continue; }
|
||||
|
||||
if (tk_idx >= MAX_TOK - 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
Token *t = &tokens[tk_idx++];
|
||||
t->text = s;
|
||||
|
||||
if (*s == '/' && *(s+1) == '/') {
|
||||
if (*s == '/' && s[1] && s[1] == '/') {
|
||||
while (*s && *s != '\n') s++;
|
||||
tk_idx--;
|
||||
continue;
|
||||
@ -20,9 +26,10 @@ void tokenize(char *src) {
|
||||
|
||||
if (isalpha(*s)) {
|
||||
int len = 0;
|
||||
while (isalnum(s[len]) || s[len] == '_') len++;
|
||||
while (s[len] && (isalnum(s[len]) || s[len] == '_') && len < 31) len++;
|
||||
|
||||
char buf[32];
|
||||
if (len > 31) len = 31;
|
||||
strncpy(buf, s, len); buf[len] = 0;
|
||||
|
||||
if (!strcmp(buf, "int")) t->type = Int;
|
||||
@ -52,7 +59,7 @@ void tokenize(char *src) {
|
||||
|
||||
char *d = s;
|
||||
while (*s && *s != '"') {
|
||||
if (*s == '\\' && *(s+1) == 'n') {
|
||||
if (*s == '\\' && s[1] && s[1] == 'n') {
|
||||
*d++ = '\n'; s+=2;
|
||||
} else {
|
||||
*d++ = *s++;
|
||||
@ -76,5 +83,7 @@ void tokenize(char *src) {
|
||||
|
||||
t->type = *s++;
|
||||
}
|
||||
tokens[tk_idx].type = 0;
|
||||
if (tk_idx < MAX_TOK) {
|
||||
tokens[tk_idx].type = 0;
|
||||
}
|
||||
}
|
||||
|
||||
41
tests/edge_cases.rc
Normal file
41
tests/edge_cases.rc
Normal file
@ -0,0 +1,41 @@
|
||||
int main() {
|
||||
printf("Testing Edge Cases:\n\n");
|
||||
|
||||
printf("1. Empty string operations:\n");
|
||||
char *empty = "";
|
||||
char *result1 = upper(empty);
|
||||
printf("upper('') = '%s'\n", result1);
|
||||
|
||||
printf("\n2. String slicing edge cases:\n");
|
||||
char *text = "Hello";
|
||||
char *slice1 = text[0:0];
|
||||
printf("'Hello'[0:0] = '%s'\n", slice1);
|
||||
char *slice2 = text[10:20];
|
||||
printf("'Hello'[10:20] = '%s'\n", slice2);
|
||||
char *slice3 = text[3:3];
|
||||
printf("'Hello'[3:3] = '%s'\n", slice3);
|
||||
|
||||
printf("\n3. Math with edge cases:\n");
|
||||
int zero = 0;
|
||||
printf("abs(0) = %d\n", abs(zero));
|
||||
printf("sqrt(0) = %d\n", sqrt(zero));
|
||||
|
||||
printf("\n4. String concatenation:\n");
|
||||
char *str1 = "A";
|
||||
char *str2 = "B";
|
||||
char *concat = str1 + str2;
|
||||
printf("'A' + 'B' = '%s'\n", concat);
|
||||
|
||||
printf("\n5. String search edge cases:\n");
|
||||
int pos1 = strpos("test", "xyz");
|
||||
printf("strpos('test', 'xyz') = %d\n", pos1);
|
||||
int pos2 = strpos("test", "test");
|
||||
printf("strpos('test', 'test') = %d\n", pos2);
|
||||
|
||||
printf("\n6. Nested operations:\n");
|
||||
char *nested = upper(lower(upper("TeSt")));
|
||||
printf("upper(lower(upper('TeSt'))) = '%s'\n", nested);
|
||||
|
||||
printf("\nAll edge cases handled safely!\n");
|
||||
return 0;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user