acl4のプログラムのページ0002

(1) 「式の評価」プログラム

(2) p0002a の実行例

>p0002a "1+2*3"
7.000000

>p0002a "2*(3+4)"
14.000000

(3) p0002a.c [45行]

#define a_Version 1
#include <acl4.c>

double eval(Token0 *t0, int pri)
{
    const char *t = Token1_get(t0); double d = 0.0; uint32_t c = t0->c;
    if (c == '(') { d = eval(t0, 99); Token1_get(t0); goto op2; }
    if (c == '+' && pri >= 2) { d = +       eval(t0, 2); goto op2; }
    if (c == '-' && pri >= 2) { d = -       eval(t0, 2); goto op2; }
    if (c == '!' && pri >= 2) { d = ! (int) eval(t0, 2); goto op2; }
    if (c == '~' && pri >= 2) { d = ~ (int) eval(t0, 2); goto op2; }
    d = strtod(t, NULL);
op2:
    t = Token1_get(t0); c = t0->c;
    if (c ==  '*'             && pri >=  4) { d =       d *        eval(t0,  3); goto op2; }
    if (c ==  '/'             && pri >=  4) { d =       d /        eval(t0,  3); goto op2; }
    if (c ==  '%'             && pri >=  4) { d = (int) d % (int)  eval(t0,  3); goto op2; }
    if (c ==  '+'             && pri >=  5) { d =       d +        eval(t0,  4); goto op2; }
    if (c ==  '-'             && pri >=  5) { d =       d -        eval(t0,  4); goto op2; }
    if (c == ('<' | '<' << 8) && pri >=  6) { d = (int) d << (int) eval(t0,  5); goto op2; }
    if (c == ('>' | '>' << 8) && pri >=  6) { d = (int) d >> (int) eval(t0,  5); goto op2; }
    if (c == ('<' | '=' << 8) && pri >=  7) { d =       d <=       eval(t0,  6); goto op2; }
    if (c ==  '<'             && pri >=  7) { d =       d <        eval(t0,  6); goto op2; }
    if (c == ('>' | '=' << 8) && pri >=  7) { d =       d >=       eval(t0,  6); goto op2; }
    if (c ==  '>'             && pri >=  7) { d =       d >        eval(t0,  6); goto op2; }
    if (c == ('=' | '=' << 8) && pri >=  8) { d =       d ==       eval(t0,  7); goto op2; }
    if (c == ('!' | '=' << 8) && pri >=  8) { d =       d !=       eval(t0,  7); goto op2; }
    if (c ==  '&'             && pri >=  9) { d = (int) d &  (int) eval(t0,  8); goto op2; }
    if (c ==  '^'             && pri >= 10) { d = (int) d ^  (int) eval(t0,  9); goto op2; }
    if (c ==  '|'             && pri >= 11) { d = (int) d |  (int) eval(t0, 10); goto op2; }
    if (c == ('&' | '&' << 8) && pri >= 12) { d = (int) d && (int) eval(t0, 11); goto op2; }
    if (c == ('|' | '|' << 8) && pri >= 13) { d = (int) d || (int) eval(t0, 12); goto op2; }
    t0->s = t; return d; // 一度読み込んだ未解釈の演算子をt0に押し戻してからreturn.
}

int main(int argc, const char **argv)
{
    VecChr vc[1]; VecChr_iniArg(vc, argc, argv, 1, 3);
    Token0 t0[1]; Token0_ini1(t0);
    t0->s = vc->p; t0->s1 = vc->p + vc->n;
    printf("%f\n", eval(t0, 99));
    VecChr_din(vc);
    a_malloc_debugList(_arg);
    return 0;
}

(4) 発展版? (p0002b.c)

(5) p0002b.c [86行]

#define a_Version 1
#include <acl4.c>

class_(Var) { SetElm elm[1]; double d; };
Set0 setVar[1];

double *getVarPtr(const char *s, intptr_t n)
{
    Var *v = Set0_findKn(setVar, s, n);
    if (v == NULL) {
        v = malloc_(_arg_  sizeof (Var));
        v->elm->k = s;
        v->elm->n = n;
        v->d = 0.0;
        Set0_add(setVar, v->elm);
    }
    return &(v->d);
}

int np = 0;

