nested expressions, svalue

master
Clyne Sullivan 7 years ago
parent 0c3901b3a8
commit e67715637a

@ -1,6 +1,6 @@
CC = gcc -m32 CC = gcc -m32
CFLAGS = -Wall -Wextra -I. -ggdb -fno-builtin CFLAGS = -Wall -Wextra -Wno-strict-aliasing -I. -ggdb -fno-builtin
all: all:
$(CC) $(CFLAGS) -c parser.c $(CC) $(CFLAGS) -c parser.c

@ -10,7 +10,9 @@
#define INT(v) (*((int32_t *)&v->value)) #define INT(v) (*((int32_t *)&v->value))
#define FLOAT(v) (*((float *)&v->value)) #define FLOAT(v) (*((float *)&v->value))
#define STR(v) (*((char **)&v->value))
static char *str_func = "(func)";
static char *str_undef = "(undefined)";
char *strclone(const char *s) char *strclone(const char *s)
{ {
@ -26,10 +28,56 @@ char *strnclone(const char *s, uint32_t n)
return clone; return clone;
} }
void ifunc_set(interpreter *it); void fsetstr(variable *f)
void ifunc_jmp(interpreter *it); {
void ifunc_label(interpreter *it); if (f->svalue == 0)
void ifunc_end(interpreter *it); f->svalue = (char *)malloc(16);
snprintf(f->svalue, 16, "%f", FLOAT(f));
}
void isetstr(variable *i)
{
if (i->svalue == 0)
i->svalue = (char *)malloc(12);
snprintf(i->svalue, 12, "%d", INT(i));
}
uint8_t eol(int c)
{
return c == '\n' || c == '\0';
}
uint8_t eot(int c)
{
return eol(c) || c == ' ';
}
uint8_t eoe(int c)
{
return eol(c) || c == ')';
}
uint32_t findend(const char *s, char o, char c)
{
uint8_t indent = 0;
uint32_t i;
for (i = 1; !eol(s[i]); i++) {
if (s[i] == o) {
indent++;
} else if (s[i] == c) {
if (indent == 0)
break;
else
indent--;
}
}
return i;
}
int ifunc_set(interpreter *it);
int ifunc_jmp(interpreter *it);
int ifunc_label(interpreter *it);
int ifunc_end(interpreter *it);
variable *idoexpr(interpreter *interp, const char *line); variable *idoexpr(interpreter *interp, const char *line);
@ -67,11 +115,14 @@ variable *interpreter_get_variable(interpreter *interp, const char *name)
{ {
for (uint32_t i = 0; i < MAX_VARS; i++) { for (uint32_t i = 0; i < MAX_VARS; i++) {
if (!interp->vars[i].used) { if (!interp->vars[i].used) {
interp->vars[i].used = 1; variable *v = &interp->vars[i];
interp->vars[i].valtype = FUNC; v->used = 1;
interp->vars[i].value = 0; v->fromc = 0;
v->valtype = STRING;
v->value = 0;
v->svalue = str_undef;
interp->vnames[i] = strclone(name); interp->vnames[i] = strclone(name);
return &interp->vars[i]; return v;
} else if (interp->vnames[i] != 0 && !strcmp(interp->vnames[i], name)) { } else if (interp->vnames[i] != 0 && !strcmp(interp->vnames[i], name)) {
return &interp->vars[i]; return &interp->vars[i];
} }
@ -85,7 +136,7 @@ char *interpreter_get_name(interpreter *interp, variable *v)
if (v == &interp->vars[i]) if (v == &interp->vars[i])
return interp->vnames[i]; return interp->vnames[i];
} }
return "(undefined)"; return str_undef;
} }
void inew_string(interpreter *interp, const char *name, char *value) void inew_string(interpreter *interp, const char *name, char *value)
@ -93,7 +144,8 @@ void inew_string(interpreter *interp, const char *name, char *value)
variable *v = interpreter_get_variable(interp, name); variable *v = interpreter_get_variable(interp, name);
if (v != 0) { if (v != 0) {
v->valtype = STRING; v->valtype = STRING;
STR(v) = value; INT(v) = 0;
v->svalue = strclone(value);
} }
} }
@ -103,6 +155,7 @@ void inew_integer(interpreter *interp, const char *name, int32_t value)
if (v != 0) { if (v != 0) {
v->valtype = INTEGER; v->valtype = INTEGER;
INT(v) = value; INT(v) = value;
isetstr(v);
} }
} }
@ -112,6 +165,7 @@ void inew_float(interpreter *interp, const char *name, float value)
if (v != 0) { if (v != 0) {
v->valtype = FLOAT; v->valtype = FLOAT;
FLOAT(v) = value; FLOAT(v) = value;
fsetstr(v);
} }
} }
@ -122,24 +176,10 @@ void inew_cfunc(interpreter *interp, const char *name, func_t func)
v->fromc = 1; v->fromc = 1;
v->valtype = FUNC; v->valtype = FUNC;
v->value = (uint32_t)func; v->value = (uint32_t)func;
v->svalue = str_func;
} }
} }
uint8_t eol(int c)
{
return c == '\n' || c == '\0';
}
uint8_t eot(int c)
{
return eol(c) || c == ' ';
}
uint8_t eoe(int c)
{
return eol(c) || c == ')';
}
variable *make_var(interpreter *interp, const char *line, uint32_t *next) variable *make_var(interpreter *interp, const char *line, uint32_t *next)
{ {
if (line[0] == '\"') { // string literal if (line[0] == '\"') { // string literal
@ -150,8 +190,9 @@ variable *make_var(interpreter *interp, const char *line, uint32_t *next)
return 0; return 0;
// TODO string breakdown // TODO string breakdown
variable *v = (variable *)malloc(sizeof(variable)); variable *v = (variable *)malloc(sizeof(variable));
v->used = 0;
v->valtype = STRING; v->valtype = STRING;
STR(v) = strnclone(line + 1, end - 1); v->svalue = strnclone(line + 1, end - 1);
*next = end + 1; *next = end + 1;
return v; return v;
} }
@ -159,17 +200,11 @@ variable *make_var(interpreter *interp, const char *line, uint32_t *next)
} }
return 0; return 0;
} else if (line[0] == '(') { // equation literal } else if (line[0] == '(') { // equation literal
uint32_t end = 1; uint32_t end = findend(line, '(', ')');
while (!eol(line[end])) { if (eot(line[end]))
if (line[end] == ')' && line[end - 1] != '\\') {
if (!eot(line[end + 1]))
return 0; return 0;
// TODO string breakdown
*next = end + 1; *next = end + 1;
return idoexpr(interp, line + 1); return idoexpr(interp, line + 1);
}
end++;
}
} else if (isalpha(line[0])) { // variable/func } else if (isalpha(line[0])) { // variable/func
uint32_t end = 1; uint32_t end = 1;
for (; isalnum(line[end]); end++); for (; isalnum(line[end]); end++);
@ -196,12 +231,15 @@ variable *make_var(interpreter *interp, const char *line, uint32_t *next)
} }
} }
variable *v = (variable *)malloc(sizeof(variable)); variable *v = (variable *)malloc(sizeof(variable));
v->used = 0;
if (dec) { if (dec) {
v->valtype = FLOAT; v->valtype = FLOAT;
FLOAT(v) = strtof(line, 0); FLOAT(v) = strtof(line, 0);
fsetstr(v);
} else { } else {
v->valtype = INTEGER; v->valtype = INTEGER;
INT(v) = atoi(line); INT(v) = atoi(line);
isetstr(v);
} }
*next = end; *next = end;
return v; return v;
@ -216,7 +254,7 @@ int idoline(interpreter *interp, const char *line)
interp->lines[interp->lnidx] = strclone(line); interp->lines[interp->lnidx] = strclone(line);
loop: loop:
if (line[0] == '`') { if (line[0] == '#') {
goto norun; goto norun;
} else if (interp->indent > 0) { } else if (interp->indent > 0) {
if (!strcmp(line, "end")) if (!strcmp(line, "end"))
@ -255,7 +293,9 @@ loop:
ipush(interp, ops[i]); ipush(interp, ops[i]);
if (ops[0]->fromc) { if (ops[0]->fromc) {
((func_t)ops[0]->value)(interp); int ret = ((func_t)ops[0]->value)(interp);
if (ret != 0)
return ret;
} else { } else {
ipush(interp, (void *)(interp->lnidx + 1)); ipush(interp, (void *)(interp->lnidx + 1));
interp->lnidx = ops[0]->value; interp->lnidx = ops[0]->value;
@ -268,6 +308,11 @@ loop:
return -5; return -5;
} }
for (uint32_t i = 0; i < ooffset; i++) {
if (!ops[i]->used)
free(ops[i]);
}
norun: norun:
interp->lnidx++; interp->lnidx++;
if (interp->lines[interp->lnidx] != 0) { if (interp->lines[interp->lnidx] != 0) {
@ -280,9 +325,10 @@ norun:
typedef void (*operation_t)(variable *, variable *, variable *); typedef void (*operation_t)(variable *, variable *, variable *);
#define IOPS_COUNT 9 #define IOPS_COUNT 15
static char *iops[IOPS_COUNT] = { static char *iops[IOPS_COUNT] = {
"+", "-", "*", "/", "&", "|", "^", ">>", "<<" "+", "-", "*", "/", "&", "|", "^", ">>", "<<",
"==", "<", ">", "<=", ">=", "!="
}; };
void iop_add(variable *, variable *, variable *); void iop_add(variable *, variable *, variable *);
@ -294,15 +340,22 @@ void iop_or(variable *, variable *, variable *);
void iop_xor(variable *, variable *, variable *); void iop_xor(variable *, variable *, variable *);
void iop_shr(variable *, variable *, variable *); void iop_shr(variable *, variable *, variable *);
void iop_shl(variable *, variable *, variable *); void iop_shl(variable *, variable *, variable *);
void iop_eq(variable *, variable *, variable *);
void iop_lt(variable *, variable *, variable *);
void iop_gt(variable *, variable *, variable *);
void iop_lte(variable *, variable *, variable *);
void iop_gte(variable *, variable *, variable *);
void iop_ne(variable *, variable *, variable *);
static operation_t iopfuncs[IOPS_COUNT] = { static operation_t iopfuncs[IOPS_COUNT] = {
iop_add, iop_sub, iop_mult, iop_div, iop_and, iop_add, iop_sub, iop_mult, iop_div, iop_and,
iop_or, iop_xor, iop_shr, iop_shl iop_or, iop_xor, iop_shr, iop_shl,
iop_eq, iop_lt, iop_gt, iop_lte, iop_gte, iop_ne
}; };
variable *idoexpr(interpreter *interp, const char *line) variable *idoexpr(interpreter *interp, const char *line)
{ {
static variable result; variable *result = (variable *)malloc(sizeof(variable));
char *mline = line; char *mline = line;
void *ops[16]; void *ops[16];
uint32_t ooffset = 0; uint32_t ooffset = 0;
@ -314,11 +367,28 @@ variable *idoexpr(interpreter *interp, const char *line)
// skip whitespace // skip whitespace
for (; line[offset] == ' ' && !eol(line[offset]); offset++); for (; line[offset] == ' ' && !eol(line[offset]); offset++);
while (!eoe(line[offset])) { while (!eoe(line[offset])) {
if (line[offset] == '(') {
uint8_t indent = 0;
uint32_t i;
for (i = offset + 1; !eol(line[i]); i++) {
if (line[i] == '(') {
indent++;
} else if (line[i] == ')') {
if (indent == 0) {
break;
} else {
indent--;
}
}
}
if (eol(line[i]))
return 0;
ops[ooffset] = idoexpr(interp, line + offset + 1);
offset = i + 1;
} else {
uint32_t end = offset; uint32_t end = offset;
char cend; char cend;
if (line[offset] == '(') { if (line[offset] != '\"') {
} else if (line[offset] != '\"') {
for (; isalnum(line[end]) || line[end] == '.'; end++); for (; isalnum(line[end]) || line[end] == '.'; end++);
cend = line[end]; cend = line[end];
mline[end] = ' '; mline[end] = ' ';
@ -326,6 +396,7 @@ variable *idoexpr(interpreter *interp, const char *line)
ops[ooffset] = make_var(interp, line + offset, &next); ops[ooffset] = make_var(interp, line + offset, &next);
if (end != 0) if (end != 0)
mline[end] = cend; mline[end] = cend;
}
if (ops[ooffset] == 0) if (ops[ooffset] == 0)
return 0; return 0;
@ -357,13 +428,23 @@ variable *idoexpr(interpreter *interp, const char *line)
return 0; return 0;
// step 2 - do operations // step 2 - do operations
result.valtype = ((variable *)ops[0])->valtype; result->valtype = ((variable *)ops[0])->valtype;
result.value = ((variable *)ops[0])->value; result->value = ((variable *)ops[0])->value;
for (uint32_t i = 1; i < ooffset; i += 2) { for (uint32_t i = 1; i < ooffset; i += 2) {
iopfuncs[(uint32_t)ops[i] - 1](&result, &result, ops[i + 1]); iopfuncs[(uint32_t)ops[i] - 1](result, result, ops[i + 1]);
} }
return &result; for (uint32_t i = 0; i < ooffset; i += 2) {
if (!((variable *)ops[i])->used)
free(ops[i]);
}
if (result->valtype == INTEGER)
isetstr(result);
else
fsetstr(result);
return result;
} }
variable *igetarg(interpreter *interp, uint32_t index) variable *igetarg(interpreter *interp, uint32_t index)
@ -376,9 +457,7 @@ char *igetarg_string(interpreter *interp, uint32_t index)
if (index >= interp->stidx) if (index >= interp->stidx)
return 0; return 0;
variable *v = igetarg(interp, index); variable *v = igetarg(interp, index);
if (v->valtype == FUNC) return v->svalue;
return "(func)";
return STR(itostring(v));
} }
int igetarg_integer(interpreter *interp, uint32_t index) int igetarg_integer(interpreter *interp, uint32_t index)
@ -399,24 +478,14 @@ float igetarg_float(interpreter *interp, uint32_t index)
variable *itostring(variable *v) variable *itostring(variable *v)
{ {
char *buf;
switch (v->valtype) { switch (v->valtype) {
case STRING:
break;
case INTEGER: case INTEGER:
buf = (char *)malloc(12);
sprintf(buf, "%d", *((int32_t *)&v->value));
v->valtype = STRING; v->valtype = STRING;
STR(v) = buf; isetstr(v);
break; break;
case FLOAT: case FLOAT:
buf = (char *)malloc(24);
sprintf(buf, "%f", *((float *)&v->value));
v->valtype = STRING; v->valtype = STRING;
STR(v) = buf; fsetstr(v);
break;
case FUNC:
// no
break; break;
} }
return v; return v;
@ -427,15 +496,13 @@ variable *itoint(variable *v)
switch (v->valtype) { switch (v->valtype) {
case STRING: case STRING:
v->valtype = INTEGER; v->valtype = INTEGER;
INT(v) = atoi(STR(v)); INT(v) = atoi(v->svalue);
break; isetstr(v);
case INTEGER:
break; break;
case FLOAT: case FLOAT:
v->valtype = INTEGER; v->valtype = INTEGER;
INT(v) = (int32_t)FLOAT(v); INT(v) = (int32_t)FLOAT(v);
break; isetstr(v);
case FUNC:
break; break;
} }
return v; return v;
@ -446,69 +513,67 @@ variable *itofloat(variable *v)
switch (v->valtype) { switch (v->valtype) {
case STRING: case STRING:
v->valtype = FLOAT; v->valtype = FLOAT;
FLOAT(v) = strtof(STR(v), 0); FLOAT(v) = strtof(v->svalue, 0);
fsetstr(v);
break; break;
case INTEGER: case INTEGER:
v->valtype = FLOAT; v->valtype = FLOAT;
FLOAT(v) = (float)INT(v); FLOAT(v) = (float)INT(v);
break; fsetstr(v);
case FLOAT:
break;
case FUNC:
break; break;
} }
return v; return v;
} }
/*char *iget_string(interpreter *, const char *)
{
}
int iget_integer(interpreter *, const char *)
{
}
float iget_float(interpreter *, const char *)
{
}*/
/** /**
* Builtin functions * Builtin functions
*/ */
void ifunc_set(interpreter *it) int ifunc_set(interpreter *it)
{ {
variable *n = igetarg(it, 0); variable *n = igetarg(it, 0);
variable *v = igetarg(it, 1); variable *v = igetarg(it, 1);
if (n == 0)
return -1;
n->valtype = v->valtype; n->valtype = v->valtype;
n->value = v->value; n->value = v->value;
n->svalue = v->svalue;
return 0;
} }
void ifunc_label(interpreter *it) int ifunc_label(interpreter *it)
{ {
variable *n = igetarg(it, 0); variable *n = igetarg(it, 0);
if (n == 0)
return -1;
n->valtype = FUNC; n->valtype = FUNC;
n->value = it->lnidx; n->value = it->lnidx;
n->svalue = str_func;
it->indent++; it->indent++;
return 0;
} }
void ifunc_end(interpreter *it) int ifunc_end(interpreter *it)
{ {
if (it->stidx > 0) { if (it->stidx > 0) {
uint32_t line = (uint32_t)ipop(it); uint32_t line = (uint32_t)ipop(it);
it->lnidx = line - 1; it->lnidx = line - 1;
} }
return 0;
} }
void ifunc_jmp(interpreter *it) int ifunc_jmp(interpreter *it)
{ {
int newidx = igetarg_integer(it, 0); int newidx = igetarg_integer(it, 0);
ipop(it);
ipush(it, (void *)(it->lnidx + 1));
ipush(it, 0);
it->lnidx = newidx - 1; it->lnidx = newidx - 1;
return 0;
} }
/** /**
@ -593,3 +658,52 @@ void iop_shl(variable *r, variable *a, variable *b)
INT(r) = INT(a) << INT(b); INT(r) = INT(a) << INT(b);
} }
} }
void iop_eq(variable *r, variable *a, variable *b)
{
if (a->valtype == INTEGER && b->valtype == INTEGER)
INT(r) = INT(a) == INT(b);
else
INT(r) = FLOAT(a) == FLOAT(b);
}
void iop_lt(variable *r, variable *a, variable *b)
{
if (a->valtype == INTEGER && b->valtype == INTEGER)
INT(r) = INT(a) < INT(b);
else
INT(r) = FLOAT(a) < FLOAT(b);
}
void iop_gt(variable *r, variable *a, variable *b)
{
if (a->valtype == INTEGER && b->valtype == INTEGER)
INT(r) = INT(a) > INT(b);
else
INT(r) = FLOAT(a) > FLOAT(b);
}
void iop_lte(variable *r, variable *a, variable *b)
{
if (a->valtype == INTEGER && b->valtype == INTEGER)
INT(r) = INT(a) <= INT(b);
else
INT(r) = FLOAT(a) <= FLOAT(b);
}
void iop_gte(variable *r, variable *a, variable *b)
{
if (a->valtype == INTEGER && b->valtype == INTEGER)
INT(r) = INT(a) >= INT(b);
else
INT(r) = FLOAT(a) >= FLOAT(b);
}
void iop_ne(variable *r, variable *a, variable *b)
{
if (a->valtype == INTEGER && b->valtype == INTEGER)
INT(r) = INT(a) != INT(b);
else
INT(r) = FLOAT(a) != FLOAT(b);
}

@ -15,7 +15,7 @@ typedef struct {
uint8_t indent; uint8_t indent;
} interpreter; } interpreter;
typedef void (*func_t)(interpreter *); typedef int (*func_t)(interpreter *);
void iinit(interpreter *); void iinit(interpreter *);
@ -31,8 +31,4 @@ char *igetarg_string(interpreter *, uint32_t);
int igetarg_integer(interpreter *, uint32_t); int igetarg_integer(interpreter *, uint32_t);
float igetarg_float(interpreter *, uint32_t); float igetarg_float(interpreter *, uint32_t);
char *iget_string(interpreter *, const char *);
int iget_integer(interpreter *, const char *);
float iget_float(interpreter *, const char *);
#endif // PARSER_H_ #endif // PARSER_H_

@ -4,15 +4,14 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
void s_put(interpreter *it) int s_put(interpreter *it)
{ {
char *s = igetarg_string(it, 0); char *s = igetarg_string(it, 0);
if (s == 0)
s = "(null)";
printf("%s\n", s); printf("%s\n", s);
return 0;
} }
void s_type(interpreter *it) int s_type(interpreter *it)
{ {
variable *v = (variable *)it->stack[0]; variable *v = (variable *)it->stack[0];
switch (v->valtype) { switch (v->valtype) {
@ -26,18 +25,20 @@ void s_type(interpreter *it)
puts("float"); puts("float");
break; break;
case FUNC: case FUNC:
puts(v->value == 0 ? "undefined" : "func" ); puts("func");
break; break;
default: default:
puts("unknown"); puts("unknown");
break; break;
} }
return 0;
} }
void quit(interpreter *it) int quit(interpreter *it)
{ {
(void)it; (void)it;
exit(0); exit(0);
return 0;
} }
int main() int main()

@ -8,6 +8,7 @@ typedef struct {
uint8_t fromc :1; uint8_t fromc :1;
uint8_t valtype :2; uint8_t valtype :2;
uint32_t value; uint32_t value;
char *svalue;
} variable; } variable;
enum valtype { enum valtype {

Loading…
Cancel
Save