|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
#include "funcs.c"
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
enum {
|
|
|
744572 |
K_NONE = 0,
|
|
|
744572 |
K_POPEN,
|
|
|
744572 |
K_PCLOSE,
|
|
|
744572 |
K_BPOPEN,
|
|
|
744572 |
K_BCLOSE,
|
|
|
744572 |
K_COMMA,
|
|
|
744572 |
K_COLON,
|
|
|
744572 |
};
|
|
|
744572 |
const char *baseKeys[] = { "", "(", ")", "[", "]", ",", ":" };
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
typedef struct Op {
|
|
|
744572 |
const OpDesc *desc;
|
|
|
744572 |
Var v;
|
|
|
744572 |
struct Op *a, *b, *c;
|
|
|
744572 |
} Op;
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
void prepareKeys() {
|
|
|
744572 |
if (keys) return;
|
|
|
744572 |
keys = (const char**)calloc(1, sizeof(baseKeys) + sizeof(char*)*opsCnt);
|
|
|
744572 |
if (!keys) { fprintf(stderr, "out of memory\n"); exit(1); }
|
|
|
744572 |
memcpy(keys, baseKeys, sizeof(baseKeys));
|
|
|
744572 |
keysCnt = sizeof(baseKeys)/sizeof(*baseKeys);
|
|
|
744572 |
|
|
|
744572 |
for(int i = 0; i < opsCnt; ++i) {
|
|
|
744572 |
OpDesc *d = &ops[i];
|
|
|
744572 |
d->k = 0;
|
|
|
744572 |
if (!d->key || !*d->key) continue;
|
|
|
744572 |
for(int j = 1; j < keysCnt; ++j)
|
|
|
744572 |
if (0 == strcmp(keys[j], d->key)) { d->k = j; break; }
|
|
|
744572 |
if (!d->k) {
|
|
|
744572 |
d->k = keysCnt;
|
|
|
744572 |
keys[keysCnt++] = d->key;
|
|
|
744572 |
}
|
|
|
744572 |
}
|
|
|
744572 |
}
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
Op* opCreate(const OpDesc *d) {
|
|
|
744572 |
Op *op = (Op*)calloc(1, sizeof(*op));
|
|
|
744572 |
if (!op) { fprintf(stderr, "out of memory\n"); exit(1); }
|
|
|
744572 |
op->desc = d;
|
|
|
744572 |
return op;
|
|
|
744572 |
}
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
void opDestroy(Op *op) {
|
|
|
744572 |
if (!op) return;
|
|
|
744572 |
opDestroy(op->a);
|
|
|
744572 |
opDestroy(op->b);
|
|
|
744572 |
opDestroy(op->c);
|
|
|
744572 |
free(op);
|
|
|
744572 |
}
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
Var opCall(Op *op, U32 t);
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
Op* opSubItem(Op *op, U32 t, U32 idx) {
|
|
|
744572 |
while(op && op->desc) {
|
|
|
744572 |
if (op->desc->mode == M_ARRAY) {
|
|
|
744572 |
while(op && idx) { op = op->b; --idx; }
|
|
|
744572 |
return op ? op->a : op;
|
|
|
744572 |
} else
|
|
|
744572 |
if (op->desc->mode == M_INDEX) {
|
|
|
744572 |
U32 i = asint(opCall(op->b, t));
|
|
|
744572 |
op = opSubItem(op->a, t, i);
|
|
|
744572 |
} else {
|
|
|
744572 |
return op;
|
|
|
744572 |
}
|
|
|
744572 |
}
|
|
|
744572 |
return NULL;
|
|
|
744572 |
}
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
Var opCall(Op *op, U32 t) {
|
|
|
744572 |
if (!op || !op->desc) return vari(0);
|
|
|
744572 |
if (!op->desc->func) {
|
|
|
744572 |
if (op->desc->mode == M_INDEX) {
|
|
|
744572 |
U32 idx = asint(opCall(op->b, t));
|
|
|
744572 |
Op *o = opSubItem(op->a, t, idx);
|
|
|
744572 |
return opCall(o, t);
|
|
|
744572 |
}
|
|
|
744572 |
if (op->desc->mode == M_ARRAY)
|
|
|
744572 |
return opCall(op->a, t);
|
|
|
744572 |
return op->v;
|
|
|
744572 |
}
|
|
|
744572 |
Params p = { t, opCall(op->a, t), opCall(op->b, t), opCall(op->c, t) };
|
|
|
744572 |
return op->desc->func(p);
|
|
|
744572 |
}
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
void opPrint(Op *op, FILE *f, int level) {
|
|
|
744572 |
if (!f) f = stdout;
|
|
|
744572 |
for(int i = 0; i < level; ++i)
|
|
|
744572 |
fprintf(f, " ");
|
|
|
744572 |
if (!op || !op->desc)
|
|
|
744572 |
{ fprintf(f, "nop\n"); return; }
|
|
|
744572 |
if (!op->desc->func && op->desc->mode != M_ARRAY && op->desc->mode != M_INDEX)
|
|
|
744572 |
{ fprintf(f, "value: %d, %d, %g\n", op->v.type, op->v.u, op->v.f); return; }
|
|
|
744572 |
fprintf(f, "%d:%d:%s:\n", op->desc->mode, op->desc->priority, op->desc->key);
|
|
|
744572 |
++level;
|
|
|
744572 |
opPrint(op->a, f, level);
|
|
|
744572 |
opPrint(op->b, f, level);
|
|
|
744572 |
opPrint(op->c, f, level);
|
|
|
744572 |
}
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
Op* opParsePart(const Lex **l, int priority);
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
Op* opParseParentheses(const Lex **p) {
|
|
|
744572 |
const Lex *l = *p;
|
|
|
744572 |
if (iskey(l++, K_POPEN)) {
|
|
|
744572 |
Op *op = opParsePart(&l, INT_MAX);
|
|
|
744572 |
if (op && iskey(l++, K_PCLOSE))
|
|
|
744572 |
return *p = l, op;
|
|
|
744572 |
opDestroy(op);
|
|
|
744572 |
}
|
|
|
744572 |
return NULL;
|
|
|
744572 |
}
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
Op* opParseValue(const Lex **p, const OpDesc *d) {
|
|
|
744572 |
const Lex *l = *p;
|
|
|
744572 |
if ( d->k ? iskey(l, d->k) : (l->type == LT_INT || l->type == LT_FLOAT) ) {
|
|
|
744572 |
Op *op = opCreate(d);
|
|
|
744572 |
op->v.type = l->type == LT_FLOAT ? T_F32 : T_U32;
|
|
|
744572 |
op->v.u = l->u;
|
|
|
744572 |
return *p = l + 1, op;
|
|
|
744572 |
}
|
|
|
744572 |
return NULL;
|
|
|
744572 |
}
|
|
|
744572 |
|
|
|
744572 |
|
|
|
9e60e5 |
Op* opParseFunc(const Lex **p, const OpDesc *d) {
|
|
|
9e60e5 |
const Lex *l = *p;
|
|
|
9e60e5 |
if (iskey(l++, d->k) && iskey(l++, K_POPEN)) {
|
|
|
9e60e5 |
Op *sub = opParsePart(&l, INT_MAX);
|
|
|
9e60e5 |
if (sub && iskey(l++, K_PCLOSE)) {
|
|
|
9e60e5 |
Op *op = opCreate(d);
|
|
|
9e60e5 |
op->a = sub;
|
|
|
9e60e5 |
return *p = l, op;
|
|
|
9e60e5 |
}
|
|
|
9e60e5 |
opDestroy(sub);
|
|
|
9e60e5 |
}
|
|
|
9e60e5 |
return NULL;
|
|
|
9e60e5 |
}
|
|
|
9e60e5 |
|
|
|
9e60e5 |
|
|
|
9e60e5 |
Op* opParseFunc2(const Lex **p, const OpDesc *d) {
|
|
|
9e60e5 |
const Lex *l = *p;
|
|
|
9e60e5 |
if (iskey(l++, d->k) && iskey(l++, K_POPEN)) {
|
|
|
9e60e5 |
Op *a = opParsePart(&l, INT_MAX);
|
|
|
9e60e5 |
if (a && iskey(l++, K_COMMA)) {
|
|
|
9e60e5 |
Op *b = opParsePart(&l, INT_MAX);
|
|
|
9e60e5 |
if (b && iskey(l++, K_PCLOSE)) {
|
|
|
9e60e5 |
Op *op = opCreate(d);
|
|
|
9e60e5 |
op->a = a;
|
|
|
9e60e5 |
op->b = b;
|
|
|
9e60e5 |
return *p = l, op;
|
|
|
9e60e5 |
}
|
|
|
9e60e5 |
opDestroy(b);
|
|
|
9e60e5 |
}
|
|
|
9e60e5 |
opDestroy(a);
|
|
|
9e60e5 |
}
|
|
|
9e60e5 |
return NULL;
|
|
|
9e60e5 |
}
|
|
|
9e60e5 |
|
|
|
9e60e5 |
|
|
|
744572 |
Op* opParseArray(const Lex **p, const OpDesc *d) {
|
|
|
744572 |
const Lex *l = *p;
|
|
|
744572 |
if (iskey(l++, d->k)) {
|
|
|
744572 |
Op *op = opCreate(d), *o = op;
|
|
|
744572 |
while(1) {
|
|
|
744572 |
o->a = opParsePart(&l, INT_MAX);
|
|
|
744572 |
if (iskey(l, K_BCLOSE)) return *p = l + 1, op;
|
|
|
744572 |
if (!iskey(l++, K_COMMA)) break;
|
|
|
744572 |
o->b = opCreate(d);
|
|
|
744572 |
o = o->b;
|
|
|
744572 |
};
|
|
|
744572 |
opDestroy(op);
|
|
|
744572 |
}
|
|
|
744572 |
return NULL;
|
|
|
744572 |
}
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
Op* opParseIndex(const Lex **p, Op *a, const OpDesc *d) {
|
|
|
744572 |
const Lex *l = *p;
|
|
|
744572 |
if (iskey(l++, d->k)) {
|
|
|
744572 |
Op *b = opParsePart(&l, INT_MAX);
|
|
|
744572 |
if (b && iskey(l++, K_BCLOSE)) {
|
|
|
744572 |
Op *op = opCreate(d);
|
|
|
744572 |
op->a = a;
|
|
|
744572 |
op->b = b;
|
|
|
744572 |
return *p = l, op;
|
|
|
744572 |
}
|
|
|
744572 |
opDestroy(b);
|
|
|
744572 |
}
|
|
|
744572 |
return NULL;
|
|
|
744572 |
}
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
Op* opParsePrefix(const Lex **p, const OpDesc *d) {
|
|
|
744572 |
const Lex *l = *p;
|
|
|
744572 |
if (iskey(l++, d->k)) {
|
|
|
744572 |
Op *sub = opParsePart(&l, d->priority);
|
|
|
744572 |
if (sub) {
|
|
|
744572 |
Op *op = opCreate(d);
|
|
|
744572 |
op->a = sub;
|
|
|
744572 |
return *p = l, op;
|
|
|
744572 |
}
|
|
|
744572 |
}
|
|
|
744572 |
return NULL;
|
|
|
744572 |
}
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
Op* opParseBinary(const Lex **p, Op *a, const OpDesc *d) {
|
|
|
744572 |
const Lex *l = *p;
|
|
|
744572 |
if (iskey(l++, d->k)) {
|
|
|
744572 |
Op *b = opParsePart(&l, d->priority);
|
|
|
744572 |
if (b) {
|
|
|
744572 |
Op *op = opCreate(d);
|
|
|
744572 |
if (b->desc->priority == d->priority) {
|
|
|
744572 |
op->a = a;
|
|
|
744572 |
op->b = b->a;
|
|
|
744572 |
b->a = op;
|
|
|
744572 |
op = b;
|
|
|
744572 |
} else {
|
|
|
744572 |
op->a = a;
|
|
|
744572 |
op->b = b;
|
|
|
744572 |
}
|
|
|
744572 |
return *p = l, op;
|
|
|
744572 |
}
|
|
|
744572 |
}
|
|
|
744572 |
return NULL;
|
|
|
744572 |
}
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
Op* opParseTernary(const Lex **p, Op *a, const OpDesc *d) {
|
|
|
744572 |
const Lex *l = *p;
|
|
|
744572 |
if (iskey(l++, d->k)) {
|
|
|
744572 |
Op *b = opParsePart(&l, d->priority - 1);
|
|
|
744572 |
if (b && iskey(l++, K_COLON)) {
|
|
|
744572 |
Op *c = opParsePart(&l, d->priority);
|
|
|
744572 |
if (c) {
|
|
|
744572 |
Op *op = opCreate(d);
|
|
|
744572 |
op->a = a;
|
|
|
744572 |
op->b = b;
|
|
|
744572 |
op->c = c;
|
|
|
744572 |
return *p = l, op;
|
|
|
744572 |
}
|
|
|
744572 |
}
|
|
|
744572 |
opDestroy(b);
|
|
|
744572 |
}
|
|
|
744572 |
return NULL;
|
|
|
744572 |
}
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
Op* opParsePart(const Lex **p, int priority) {
|
|
|
744572 |
//static int level = 0;
|
|
|
744572 |
//printf("opParsePart:%d:%d:", level, priority);
|
|
|
744572 |
//lexChainPrint(*p, NULL);
|
|
|
744572 |
//printf("\n");
|
|
|
744572 |
//++level;
|
|
|
744572 |
|
|
|
744572 |
const Lex *l = *p;
|
|
|
744572 |
Op *op = opParseParentheses(&l);
|
|
|
744572 |
for(int i = 0; i < opsCnt; ++i) {
|
|
|
744572 |
//printf(" i = %d\n", i);
|
|
|
744572 |
const OpDesc *d = &ops[i];
|
|
|
744572 |
if (d->priority > priority) break;
|
|
|
744572 |
switch(d->mode) {
|
|
|
744572 |
case M_VALUE:
|
|
|
744572 |
if (!op) op = opParseValue(&l, d);
|
|
|
744572 |
break;
|
|
|
9e60e5 |
case M_FUNC:
|
|
|
9e60e5 |
if (!op) op = opParseFunc(&l, d);
|
|
|
9e60e5 |
break;
|
|
|
9e60e5 |
case M_FUNC2:
|
|
|
9e60e5 |
if (!op) op = opParseFunc2(&l, d);
|
|
|
9e60e5 |
break;
|
|
|
744572 |
case M_ARRAY:
|
|
|
744572 |
if (!op) op = opParseArray(&l, d);
|
|
|
744572 |
break;
|
|
|
744572 |
case M_INDEX:
|
|
|
744572 |
if (op) {
|
|
|
744572 |
Op *o = opParseIndex(&l, op, d);
|
|
|
744572 |
if (o) { op = o; i = 0; }
|
|
|
744572 |
}
|
|
|
744572 |
break;
|
|
|
744572 |
case M_PREFIX:
|
|
|
744572 |
if (!op) op = opParsePrefix(&l, d);
|
|
|
744572 |
break;
|
|
|
744572 |
case M_BINARY:
|
|
|
744572 |
if (op) {
|
|
|
744572 |
Op *o = opParseBinary(&l, op, d);
|
|
|
744572 |
if (o) { op = o; i = 0; }
|
|
|
744572 |
}
|
|
|
744572 |
break;
|
|
|
744572 |
case M_TERNARY:
|
|
|
744572 |
if (op) {
|
|
|
744572 |
Op *o = opParseTernary(&l, op, d);
|
|
|
744572 |
if (o) { op = o; i = 0; }
|
|
|
744572 |
}
|
|
|
744572 |
break;
|
|
|
744572 |
}
|
|
|
744572 |
}
|
|
|
744572 |
if (op) *p = l;
|
|
|
744572 |
|
|
|
744572 |
//--level;
|
|
|
744572 |
return op;
|
|
|
744572 |
}
|
|
|
744572 |
|
|
|
744572 |
|
|
|
744572 |
Op* opParse(const Lex *l) {
|
|
|
744572 |
Op *op = opParsePart(&l, INT_MAX);
|
|
|
744572 |
if (!op || l->type != LT_NONE)
|
|
|
744572 |
{ fprintf(stderr, "parse error at: "); lexChainPrint(l, stderr); fprintf(stderr, "\n"); }
|
|
|
744572 |
return op;
|
|
|
744572 |
}
|
|
|
744572 |
|