201 lines
5.1 KiB
C
201 lines
5.1 KiB
C
|
|
#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) {
|
||
|
|
printf("Error at token %d ('%c'): %s\n", pc, tokens[pc].type, msg);
|
||
|
|
exit(1);
|
||
|
|
}
|
||
|
|
|
||
|
|
void match(int type) {
|
||
|
|
if (tokens[pc].type == type) pc++;
|
||
|
|
else error("Unexpected token");
|
||
|
|
}
|
||
|
|
|
||
|
|
int find_local(char *name, int len) {
|
||
|
|
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) {
|
||
|
|
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) {
|
||
|
|
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 {
|
||
|
|
if (tokens[pc].type == '{') brace++;
|
||
|
|
if (tokens[pc].type == '}') brace--;
|
||
|
|
pc++;
|
||
|
|
} while (brace > 0 && tokens[pc].type != 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
void statement() {
|
||
|
|
if (tokens[pc].type == '{') {
|
||
|
|
pc++;
|
||
|
|
while (tokens[pc].type != '}' && tokens[pc].type != 0) {
|
||
|
|
statement();
|
||
|
|
if (ax == -999) break;
|
||
|
|
}
|
||
|
|
match('}');
|
||
|
|
}
|
||
|
|
else if (tokens[pc].type == Int || tokens[pc].type == Char) {
|
||
|
|
pc++;
|
||
|
|
while (tokens[pc].type != ';') {
|
||
|
|
while (tokens[pc].type == '*') pc++;
|
||
|
|
Token *t = &tokens[pc];
|
||
|
|
match(Id);
|
||
|
|
|
||
|
|
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 == '[') {
|
||
|
|
pc++;
|
||
|
|
int size = (int)expression();
|
||
|
|
match(']');
|
||
|
|
s->is_array = 1;
|
||
|
|
sp += size;
|
||
|
|
} else {
|
||
|
|
sp++;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (tokens[pc].type == '=') {
|
||
|
|
pc++;
|
||
|
|
memory[addr] = expression();
|
||
|
|
}
|
||
|
|
if (tokens[pc].type == ',') pc++;
|
||
|
|
}
|
||
|
|
match(';');
|
||
|
|
}
|
||
|
|
else if (tokens[pc].type == If) {
|
||
|
|
pc++;
|
||
|
|
match('(');
|
||
|
|
long cond = expression();
|
||
|
|
match(')');
|
||
|
|
if (cond) {
|
||
|
|
statement();
|
||
|
|
if (ax == -999) return;
|
||
|
|
if (tokens[pc].type == Else) { pc++; skip_block(); }
|
||
|
|
} else {
|
||
|
|
skip_block();
|
||
|
|
if (tokens[pc].type == Else) {
|
||
|
|
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 {
|
||
|
|
while (1) {
|
||
|
|
statement();
|
||
|
|
if (ax == -999) return;
|
||
|
|
int save_pc = pc;
|
||
|
|
pc = loop_start;
|
||
|
|
match('(');
|
||
|
|
cond = expression();
|
||
|
|
match(')');
|
||
|
|
if (!cond) { pc = save_pc; break; }
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if (tokens[pc].type == Return) {
|
||
|
|
pc++;
|
||
|
|
if (tokens[pc].type != ';') ax = expression();
|
||
|
|
else ax = 0;
|
||
|
|
match(';');
|
||
|
|
ax = -999;
|
||
|
|
}
|
||
|
|
else if (tokens[pc].type == Printf) {
|
||
|
|
pc++;
|
||
|
|
match('(');
|
||
|
|
char *fmt = tokens[pc].text;
|
||
|
|
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);
|
||
|
|
else if (*p == 's') printf("%s", (char*)val);
|
||
|
|
p++;
|
||
|
|
} else {
|
||
|
|
putchar(*p++);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
match(')');
|
||
|
|
match(';');
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
expression();
|
||
|
|
match(';');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void scan_functions() {
|
||
|
|
int i = 0;
|
||
|
|
while (tokens[i].type != 0) {
|
||
|
|
if ((tokens[i].type == Int || tokens[i].type == Char) &&
|
||
|
|
tokens[i+1].type == Id && tokens[i+2].type == '(') {
|
||
|
|
|
||
|
|
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 != ')') {
|
||
|
|
if (tokens[i].type == Int || tokens[i].type == Char) {
|
||
|
|
params++;
|
||
|
|
i++;
|
||
|
|
while (tokens[i].type == '*') i++;
|
||
|
|
if (tokens[i].type == Id) i++;
|
||
|
|
} else i++;
|
||
|
|
}
|
||
|
|
f->param_count = params;
|
||
|
|
i++;
|
||
|
|
f->entry_point = i;
|
||
|
|
|
||
|
|
int brace = 0;
|
||
|
|
do {
|
||
|
|
if (tokens[i].type == '{') brace++;
|
||
|
|
if (tokens[i].type == '}') brace--;
|
||
|
|
i++;
|
||
|
|
} while (brace > 0 && tokens[i].type != 0);
|
||
|
|
} else {
|
||
|
|
i++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|