double eval(Token0 *t0, int pri)
{
    const char *t = Token1_get(t0); double d = 0.0, *pd = NULL; uint32_t c = t0->c, n = t0->len;
    if (n == 0) return d;
    if (c == '(') { d = eval(t0, 99); Token1_get(t0); goto op2; }
    if (c == '+' && pri >= 2) { d = +       eval(t0, 2); goto op2; }
    if (c == '-' && pri >= 2) { d = -       eval(t0, 2); goto op2; }
    if (c == '!' && pri >= 2) { d = ! (int) eval(t0, 2); goto op2; }
    if (c == '~' && pri >= 2) { d = ~ (int) eval(t0, 2); goto op2; }
    if (pri >= 2 && n == 3 && memcmp(t, "sin",   3) == 0) { d = sin( eval(t0, 2)); goto op2; }
    if (pri >= 2 && n == 3 && memcmp(t, "cos",   3) == 0) { d = cos( eval(t0, 2)); goto op2; }
    if (pri >= 2 && n == 3 && memcmp(t, "tan",   3) == 0) { d = tan( eval(t0, 2)); goto op2; }
    if (pri >= 2 && n == 3 && memcmp(t, "exp",   3) == 0) { d = exp( eval(t0, 2)); goto op2; }
    if (pri >= 2 && n == 3 && memcmp(t, "log",   3) == 0) { d = log( eval(t0, 2)); goto op2; }
    if (pri >= 2 && n == 4 && memcmp(t, "sqrt",  4) == 0) { d = sqrt(eval(t0, 2)); goto op2; }
    if (pri >= 2 && n == 5 && memcmp(t, "print", 5) == 0) { d = eval(t0, 97); printf("%f\n", d); np++; goto op2; }
    if ('0' <= *t && *t <= '9')
        d = strtod(t, NULL);
    else {
        pd = getVarPtr(t, n);
        d = *pd;
    }
op2:
    t = Token1_get(t0); c = t0->c; n = t0->len;
    if (n == 0) return d;
    if (c ==  '*'             && pri >=  4) { d =       d *        eval(t0,  3); goto op2; }
    if (c ==  '/'             && pri >=  4) { d =       d /        eval(t0,  3); goto op2; }
    if (c ==  '%'             && pri >=  4) { d = (int) d % (int)  eval(t0,  3); goto op2; }
    if (c ==  '+'             && pri >=  5) { d =       d +        eval(t0,  4); goto op2; }
    if (c ==  '-'             && pri >=  5) { d =       d -        eval(t0,  4); goto op2; }
    if (c == ('<' | '<' << 8) && pri >=  6) { d = (int) d << (int) eval(t0,  5); goto op2; }
    if (c == ('>' | '>' << 8) && pri >=  6) { d = (int) d >> (int) eval(t0,  5); goto op2; }
    if (c == ('<' | '=' << 8) && pri >=  7) { d =       d <=       eval(t0,  6); goto op2; }
    if (c ==  '<'             && pri >=  7) { d =       d <        eval(t0,  6); goto op2; }
    if (c == ('>' | '=' << 8) && pri >=  7) { d =       d >=       eval(t0,  6); goto op2; }
    if (c ==  '>'             && pri >=  7) { d =       d >        eval(t0,  6); goto op2; }
    if (c == ('=' | '=' << 8) && pri >=  8) { d =       d ==       eval(t0,  7); goto op2; }
    if (c == ('!' | '=' << 8) && pri >=  8) { d =       d !=       eval(t0,  7); goto op2; }
    if (c ==  '&'             && pri >=  9) { d = (int) d &  (int) eval(t0,  8); goto op2; }
    if (c ==  '^'             && pri >= 10) { d = (int) d ^  (int) eval(t0,  9); goto op2; }
    if (c ==  '|'             && pri >= 11) { d = (int) d |  (int) eval(t0, 10); goto op2; }
    if (c == ('&' | '&' << 8) && pri >= 12) { d = (int) d && (int) eval(t0, 11); goto op2; }
    if (c == ('|' | '|' << 8) && pri >= 13) { d = (int) d || (int) eval(t0, 12); goto op2; }
    if (c == '='              && pri >= 15) { d = eval(t0, 15); if (pd != NULL) { *pd = d; } goto op2; }
    if (c ==  ';'             && pri >= 98) { d =                  eval(t0, 97); goto op2; }
    t0->s = t; return d; // 一度読み込んだ未解釈の演算子をt0に押し戻してからreturn.
}

int main(int argc, const char **argv)
{
    VecChr vc[1]; VecChr_iniArg(vc, argc, argv, 1, 3);
    Token0 t0[1]; Token0_ini1(t0);
    Set0_ini(setVar);
    t0->s = vc->p; t0->s1 = vc->p + vc->n;
    double d = eval(t0, 99);
    if (np == 0)
         printf("%f\n", d);
    VecChr_din(vc);
    intptr_t i, n = setVar->tbl->n / sizeof (Var *);
    for (i = 0; i < n; i++)
        free_(_arg_  ((Var **) setVar->tbl->p)[i], sizeof (Var));
    Set0_din(setVar);
    a_malloc_debugList(_arg);
    return 0;
}

(99) 更新履歴


トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS