Break loop.
This commit is contained in:
parent
63f9eb48a4
commit
050e85b72a
2
Makefile
2
Makefile
@ -1,6 +1,6 @@
|
|||||||
CC = gcc
|
CC = gcc
|
||||||
CFLAGS = -Wall -Wextra -O2 -Isrc
|
CFLAGS = -Wall -Wextra -O2 -Isrc
|
||||||
LDFLAGS = -lm
|
LDFLAGS = -lm -lpthread
|
||||||
|
|
||||||
SRC_DIR = src
|
SRC_DIR = src
|
||||||
TEST_DIR = tests
|
TEST_DIR = tests
|
||||||
|
|||||||
20
TODO2.md
Normal file
20
TODO2.md
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# TO BUILD
|
||||||
|
|
||||||
|
1. Read the whole source code in src.
|
||||||
|
2. Add File I/O Functions to the scripting language
|
||||||
|
2.1 Add working tests within the tests directory.
|
||||||
|
3. Implement async I/O functions for File I/O / Socket I/O / Async I/O. The basic asyncio for methods should be we working using threads so it's a multicore application. It must be a safe way of threading but still performance.
|
||||||
|
3.1 Add working tests within the tests directory.
|
||||||
|
3.2 Add a nice example script source file (.rc) to the examples directory that shows file I/O, async I/O, and socket I/O.
|
||||||
|
4. Add double data type to the language
|
||||||
|
4.1 Add working tests within the tests directory.
|
||||||
|
5. Implement break and continue statements in the language
|
||||||
|
5.1 Add working tests within the tests directory.
|
||||||
|
6. Update Makefile, README.md, and TUTORIAL.md.
|
||||||
|
|
||||||
|
# IMPORTANT
|
||||||
|
1. Consistency (By researching how other things are implemented)
|
||||||
|
2. Performance (But readability is also important)
|
||||||
|
3. Ease of use for the user of the new language (No weird caveats)
|
||||||
|
4. Safety (for using the langauge by defensive coding)
|
||||||
|
|
||||||
@ -73,11 +73,20 @@ void statement() {
|
|||||||
pc++;
|
pc++;
|
||||||
while (pc < MAX_TOK && pc < tk_idx && tokens[pc].type != '}' && tokens[pc].type != 0) {
|
while (pc < MAX_TOK && pc < tk_idx && tokens[pc].type != '}' && tokens[pc].type != 0) {
|
||||||
statement();
|
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('}');
|
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++;
|
pc++;
|
||||||
while (pc < MAX_TOK && pc < tk_idx && tokens[pc].type != ';') {
|
while (pc < MAX_TOK && pc < tk_idx && tokens[pc].type != ';') {
|
||||||
while (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == '*') pc++;
|
while (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == '*') pc++;
|
||||||
@ -94,6 +103,7 @@ void statement() {
|
|||||||
int addr = sp;
|
int addr = sp;
|
||||||
Symbol *s = &locals[loc_cnt++];
|
Symbol *s = &locals[loc_cnt++];
|
||||||
strncpy(s->name, t->text, t->val); s->name[t->val] = 0;
|
strncpy(s->name, t->text, t->val); s->name[t->val] = 0;
|
||||||
|
s->type = var_type;
|
||||||
s->addr = addr;
|
s->addr = addr;
|
||||||
s->is_array = 0;
|
s->is_array = 0;
|
||||||
|
|
||||||
@ -129,42 +139,45 @@ void statement() {
|
|||||||
match(')');
|
match(')');
|
||||||
if (cond) {
|
if (cond) {
|
||||||
statement();
|
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(); }
|
if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == Else) { pc++; skip_block(); }
|
||||||
} else {
|
} else {
|
||||||
skip_block();
|
skip_block();
|
||||||
if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == Else) {
|
if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == Else) {
|
||||||
pc++;
|
pc++;
|
||||||
statement();
|
statement();
|
||||||
if (ax == -999) return;
|
if (ax == -999 || ax == -998 || ax == -997) return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (tokens[pc].type == While) {
|
else if (tokens[pc].type == While) {
|
||||||
pc++;
|
pc++;
|
||||||
int loop_start = pc;
|
int loop_start = pc;
|
||||||
match('(');
|
int body_start;
|
||||||
long cond = expression();
|
int iteration_count = 0;
|
||||||
match(')');
|
while (1) {
|
||||||
if (!cond) {
|
if (++iteration_count > 1000000) {
|
||||||
skip_block();
|
error("Potential infinite loop detected");
|
||||||
} else {
|
}
|
||||||
int iteration_count = 0;
|
pc = loop_start;
|
||||||
while (1) {
|
match('(');
|
||||||
if (++iteration_count > 1000000) {
|
long cond = expression();
|
||||||
error("Potential infinite loop detected");
|
match(')');
|
||||||
}
|
if (!cond) {
|
||||||
statement();
|
skip_block();
|
||||||
if (ax == -999) return;
|
break;
|
||||||
int save_pc = pc;
|
}
|
||||||
if (loop_start >= MAX_TOK || loop_start >= tk_idx) {
|
body_start = pc;
|
||||||
error("Loop start out of bounds");
|
statement();
|
||||||
}
|
if (ax == -999) return;
|
||||||
pc = loop_start;
|
if (ax == -998) {
|
||||||
match('(');
|
ax = 0;
|
||||||
cond = expression();
|
pc = body_start;
|
||||||
match(')');
|
skip_block();
|
||||||
if (!cond) { pc = save_pc; break; }
|
break;
|
||||||
|
}
|
||||||
|
if (ax == -997) {
|
||||||
|
ax = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -175,6 +188,16 @@ void statement() {
|
|||||||
match(';');
|
match(';');
|
||||||
ax = -999;
|
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) {
|
else if (tokens[pc].type == Printf) {
|
||||||
pc++;
|
pc++;
|
||||||
match('(');
|
match('(');
|
||||||
@ -187,11 +210,16 @@ void statement() {
|
|||||||
|
|
||||||
char *p = fmt;
|
char *p = fmt;
|
||||||
while (*p) {
|
while (*p) {
|
||||||
if (*p == '%' && (p[1] == 'd' || p[1] == 's')) {
|
if (*p == '%' && (p[1] == 'd' || p[1] == 's' || p[1] == 'f')) {
|
||||||
p++;
|
p++;
|
||||||
match(',');
|
match(',');
|
||||||
long val = expression();
|
long val = expression();
|
||||||
if (*p == 'd') printf("%ld", val);
|
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') {
|
else if (*p == 's') {
|
||||||
char *str = (char*)val;
|
char *str = (char*)val;
|
||||||
if (str) printf("%s", str);
|
if (str) printf("%s", str);
|
||||||
@ -214,7 +242,7 @@ void scan_functions() {
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
while (i < MAX_TOK && i < tk_idx && tokens[i].type != 0) {
|
while (i < MAX_TOK && i < tk_idx && tokens[i].type != 0) {
|
||||||
if (i + 2 < MAX_TOK && i + 2 < tk_idx &&
|
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 == '(') {
|
tokens[i+1].type == Id && tokens[i+2].type == '(') {
|
||||||
|
|
||||||
if (func_cnt >= 100) {
|
if (func_cnt >= 100) {
|
||||||
@ -227,7 +255,7 @@ void scan_functions() {
|
|||||||
i += 3;
|
i += 3;
|
||||||
int params = 0;
|
int params = 0;
|
||||||
while(i < MAX_TOK && i < tk_idx && tokens[i].type != ')') {
|
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++;
|
params++;
|
||||||
i++;
|
i++;
|
||||||
while (i < MAX_TOK && i < tk_idx && tokens[i].type == '*') i++;
|
while (i < MAX_TOK && i < tk_idx && tokens[i].type == '*') i++;
|
||||||
|
|||||||
@ -448,6 +448,274 @@ long native_endswith(long *args, int argc) {
|
|||||||
return strcmp(str + str_len - suffix_len, suffix) == 0;
|
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() {
|
void register_native_functions() {
|
||||||
register_native_func("socket", native_socket);
|
register_native_func("socket", native_socket);
|
||||||
register_native_func("bind", native_bind);
|
register_native_func("bind", native_bind);
|
||||||
@ -475,4 +743,24 @@ void register_native_functions() {
|
|||||||
register_native_func("replace", native_replace);
|
register_native_func("replace", native_replace);
|
||||||
register_native_func("startswith", native_startswith);
|
register_native_func("startswith", native_startswith);
|
||||||
register_native_func("endswith", native_endswith);
|
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);
|
||||||
}
|
}
|
||||||
|
|||||||
28
src/parser.c
28
src/parser.c
@ -35,6 +35,12 @@ long factor() {
|
|||||||
pc++;
|
pc++;
|
||||||
return t->val;
|
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) {
|
else if (t->type == Str) {
|
||||||
pc++;
|
pc++;
|
||||||
return (long)t->text;
|
return (long)t->text;
|
||||||
@ -256,6 +262,26 @@ long relational() {
|
|||||||
return val;
|
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() {
|
long expression() {
|
||||||
if (pc >= MAX_TOK) return 0;
|
if (pc >= MAX_TOK) return 0;
|
||||||
if (tokens[pc].type == '*') {
|
if (tokens[pc].type == '*') {
|
||||||
@ -327,5 +353,5 @@ long expression() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return relational();
|
return logical_or();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,8 @@
|
|||||||
#define PARSER_H
|
#define PARSER_H
|
||||||
|
|
||||||
long expression();
|
long expression();
|
||||||
|
long logical_or();
|
||||||
|
long logical_and();
|
||||||
long relational();
|
long relational();
|
||||||
long add();
|
long add();
|
||||||
long term();
|
long term();
|
||||||
|
|||||||
@ -34,11 +34,14 @@ void tokenize(char *src) {
|
|||||||
|
|
||||||
if (!strcmp(buf, "int")) t->type = Int;
|
if (!strcmp(buf, "int")) t->type = Int;
|
||||||
else if (!strcmp(buf, "char")) t->type = Char;
|
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, "if")) t->type = If;
|
||||||
else if (!strcmp(buf, "else")) t->type = Else;
|
else if (!strcmp(buf, "else")) t->type = Else;
|
||||||
else if (!strcmp(buf, "while")) t->type = While;
|
else if (!strcmp(buf, "while")) t->type = While;
|
||||||
else if (!strcmp(buf, "return")) t->type = Return;
|
else if (!strcmp(buf, "return")) t->type = Return;
|
||||||
else if (!strcmp(buf, "printf")) t->type = Printf;
|
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;
|
else t->type = Id;
|
||||||
|
|
||||||
t->val = len;
|
t->val = len;
|
||||||
@ -46,9 +49,20 @@ void tokenize(char *src) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isdigit(*s)) {
|
if (isdigit(*s) || (*s == '.' && s[1] && isdigit(s[1]))) {
|
||||||
t->type = Num;
|
char *start = s;
|
||||||
t->val = strtol(s, &s, 10);
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,13 +8,14 @@
|
|||||||
#define STR_POOL_SIZE 100000
|
#define STR_POOL_SIZE 100000
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
Num = 128, Str, Id, Int, Char, Else, If, While, Return, Printf,
|
Num = 128, Dbl, Str, Id, Int, Char, Double, Else, If, While, Return, Printf,
|
||||||
Assign, Eq, Ne, Lt, Gt, Le, Ge, Or, And, Inc, Dec
|
Assign, Eq, Ne, Lt, Gt, Le, Ge, Or, And, Inc, Dec, Break, Continue
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int type;
|
int type;
|
||||||
long val;
|
long val;
|
||||||
|
double dval;
|
||||||
char *text;
|
char *text;
|
||||||
} Token;
|
} Token;
|
||||||
|
|
||||||
|
|||||||
81
tests/break_continue_test.rc
Normal file
81
tests/break_continue_test.rc
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
int main() {
|
||||||
|
printf("=== Break and Continue Tests ===\n");
|
||||||
|
|
||||||
|
printf("Test 1: Break statement\n");
|
||||||
|
int count = 0;
|
||||||
|
while (count < 10) {
|
||||||
|
count = count + 1;
|
||||||
|
if (count == 5) {
|
||||||
|
printf("Breaking at count = %d\n", count);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
printf("count = %d\n", count);
|
||||||
|
}
|
||||||
|
printf("Final count after break: %d\n", count);
|
||||||
|
printf("PASS: Break works\n");
|
||||||
|
|
||||||
|
printf("Test 2: Continue statement\n");
|
||||||
|
int i = 0;
|
||||||
|
int sum = 0;
|
||||||
|
while (i < 10) {
|
||||||
|
i = i + 1;
|
||||||
|
if (i == 3 || i == 7) {
|
||||||
|
printf("Skipping i = %d\n", i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sum = sum + i;
|
||||||
|
printf("Adding i = %d, sum = %d\n", i, sum);
|
||||||
|
}
|
||||||
|
printf("Final sum (skipped 3 and 7): %d\n", sum);
|
||||||
|
printf("PASS: Continue works\n");
|
||||||
|
|
||||||
|
printf("Test 3: Break in nested if\n");
|
||||||
|
int j = 0;
|
||||||
|
while (j < 10) {
|
||||||
|
j = j + 1;
|
||||||
|
if (j > 3) {
|
||||||
|
if (j == 6) {
|
||||||
|
printf("Breaking at j = %d (nested if)\n", j);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("j = %d\n", j);
|
||||||
|
}
|
||||||
|
printf("Final j: %d\n", j);
|
||||||
|
printf("PASS: Nested break works\n");
|
||||||
|
|
||||||
|
printf("Test 4: Continue in nested if\n");
|
||||||
|
int k = 0;
|
||||||
|
int even_sum = 0;
|
||||||
|
while (k < 10) {
|
||||||
|
k = k + 1;
|
||||||
|
if (k > 0) {
|
||||||
|
int rem = k - (k / 2) * 2;
|
||||||
|
if (rem == 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
even_sum = even_sum + k;
|
||||||
|
}
|
||||||
|
printf("Sum of even numbers 1-10: %d\n", even_sum);
|
||||||
|
printf("PASS: Nested continue works\n");
|
||||||
|
|
||||||
|
printf("Test 5: Multiple breaks and continues\n");
|
||||||
|
int n = 0;
|
||||||
|
int result = 0;
|
||||||
|
while (n < 20) {
|
||||||
|
n = n + 1;
|
||||||
|
if (n < 5) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (n > 15) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
result = result + 1;
|
||||||
|
}
|
||||||
|
printf("Numbers counted between 5 and 15: %d\n", result);
|
||||||
|
printf("PASS: Multiple break/continue works\n");
|
||||||
|
|
||||||
|
printf("\n=== All Break/Continue Tests Completed ===\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
14
tests/break_test1.rc
Normal file
14
tests/break_test1.rc
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
int main() {
|
||||||
|
printf("=== Break Test ===\n");
|
||||||
|
int count = 0;
|
||||||
|
while (count < 10) {
|
||||||
|
count = count + 1;
|
||||||
|
if (count == 5) {
|
||||||
|
printf("Breaking at count = %d\n", count);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
printf("count = %d\n", count);
|
||||||
|
}
|
||||||
|
printf("Final count: %d\n", count);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
13
tests/break_test2.rc
Normal file
13
tests/break_test2.rc
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
int main() {
|
||||||
|
printf("=== Break Test ===\n");
|
||||||
|
int count = 0;
|
||||||
|
while (count < 10) {
|
||||||
|
count = count + 1;
|
||||||
|
if (count == 5) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
printf("count = %d\n", count);
|
||||||
|
}
|
||||||
|
printf("Final count: %d\n", count);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
14
tests/continue_or_test.rc
Normal file
14
tests/continue_or_test.rc
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
int main() {
|
||||||
|
printf("Test OR with continue\n");
|
||||||
|
int i = 0;
|
||||||
|
while (i < 10) {
|
||||||
|
i = i + 1;
|
||||||
|
if (i == 3 || i == 7) {
|
||||||
|
printf("Skip %d\n", i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
printf("i = %d\n", i);
|
||||||
|
}
|
||||||
|
printf("Done\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
14
tests/continue_test_simple.rc
Normal file
14
tests/continue_test_simple.rc
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
int main() {
|
||||||
|
printf("Start\n");
|
||||||
|
int i = 0;
|
||||||
|
while (i < 5) {
|
||||||
|
i = i + 1;
|
||||||
|
if (i == 3) {
|
||||||
|
printf("Skipping i = %d\n", i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
printf("i = %d\n", i);
|
||||||
|
}
|
||||||
|
printf("Done\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
53
tests/double_test.rc
Normal file
53
tests/double_test.rc
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
int main() {
|
||||||
|
printf("=== Double Data Type Tests ===\n");
|
||||||
|
|
||||||
|
printf("Test 1: Double variable declaration and assignment\n");
|
||||||
|
double pi = 3.14159;
|
||||||
|
printf("pi = %f\n", pi);
|
||||||
|
printf("PASS: Double variable works\n");
|
||||||
|
|
||||||
|
printf("Test 2: Double arithmetic using helper functions\n");
|
||||||
|
double a = 10.5;
|
||||||
|
double b = 2.5;
|
||||||
|
printf("a = %f, b = %f\n", a, b);
|
||||||
|
|
||||||
|
double sum = double_add(a, b);
|
||||||
|
printf("a + b = %f\n", sum);
|
||||||
|
|
||||||
|
double diff = double_sub(a, b);
|
||||||
|
printf("a - b = %f\n", diff);
|
||||||
|
|
||||||
|
double prod = double_mul(a, b);
|
||||||
|
printf("a * b = %f\n", prod);
|
||||||
|
|
||||||
|
double quot = double_div(a, b);
|
||||||
|
printf("a / b = %f\n", quot);
|
||||||
|
printf("PASS: Double arithmetic works\n");
|
||||||
|
|
||||||
|
printf("Test 3: Type conversions\n");
|
||||||
|
int x = 42;
|
||||||
|
double dx = int_to_double(x);
|
||||||
|
printf("int %d converted to double: %f\n", x, dx);
|
||||||
|
|
||||||
|
double y = 99.9;
|
||||||
|
int iy = double_to_int(y);
|
||||||
|
printf("double %f converted to int: %d\n", y, iy);
|
||||||
|
printf("PASS: Type conversions work\n");
|
||||||
|
|
||||||
|
printf("Test 4: Double with mathematical functions\n");
|
||||||
|
double num = 16.0;
|
||||||
|
double sq = sqrt(double_to_int(num));
|
||||||
|
double sq_double = int_to_double(sq);
|
||||||
|
printf("sqrt(%f) = %f\n", num, sq_double);
|
||||||
|
printf("PASS: Math functions work with doubles\n");
|
||||||
|
|
||||||
|
printf("Test 5: Complex calculation\n");
|
||||||
|
double radius = 5.0;
|
||||||
|
double pi2 = 3.14159;
|
||||||
|
double area = double_mul(pi2, double_mul(radius, radius));
|
||||||
|
printf("Circle area (r=%f): %f\n", radius, area);
|
||||||
|
printf("PASS: Complex calculations work\n");
|
||||||
|
|
||||||
|
printf("\n=== All Double Tests Completed ===\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
82
tests/file_io_test.rc
Normal file
82
tests/file_io_test.rc
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
int main() {
|
||||||
|
printf("=== File I/O Tests ===\n");
|
||||||
|
|
||||||
|
printf("Test 1: Writing to a file\n");
|
||||||
|
int f = fopen("test_output.txt", "w");
|
||||||
|
if (f == 0) {
|
||||||
|
printf("ERROR: Could not open file for writing\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
fputs(f, "Hello, File I/O!\n");
|
||||||
|
fputs(f, "This is line 2.\n");
|
||||||
|
fputs(f, "Testing file operations.\n");
|
||||||
|
fclose(f);
|
||||||
|
printf("PASS: File written successfully\n");
|
||||||
|
|
||||||
|
printf("Test 2: Reading from file using fgets\n");
|
||||||
|
f = fopen("test_output.txt", "r");
|
||||||
|
if (f == 0) {
|
||||||
|
printf("ERROR: Could not open file for reading\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
char *line1 = fgets(f, 256);
|
||||||
|
printf("Line 1: %s", line1);
|
||||||
|
char *line2 = fgets(f, 256);
|
||||||
|
printf("Line 2: %s", line2);
|
||||||
|
char *line3 = fgets(f, 256);
|
||||||
|
printf("Line 3: %s", line3);
|
||||||
|
fclose(f);
|
||||||
|
printf("PASS: File read successfully\n");
|
||||||
|
|
||||||
|
printf("Test 3: File position operations\n");
|
||||||
|
f = fopen("test_output.txt", "r");
|
||||||
|
if (f == 0) {
|
||||||
|
printf("ERROR: Could not open file\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
int pos = ftell(f);
|
||||||
|
printf("Initial position: %d\n", pos);
|
||||||
|
fseek(f, 7, SEEK_SET());
|
||||||
|
pos = ftell(f);
|
||||||
|
printf("Position after seek: %d\n", pos);
|
||||||
|
char *partial = fgets(f, 256);
|
||||||
|
printf("Read after seek: %s", partial);
|
||||||
|
fclose(f);
|
||||||
|
printf("PASS: File positioning works\n");
|
||||||
|
|
||||||
|
printf("Test 4: End of file detection\n");
|
||||||
|
f = fopen("test_output.txt", "r");
|
||||||
|
if (f == 0) {
|
||||||
|
printf("ERROR: Could not open file\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
int line_count = 0;
|
||||||
|
while (feof(f) == 0) {
|
||||||
|
char *line = fgets(f, 256);
|
||||||
|
if (strlen(line) > 0) {
|
||||||
|
line_count = line_count + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("Total lines read: %d\n", line_count);
|
||||||
|
fclose(f);
|
||||||
|
printf("PASS: EOF detection works\n");
|
||||||
|
|
||||||
|
printf("Test 5: File rename operation\n");
|
||||||
|
int result = frename("test_output.txt", "test_renamed.txt");
|
||||||
|
if (result == 0) {
|
||||||
|
printf("PASS: File renamed successfully\n");
|
||||||
|
} else {
|
||||||
|
printf("ERROR: File rename failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Test 6: File removal\n");
|
||||||
|
result = fremove("test_renamed.txt");
|
||||||
|
if (result == 0) {
|
||||||
|
printf("PASS: File removed successfully\n");
|
||||||
|
} else {
|
||||||
|
printf("ERROR: File removal failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n=== All File I/O Tests Completed ===\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
9
tests/or_test.rc
Normal file
9
tests/or_test.rc
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
int main() {
|
||||||
|
printf("Test OR\n");
|
||||||
|
int i = 3;
|
||||||
|
if (i == 3 || i == 7) {
|
||||||
|
printf("Match\n");
|
||||||
|
}
|
||||||
|
printf("Done\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
13
tests/simple_break_test.rc
Normal file
13
tests/simple_break_test.rc
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
int main() {
|
||||||
|
printf("Start\n");
|
||||||
|
int i = 0;
|
||||||
|
while (i < 5) {
|
||||||
|
i = i + 1;
|
||||||
|
printf("i = %d\n", i);
|
||||||
|
if (i == 3) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("After loop, i = %d\n", i);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user