2025-11-22 22:22:43 +01:00
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <ctype.h>
|
|
|
|
|
#include "types.h"
|
|
|
|
|
#include "interpreter.h"
|
|
|
|
|
#include "parser.h"
|
|
|
|
|
|
|
|
|
|
void error(char *msg) {
|
2025-11-22 23:15:15 +01:00
|
|
|
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);
|
|
|
|
|
}
|
2025-11-22 22:22:43 +01:00
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void match(int type) {
|
2025-11-22 23:15:15 +01:00
|
|
|
if (pc >= MAX_TOK || pc >= tk_idx) {
|
|
|
|
|
error("Token index out of bounds in match");
|
|
|
|
|
}
|
2025-11-22 22:22:43 +01:00
|
|
|
if (tokens[pc].type == type) pc++;
|
|
|
|
|
else error("Unexpected token");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int find_local(char *name, int len) {
|
2025-11-22 23:15:15 +01:00
|
|
|
if (!name || len < 0 || len >= 32) return -1;
|
|
|
|
|
if (loc_cnt > VAR_MAX) loc_cnt = VAR_MAX;
|
2025-11-22 22:22:43 +01:00
|
|
|
for (int i = loc_cnt - 1; i >= 0; i--) {
|
|
|
|
|
if (!strncmp(locals[i].name, name, len) && locals[i].name[len] == 0)
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int find_func(char *name, int len) {
|
2025-11-22 23:15:15 +01:00
|
|
|
if (!name || len < 0 || len >= 32) return -1;
|
|
|
|
|
if (func_cnt > 100) func_cnt = 100;
|
2025-11-22 22:22:43 +01:00
|
|
|
for (int i = 0; i < func_cnt; i++) {
|
|
|
|
|
if (!strncmp(funcs[i].name, name, len) && funcs[i].name[len] == 0)
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int find_native_func(char *name, int len) {
|
2025-11-22 23:15:15 +01:00
|
|
|
if (!name || len < 0 || len >= 32) return -1;
|
|
|
|
|
if (native_func_cnt > 100) native_func_cnt = 100;
|
2025-11-22 22:22:43 +01:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void skip_block() {
|
|
|
|
|
int brace = 0;
|
|
|
|
|
do {
|
2025-11-22 23:15:15 +01:00
|
|
|
if (pc >= MAX_TOK || pc >= tk_idx) {
|
|
|
|
|
error("Token index out of bounds in skip_block");
|
|
|
|
|
}
|
2025-11-22 22:22:43 +01:00
|
|
|
if (tokens[pc].type == '{') brace++;
|
|
|
|
|
if (tokens[pc].type == '}') brace--;
|
|
|
|
|
pc++;
|
2025-11-22 23:15:15 +01:00
|
|
|
} while (brace > 0 && pc < MAX_TOK && pc < tk_idx && tokens[pc].type != 0);
|
2025-11-22 22:22:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void statement() {
|
2025-11-22 23:15:15 +01:00
|
|
|
if (pc >= MAX_TOK || pc >= tk_idx) {
|
|
|
|
|
error("Token index out of bounds in statement");
|
|
|
|
|
}
|
2025-11-22 22:22:43 +01:00
|
|
|
if (tokens[pc].type == '{') {
|
|
|
|
|
pc++;
|
2025-11-22 23:15:15 +01:00
|
|
|
while (pc < MAX_TOK && pc < tk_idx && tokens[pc].type != '}' && tokens[pc].type != 0) {
|
2025-11-22 22:22:43 +01:00
|
|
|
statement();
|
|
|
|
|
if (ax == -999) break;
|
|
|
|
|
}
|
|
|
|
|
match('}');
|
|
|
|
|
}
|
|
|
|
|
else if (tokens[pc].type == Int || tokens[pc].type == Char) {
|
|
|
|
|
pc++;
|
2025-11-22 23:15:15 +01:00
|
|
|
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;
|
2025-11-22 22:22:43 +01:00
|
|
|
Token *t = &tokens[pc];
|
|
|
|
|
match(Id);
|
|
|
|
|
|
2025-11-22 23:15:15 +01:00
|
|
|
if (loc_cnt >= VAR_MAX) {
|
|
|
|
|
error("Too many local variables");
|
|
|
|
|
}
|
|
|
|
|
if (sp >= MEM_SIZE) {
|
|
|
|
|
error("Stack overflow");
|
|
|
|
|
}
|
2025-11-22 22:22:43 +01:00
|
|
|
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;
|
|
|
|
|
|
2025-11-22 23:15:15 +01:00
|
|
|
if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == '[') {
|
2025-11-22 22:22:43 +01:00
|
|
|
pc++;
|
|
|
|
|
int size = (int)expression();
|
|
|
|
|
match(']');
|
|
|
|
|
s->is_array = 1;
|
2025-11-22 23:15:15 +01:00
|
|
|
if (sp + size >= MEM_SIZE) {
|
|
|
|
|
error("Stack overflow during array allocation");
|
|
|
|
|
}
|
2025-11-22 22:22:43 +01:00
|
|
|
sp += size;
|
|
|
|
|
} else {
|
|
|
|
|
sp++;
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-22 23:15:15 +01:00
|
|
|
if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == '=') {
|
2025-11-22 22:22:43 +01:00
|
|
|
pc++;
|
2025-11-22 23:15:15 +01:00
|
|
|
if (addr >= 0 && addr < MEM_SIZE) {
|
|
|
|
|
memory[addr] = expression();
|
|
|
|
|
} else {
|
|
|
|
|
error("Memory access out of bounds");
|
|
|
|
|
}
|
2025-11-22 22:22:43 +01:00
|
|
|
}
|
2025-11-22 23:15:15 +01:00
|
|
|
if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == ',') pc++;
|
2025-11-22 22:22:43 +01:00
|
|
|
}
|
|
|
|
|
match(';');
|
|
|
|
|
}
|
|
|
|
|
else if (tokens[pc].type == If) {
|
|
|
|
|
pc++;
|
|
|
|
|
match('(');
|
|
|
|
|
long cond = expression();
|
|
|
|
|
match(')');
|
|
|
|
|
if (cond) {
|
|
|
|
|
statement();
|
|
|
|
|
if (ax == -999) return;
|
2025-11-22 23:15:15 +01:00
|
|
|
if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == Else) { pc++; skip_block(); }
|
2025-11-22 22:22:43 +01:00
|
|
|
} else {
|
|
|
|
|
skip_block();
|
2025-11-22 23:15:15 +01:00
|
|
|
if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == Else) {
|
2025-11-22 22:22:43 +01:00
|
|
|
pc++;
|
|
|
|
|
statement();
|
|
|
|
|
if (ax == -999) return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (tokens[pc].type == While) {
|
|
|
|
|
pc++;
|
|
|
|
|
int loop_start = pc;
|
|
|
|
|
match('(');
|
|
|
|
|
long cond = expression();
|
|
|
|
|
match(')');
|
|
|
|
|
if (!cond) {
|
|
|
|
|
skip_block();
|
|
|
|
|
} else {
|
2025-11-22 23:15:15 +01:00
|
|
|
int iteration_count = 0;
|
2025-11-22 22:22:43 +01:00
|
|
|
while (1) {
|
2025-11-22 23:15:15 +01:00
|
|
|
if (++iteration_count > 1000000) {
|
|
|
|
|
error("Potential infinite loop detected");
|
|
|
|
|
}
|
2025-11-22 22:22:43 +01:00
|
|
|
statement();
|
|
|
|
|
if (ax == -999) return;
|
|
|
|
|
int save_pc = pc;
|
2025-11-22 23:15:15 +01:00
|
|
|
if (loop_start >= MAX_TOK || loop_start >= tk_idx) {
|
|
|
|
|
error("Loop start out of bounds");
|
|
|
|
|
}
|
2025-11-22 22:22:43 +01:00
|
|
|
pc = loop_start;
|
|
|
|
|
match('(');
|
|
|
|
|
cond = expression();
|
|
|
|
|
match(')');
|
|
|
|
|
if (!cond) { pc = save_pc; break; }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (tokens[pc].type == Return) {
|
|
|
|
|
pc++;
|
2025-11-22 23:15:15 +01:00
|
|
|
if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type != ';') ax = expression();
|
2025-11-22 22:22:43 +01:00
|
|
|
else ax = 0;
|
|
|
|
|
match(';');
|
|
|
|
|
ax = -999;
|
|
|
|
|
}
|
|
|
|
|
else if (tokens[pc].type == Printf) {
|
|
|
|
|
pc++;
|
|
|
|
|
match('(');
|
2025-11-22 23:15:15 +01:00
|
|
|
if (pc >= MAX_TOK || pc >= tk_idx) {
|
|
|
|
|
error("Token index out of bounds in printf");
|
|
|
|
|
}
|
2025-11-22 22:22:43 +01:00
|
|
|
char *fmt = tokens[pc].text;
|
2025-11-22 23:15:15 +01:00
|
|
|
if (!fmt) fmt = "";
|
2025-11-22 22:22:43 +01:00
|
|
|
match(Str);
|
|
|
|
|
|
|
|
|
|
char *p = fmt;
|
|
|
|
|
while (*p) {
|
|
|
|
|
if (*p == '%' && (p[1] == 'd' || p[1] == 's')) {
|
|
|
|
|
p++;
|
|
|
|
|
match(',');
|
|
|
|
|
long val = expression();
|
|
|
|
|
if (*p == 'd') printf("%ld", val);
|
2025-11-22 23:15:15 +01:00
|
|
|
else if (*p == 's') {
|
|
|
|
|
char *str = (char*)val;
|
|
|
|
|
if (str) printf("%s", str);
|
|
|
|
|
}
|
2025-11-22 22:22:43 +01:00
|
|
|
p++;
|
|
|
|
|
} else {
|
|
|
|
|
putchar(*p++);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
match(')');
|
|
|
|
|
match(';');
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
expression();
|
|
|
|
|
match(';');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void scan_functions() {
|
|
|
|
|
int i = 0;
|
2025-11-22 23:15:15 +01:00
|
|
|
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) &&
|
2025-11-22 22:22:43 +01:00
|
|
|
tokens[i+1].type == Id && tokens[i+2].type == '(') {
|
|
|
|
|
|
2025-11-22 23:15:15 +01:00
|
|
|
if (func_cnt >= 100) {
|
|
|
|
|
error("Too many functions defined");
|
|
|
|
|
}
|
2025-11-22 22:22:43 +01:00
|
|
|
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;
|
2025-11-22 23:15:15 +01:00
|
|
|
while(i < MAX_TOK && i < tk_idx && tokens[i].type != ')') {
|
2025-11-22 22:22:43 +01:00
|
|
|
if (tokens[i].type == Int || tokens[i].type == Char) {
|
|
|
|
|
params++;
|
|
|
|
|
i++;
|
2025-11-22 23:15:15 +01:00
|
|
|
while (i < MAX_TOK && i < tk_idx && tokens[i].type == '*') i++;
|
|
|
|
|
if (i < MAX_TOK && i < tk_idx && tokens[i].type == Id) i++;
|
2025-11-22 22:22:43 +01:00
|
|
|
} else i++;
|
|
|
|
|
}
|
|
|
|
|
f->param_count = params;
|
2025-11-22 23:15:15 +01:00
|
|
|
if (i < MAX_TOK && i < tk_idx) i++;
|
2025-11-22 22:22:43 +01:00
|
|
|
f->entry_point = i;
|
|
|
|
|
|
|
|
|
|
int brace = 0;
|
|
|
|
|
do {
|
2025-11-22 23:15:15 +01:00
|
|
|
if (i >= MAX_TOK || i >= tk_idx) {
|
|
|
|
|
error("Token index out of bounds in scan_functions");
|
|
|
|
|
}
|
2025-11-22 22:22:43 +01:00
|
|
|
if (tokens[i].type == '{') brace++;
|
|
|
|
|
if (tokens[i].type == '}') brace--;
|
|
|
|
|
i++;
|
2025-11-22 23:15:15 +01:00
|
|
|
} while (brace > 0 && i < MAX_TOK && i < tk_idx && tokens[i].type != 0);
|
2025-11-22 22:22:43 +01:00
|
|
|
} else {
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|