summaryrefslogtreecommitdiff
path: root/src/tibeval.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tibeval.c')
-rw-r--r--src/tibeval.c1287
1 files changed, 649 insertions, 638 deletions
diff --git a/src/tibeval.c b/src/tibeval.c
index 3f1f182..364d569 100644
--- a/src/tibeval.c
+++ b/src/tibeval.c
@@ -1,6 +1,6 @@
/*
* libtib - Read, write, and evaluate TI BASIC programs
- * Copyright (C) 2015-2016 Delwink, LLC
+ * Copyright (C) 2015-2017 Delwink, LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -26,787 +26,798 @@
#include "tibvar.h"
enum math_operator_function_type
- {
- T,
- TT
- };
+{
+ T,
+ TT
+};
struct math_operator
{
- union
- {
- TIB *(*t) (const TIB *);
- TIB *(*tt) (const TIB *, const TIB *);
- } func;
+ union
+ {
+ TIB *(*t)(const TIB *);
+ TIB *(*tt)(const TIB *, const TIB *);
+ } func;
- enum math_operator_function_type function_type;
+ enum math_operator_function_type function_type;
- int c;
- int priority;
+ int c;
+ int priority;
};
-static const struct math_operator OPERATORS[] =
- {
- { { .t = tib_factorial }, T, '!', 0 },
- { { .t = tib_toradians }, T, TIB_CHAR_DEGREE, 0 },
- { { .tt = tib_pow }, TT, '^', 1 },
- { { .tt = tib_mul }, TT, '*', 2 },
- { { .tt = tib_div }, TT, '/', 2 },
- { { .tt = tib_add }, TT, '+', 3 },
- { { .tt = tib_sub }, TT, '-', 3 }
- };
+static const struct math_operator OPERATORS[] = {
+ { {.t = tib_factorial }, T, '!', 0},
+ { {.t = tib_toradians }, T, TIB_CHAR_DEGREE, 0},
+ { {.tt = tib_pow }, TT, '^', 1},
+ { {.tt = tib_mul }, TT, '*', 2},
+ { {.tt = tib_div }, TT, '/', 2},
+ { {.tt = tib_add }, TT, '+', 3},
+ { {.tt = tib_sub }, TT, '-', 3}
+};
#define NUM_MATH_OPERATORS (sizeof OPERATORS / sizeof (struct math_operator))
#define LAST_PRIORITY 3
static bool
-is_var_char (int c)
+is_var_char(int c)
{
- return isupper (c) || TIB_CHAR_THETA == c;
+ return isupper(c) || TIB_CHAR_THETA == c;
}
static bool
-needs_mult_common (int c)
+needs_mult_common(int c)
{
- return (isdigit (c) || is_var_char (c) || tib_is_var (c));
+ return (isdigit(c) || is_var_char(c) || tib_is_var(c));
}
static bool
-needs_mult_right (int c)
+needs_mult_right(int c)
{
- return (needs_mult_common (c) || tib_is_func (c));
+ return (needs_mult_common(c) || tib_is_func(c));
}
static bool
-needs_mult_left (int c)
+needs_mult_left(int c)
{
- return (needs_mult_common (c) || ')' == c);
+ return (needs_mult_common(c) || ')' == c);
}
bool
-is_sign_operator (int c)
+is_sign_operator(int c)
{
- return ('+' == c || '-' == c);
+ return ('+' == c || '-' == c);
}
static const struct math_operator *
-get_math_operator (int c)
+get_math_operator(int c)
{
- for (unsigned int i = 0; i < NUM_MATH_OPERATORS; ++i)
- if (OPERATORS[i].c == c)
- return &OPERATORS[i];
+ for (unsigned int i = 0; i < NUM_MATH_OPERATORS; ++i)
+ if (OPERATORS[i].c == c)
+ return &OPERATORS[i];
- return NULL;
+ return NULL;
}
bool
-is_math_operator (int c)
+is_math_operator(int c)
{
- return get_math_operator (c) != NULL;
+ return get_math_operator(c) != NULL;
}
unsigned int
-sign_count (const struct tib_expr *expr)
+sign_count(const struct tib_expr *expr)
{
- int i;
- unsigned int out = 0;
+ int i;
+ unsigned int out = 0;
- tib_expr_foreach (expr, i)
- if (is_sign_operator (expr->data[i]))
- ++out;
+ tib_expr_foreach(expr, i)
+ if (is_sign_operator(expr->data[i]))
+ ++out;
- return out;
+ return out;
}
bool
-contains_i (const struct tib_expr *expr)
+contains_i(const struct tib_expr *expr)
{
- int i;
+ int i;
- tib_expr_foreach (expr, i)
- if ('i' == expr->data[i])
- return true;
+ tib_expr_foreach(expr, i)
+ if ('i' == expr->data[i])
+ return true;
- return false;
+ return false;
}
static int
-replace_epow10 (struct tib_expr *expr)
+replace_epow10(struct tib_expr *expr)
{
- int i;
-
- tib_expr_foreach (expr, i)
- {
- if (TIB_CHAR_EPOW10 == expr->data[i])
- {
- expr->data[i++] = '*';
-
- const char *s = "10^";
- for (; *s != '\0'; ++s, ++i)
- {
- int rc = tib_expr_insert (expr, i, *s);
- if (rc)
- return rc;
- }
- }
- }
-
- return 0;
+ int i;
+
+ tib_expr_foreach(expr, i)
+ {
+ if (TIB_CHAR_EPOW10 == expr->data[i])
+ {
+ expr->data[i++] = '*';
+
+ const char *s = "10^";
+ for (; *s != '\0'; ++s, ++i)
+ {
+ int rc = tib_expr_insert(expr, i, *s);
+ if (rc)
+ return rc;
+ }
+ }
+ }
+
+ return 0;
}
static TIB *
-single_eval (const struct tib_expr *expr)
+single_eval(const struct tib_expr *expr)
{
- int len = expr->len;
-
- if (0 == len)
- return tib_empty ();
-
- if (1 == len && (is_var_char (expr->data[0]) || tib_is_var (expr->data[0])))
- return tib_var_get (expr->data[0]);
-
- int func = tib_eval_surrounded (expr);
- if (func)
- {
- struct tib_expr temp;
- tib_subexpr (&temp, expr, 1, len - 1);
- return tib_call (func, &temp);
- }
-
- if (tib_eval_isnum (expr))
- {
- gsl_complex z;
- tib_errno = tib_expr_parse_complex (expr, &z);
- return tib_errno ? NULL : tib_new_complex (GSL_REAL (z), GSL_IMAG (z));
- }
-
- if (tib_eval_isstr (expr))
- {
- char *s = tib_expr_tostr (expr);
- if (NULL == s)
- return NULL;
-
- TIB *temp = tib_new_str (s);
- free (s);
-
- return temp;
- }
-
- tib_errno = TIB_ESYNTAX;
- return NULL;
+ int len = expr->len;
+
+ if (0 == len)
+ return tib_empty();
+
+ if (1 == len
+ && (is_var_char(expr->data[0]) || tib_is_var(expr->data[0])))
+ return tib_var_get(expr->data[0]);
+
+ int func = tib_eval_surrounded(expr);
+ if (func)
+ {
+ struct tib_expr temp;
+ tib_subexpr(&temp, expr, 1, len - 1);
+ return tib_call(func, &temp);
+ }
+
+ if (tib_eval_isnum(expr))
+ {
+ gsl_complex z;
+ tib_errno = tib_expr_parse_complex(expr, &z);
+ return tib_errno ? NULL : tib_new_complex(GSL_REAL(z),
+ GSL_IMAG(z));
+ }
+
+ if (tib_eval_isstr(expr))
+ {
+ char *s = tib_expr_tostr(expr);
+ if (NULL == s)
+ return NULL;
+
+ TIB *temp = tib_new_str(s);
+ free(s);
+
+ return temp;
+ }
+
+ tib_errno = TIB_ESYNTAX;
+ return NULL;
}
TIB *
-tib_eval (const struct tib_expr *in)
+tib_eval(const struct tib_expr *in)
{
- int i;
-
- if (0 == in->len)
- return tib_empty ();
-
- /* check for store operator */
- i = tib_expr_indexof (in, TIB_CHAR_STO);
- if (i >= 0)
- {
- if (i != in->len - 2 || 0 == i)
- {
- tib_errno = TIB_ESYNTAX;
- return NULL;
- }
-
- int c = in->data[i + 1];
- if (!is_var_char (c))
- {
- tib_errno = TIB_ESYNTAX;
- return NULL;
- }
-
- struct tib_expr e;
- tib_subexpr (&e, in, 0, i);
-
- TIB *stoval = tib_eval (&e);
- if (NULL == stoval)
- return NULL;
-
- tib_errno = tib_var_set (c, stoval);
- if (tib_errno)
- {
- tib_decref (stoval);
- return NULL;
- }
-
- return stoval;
- }
-
- struct tib_expr expr = { .bufsize = 0 };
- tib_errno = tib_exprcpy (&expr, in);
- if (tib_errno)
- return NULL;
-
- /* check for sign operator at the beginning of number */
- if (expr.len > 0 && ('-' == expr.data[0] || '+' == expr.data[0]))
- {
- tib_errno = tib_expr_insert (&expr, 0, '0');
- if (tib_errno)
- {
- tib_expr_destroy (&expr);
- return NULL;
- }
- }
-
- /* check for implicit closing parentheses and close them */
- tib_errno = tib_eval_close_parens (&expr);
- if (tib_errno)
- {
- tib_expr_destroy (&expr);
- return NULL;
- }
-
- /* replace power of 10 E character with "*10^" */
- tib_errno = replace_epow10 (&expr);
- if (tib_errno)
- {
- tib_expr_destroy (&expr);
- return NULL;
- }
-
- /* add multiplication operators between implicit multiplications */
- bool add = true;
- tib_expr_foreach (&expr, i)
- {
- int c = expr.data[i];
-
- if ('"' == c)
- {
- add = !add; /* don't change anything inside a string */
- }
- else if (add)
- {
- if (is_var_char (c) || tib_is_var (c))
- {
- if (i > 0 && needs_mult_left (expr.data[i - 1]))
- tib_errno = tib_expr_insert (&expr, i++, '*');
-
- if (!tib_errno && i < expr.len - 1
- && needs_mult_right (expr.data[i + 1]))
- tib_errno = tib_expr_insert (&expr, ++i, '*');
- }
- else if (i > 0 && i < expr.len - 1)
- {
- if (tib_is_func (c) && needs_mult_left (expr.data[i - 1]))
- tib_errno = tib_expr_insert (&expr, i++, '*');
- else if (')' == c && needs_mult_right (expr.data[i + 1]))
- tib_errno = tib_expr_insert (&expr, ++i, '*');
- }
-
- if (tib_errno)
- {
- tib_expr_destroy (&expr);
- return NULL;
- }
- }
- }
-
- /* this is temp storage for internally-resolved portions */
- struct tib_lst *resolved = tib_new_lst ();
- if (!resolved)
- {
- tib_expr_destroy (&expr);
- tib_errno = TIB_EALLOC;
- return NULL;
- }
-
- /* this is to remember the operations to be executed */
- struct tib_expr calc;
- tib_errno = tib_expr_init (&calc);
- if (tib_errno)
- {
- tib_expr_destroy (&expr);
- tib_free_lst (resolved);
- return NULL;
- }
-
- /* resolve operand expressions, and store the values for later */
- int beg = 0, numpar = 0;
- add = true;
- tib_expr_foreach (&expr, i)
- {
- int c = expr.data[i];
-
- if ('"' == c)
- {
- add = !add;
- continue;
- }
-
- if (!add)
- continue;
-
- if (tib_is_func (c))
- {
- ++numpar;
- }
- else if (')' == c)
- {
- if (0 == numpar)
- {
- tib_errno = TIB_ESYNTAX;
- break;
- }
-
- --numpar;
- }
-
- const struct math_operator *oper;
- if (0 == numpar && (oper = get_math_operator (c)) != NULL)
- {
- struct tib_expr sub;
- tib_subexpr (&sub, &expr, beg, i);
-
- TIB *part = single_eval (&sub);
- if (!part)
- break;
-
- if (T == oper->function_type)
- {
- do
- {
- TIB *temp = oper->func.t (part);
- tib_decref (part);
- if (!temp)
- break;
-
- part = temp;
- }
- while (++i < expr.len
- && (oper = get_math_operator (expr.data[i])) != NULL
- && T == oper->function_type);
-
- if (tib_errno)
- break;
-
- tib_errno = tib_lst_push (resolved, part);
- tib_decref (part);
- if (tib_errno)
- break;
-
- if (i < expr.len)
- {
- c = expr.data[i];
-
- if (is_math_operator (c))
- {
- tib_errno = tib_expr_push (&calc, c);
- if (tib_errno)
- break;
-
- ++i;
- }
- else
- {
- tib_errno = tib_expr_push (&calc, '*');
- if (tib_errno)
- break;
- }
-
- beg = i;
- }
- }
- else
- {
- tib_errno = tib_lst_push (resolved, part);
- tib_decref (part);
- if (tib_errno)
- break;
-
- tib_errno = tib_expr_push (&calc, c);
- if (tib_errno)
- break;
-
- beg = i + 1;
- }
- }
- }
-
- if (!tib_errno)
- {
- const struct math_operator *oper;
-
- if (tib_lst_len (resolved) == 0)
- {
- TIB *temp = single_eval (&expr);
- if (!temp)
- goto end;
-
- tib_errno = tib_lst_push (resolved, temp);
- tib_decref (temp);
- if (tib_errno)
- goto end;
- }
- else if (NULL == (oper = get_math_operator (expr.data[expr.len - 1]))
- || oper->function_type != T)
- {
- struct tib_expr sub;
- tib_subexpr (&sub, &expr, beg, i);
-
- TIB *temp = single_eval (&sub);
- if (!temp)
- goto end;
-
- tib_errno = tib_lst_push (resolved, temp);
- tib_decref (temp);
- if (tib_errno)
- goto end;
- }
-
- if (tib_lst_len (resolved) != calc.len + 1)
- tib_errno = TIB_ESYNTAX;
- }
-
- tib_expr_destroy (&expr);
-
- if (tib_errno)
- goto end;
-
- for (int priority = 1; priority <= LAST_PRIORITY; ++priority)
- {
- for (i = 0; i < calc.len; ++i)
- {
- const struct math_operator *oper = get_math_operator (calc.data[i]);
- if (oper->priority != priority)
- continue;
-
- TIB *t;
- unsigned int num_operands;
- switch (oper->function_type)
- {
- case TT:
- t = oper->func.tt (tib_lst_ref (resolved, i),
- tib_lst_ref (resolved, i + 1));
- if (!t)
- goto end;
-
- num_operands = 2;
- break;
-
- default:
- tib_errno = TIB_ESYNTAX;
- goto end;
- }
-
- for (unsigned int _ = 0; _ < num_operands; ++_)
- tib_lst_remove (resolved, i);
-
- tib_errno = tib_lst_insert (resolved, t, i);
- tib_decref (t);
-
- if (tib_errno)
- goto end;
-
- tib_expr_delete (&calc, i--);
- }
- }
+ int i;
+
+ if (0 == in->len)
+ return tib_empty();
+
+ /* check for store operator */
+ i = tib_expr_indexof(in, TIB_CHAR_STO);
+ if (i >= 0)
+ {
+ if (i != in->len - 2 || 0 == i)
+ {
+ tib_errno = TIB_ESYNTAX;
+ return NULL;
+ }
+
+ int c = in->data[i + 1];
+ if (!is_var_char(c))
+ {
+ tib_errno = TIB_ESYNTAX;
+ return NULL;
+ }
+
+ struct tib_expr e;
+ tib_subexpr(&e, in, 0, i);
+
+ TIB *stoval = tib_eval(&e);
+ if (NULL == stoval)
+ return NULL;
+
+ tib_errno = tib_var_set(c, stoval);
+ if (tib_errno)
+ {
+ tib_decref(stoval);
+ return NULL;
+ }
+
+ return stoval;
+ }
+
+ struct tib_expr expr = {.bufsize = 0 };
+ tib_errno = tib_exprcpy(&expr, in);
+ if (tib_errno)
+ return NULL;
+
+ // check for sign operator at the beginning of number
+ if (expr.len > 0 && ('-' == expr.data[0] || '+' == expr.data[0]))
+ {
+ tib_errno = tib_expr_insert(&expr, 0, '0');
+ if (tib_errno)
+ {
+ tib_expr_destroy(&expr);
+ return NULL;
+ }
+ }
+
+ // check for implicit closing parentheses and close them
+ tib_errno = tib_eval_close_parens(&expr);
+ if (tib_errno)
+ {
+ tib_expr_destroy(&expr);
+ return NULL;
+ }
+
+ // replace power of 10 E character with "*10^"
+ tib_errno = replace_epow10(&expr);
+ if (tib_errno)
+ {
+ tib_expr_destroy(&expr);
+ return NULL;
+ }
+
+ // add multiplication operators between implicit multiplications
+ bool add = true;
+ tib_expr_foreach(&expr, i)
+ {
+ int c = expr.data[i];
+
+ if ('"' == c)
+ {
+ add = !add; // don't change anything inside a string
+ }
+ else if (add)
+ {
+ if (is_var_char(c) || tib_is_var(c))
+ {
+ if (i > 0 && needs_mult_left(expr.data[i - 1]))
+ tib_errno = tib_expr_insert(&expr,
+ i++, '*');
+
+ if (!tib_errno && i < expr.len - 1
+ && needs_mult_right(expr.data[i + 1]))
+ tib_errno = tib_expr_insert(&expr,
+ ++i, '*');
+ }
+ else if (i > 0 && i < expr.len - 1)
+ {
+ if (tib_is_func(c)
+ && needs_mult_left(expr.data[i - 1]))
+ tib_errno = tib_expr_insert(&expr,
+ i++, '*');
+ else if (')' == c
+ && needs_mult_right(expr.data[i + 1]))
+ tib_errno = tib_expr_insert(&expr,
+ ++i, '*');
+ }
+
+ if (tib_errno)
+ {
+ tib_expr_destroy(&expr);
+ return NULL;
+ }
+ }
+ }
+
+ // this is temp storage for internally-resolved portions
+ struct tib_lst *resolved = tib_new_lst();
+ if (!resolved)
+ {
+ tib_expr_destroy(&expr);
+ tib_errno = TIB_EALLOC;
+ return NULL;
+ }
+
+ // this is to remember the operations to be executed
+ struct tib_expr calc;
+ tib_errno = tib_expr_init(&calc);
+ if (tib_errno)
+ {
+ tib_expr_destroy(&expr);
+ tib_free_lst(resolved);
+ return NULL;
+ }
+
+ // resolve operand expressions, and store the values for later
+ int beg = 0, numpar = 0;
+ add = true;
+ tib_expr_foreach(&expr, i)
+ {
+ int c = expr.data[i];
+
+ if ('"' == c)
+ {
+ add = !add;
+ continue;
+ }
+
+ if (!add)
+ continue;
+
+ if (tib_is_func(c))
+ {
+ ++numpar;
+ }
+ else if (')' == c)
+ {
+ if (0 == numpar)
+ {
+ tib_errno = TIB_ESYNTAX;
+ break;
+ }
+
+ --numpar;
+ }
+
+ const struct math_operator *oper;
+ if (0 == numpar && (oper = get_math_operator(c)) != NULL)
+ {
+ struct tib_expr sub;
+ tib_subexpr(&sub, &expr, beg, i);
+
+ TIB *part = single_eval(&sub);
+ if (!part)
+ break;
+
+ if (T == oper->function_type)
+ {
+ do
+ {
+ TIB *temp = oper->func.t(part);
+ tib_decref(part);
+ if (!temp)
+ break;
+
+ part = temp;
+ } while (++i < expr.len
+ && (oper = get_math_operator(expr.data[i])) != NULL
+ && T == oper->function_type);
+
+ if (tib_errno)
+ break;
+
+ tib_errno = tib_lst_push(resolved, part);
+ tib_decref(part);
+ if (tib_errno)
+ break;
+
+ if (i < expr.len)
+ {
+ c = expr.data[i];
+
+ if (is_math_operator(c))
+ {
+ tib_errno = tib_expr_push(&calc,
+ c);
+ if (tib_errno)
+ break;
+
+ ++i;
+ }
+ else
+ {
+ tib_errno = tib_expr_push(&calc,
+ '*');
+ if (tib_errno)
+ break;
+ }
+
+ beg = i;
+ }
+ }
+ else
+ {
+ tib_errno = tib_lst_push(resolved, part);
+ tib_decref(part);
+ if (tib_errno)
+ break;
+
+ tib_errno = tib_expr_push(&calc, c);
+ if (tib_errno)
+ break;
+
+ beg = i + 1;
+ }
+ }
+ }
+
+ if (!tib_errno)
+ {
+ const struct math_operator *oper;
+
+ if (tib_lst_len(resolved) == 0)
+ {
+ TIB *temp = single_eval(&expr);
+ if (!temp)
+ goto end;
+
+ tib_errno = tib_lst_push(resolved, temp);
+ tib_decref(temp);
+ if (tib_errno)
+ goto end;
+ }
+ else if (NULL ==
+ (oper = get_math_operator(expr.data[expr.len - 1]))
+ || oper->function_type != T)
+ {
+ struct tib_expr sub;
+ tib_subexpr(&sub, &expr, beg, i);
+
+ TIB *temp = single_eval(&sub);
+ if (!temp)
+ goto end;
+
+ tib_errno = tib_lst_push(resolved, temp);
+ tib_decref(temp);
+ if (tib_errno)
+ goto end;
+ }
+
+ if (tib_lst_len(resolved) != calc.len + 1)
+ tib_errno = TIB_ESYNTAX;
+ }
+
+ tib_expr_destroy(&expr);
+
+ if (tib_errno)
+ goto end;
+
+ for (int priority = 1; priority <= LAST_PRIORITY; ++priority)
+ {
+ for (i = 0; i < calc.len; ++i)
+ {
+ const struct math_operator *oper =
+ get_math_operator(calc.data[i]);
+ if (oper->priority != priority)
+ continue;
+
+ TIB *t;
+ unsigned int num_operands;
+ switch (oper->function_type)
+ {
+ case TT:
+ t = oper->func.tt(tib_lst_ref(resolved, i),
+ tib_lst_ref(resolved, i + 1));
+ if (!t)
+ goto end;
+
+ num_operands = 2;
+ break;
+
+ default:
+ tib_errno = TIB_ESYNTAX;
+ goto end;
+ }
+
+ for (unsigned int _ = 0; _ < num_operands; ++_)
+ tib_lst_remove(resolved, i);
+
+ tib_errno = tib_lst_insert(resolved, t, i);
+ tib_decref(t);
+
+ if (tib_errno)
+ goto end;
+
+ tib_expr_delete(&calc, i--);
+ }
+ }
end:
- tib_expr_destroy (&calc);
-
- TIB *out = NULL;
- if (!tib_errno)
- {
- if (tib_lst_len (resolved) != 1)
- {
- tib_errno = TIB_ESYNTAX;
- }
- else
- {
- out = tib_lst_ref (resolved, 0);
- tib_incref (out);
- }
- }
-
- tib_free_lst (resolved);
-
- return out;
+ tib_expr_destroy(&calc);
+
+ TIB *out = NULL;
+ if (!tib_errno)
+ {
+ if (tib_lst_len(resolved) != 1)
+ {
+ tib_errno = TIB_ESYNTAX;
+ }
+ else
+ {
+ out = tib_lst_ref(resolved, 0);
+ tib_incref(out);
+ }
+ }
+
+ tib_free_lst(resolved);
+
+ return out;
}
int
-tib_eval_surrounded (const struct tib_expr *expr)
+tib_eval_surrounded(const struct tib_expr *expr)
{
- int count = 0, opening = expr->data[0], len = expr->len;
+ int count = 0, opening = expr->data[0], len = expr->len;
- if (len > 2 && tib_is_func (opening) && ')' == expr->data[len - 1])
- {
- count = 1;
+ if (len > 2 && tib_is_func(opening) && ')' == expr->data[len - 1])
+ {
+ count = 1;
- for (int i = 1; i < len-1; ++i)
- {
- int c = expr->data[i];
+ for (int i = 1; i < len - 1; ++i)
+ {
+ int c = expr->data[i];
- if (tib_is_func (c))
- ++count;
- else if (')' == c && --count == 0)
- return 0;
- }
+ if (tib_is_func(c))
+ ++count;
+ else if (')' == c && --count == 0)
+ return 0;
+ }
- return opening;
- }
+ return opening;
+ }
- return 0;
+ return 0;
}
static int
-char_count (const struct tib_expr *expr, int c)
+char_count(const struct tib_expr *expr, int c)
{
- int i, count = 0;
+ int i, count = 0;
- tib_expr_foreach (expr, i)
- if (c == expr->data[i])
- ++count;
+ tib_expr_foreach(expr, i)
+ if (c == expr->data[i])
+ ++count;
- return count;
+ return count;
}
int
-i_count (const struct tib_expr *expr)
+i_count(const struct tib_expr *expr)
{
- return char_count (expr, 'i');
+ return char_count(expr, 'i');
}
static int
-dot_count (const struct tib_expr *expr)
+dot_count(const struct tib_expr *expr)
{
- return char_count (expr, '.');
+ return char_count(expr, '.');
}
static bool
-is_number_char (int c)
+is_number_char(int c)
{
- return (isdigit (c) || '.' == c || 'i' == c || is_sign_operator (c));
+ return (isdigit(c) || '.' == c || 'i' == c || is_sign_operator(c));
}
int
-get_char_pos (const struct tib_expr *expr, int c, int which)
+get_char_pos(const struct tib_expr *expr, int c, int which)
{
- int i, found = 0;
+ int i, found = 0;
- tib_expr_foreach (expr, i)
- {
- if (c == expr->data[i] && ++found == which)
- break;
- }
+ tib_expr_foreach(expr, i)
+ {
+ if (c == expr->data[i] && ++found == which)
+ break;
+ }
- return i;
+ return i;
}
static int
-get_sign_pos (const struct tib_expr *expr, int which)
+get_sign_pos(const struct tib_expr *expr, int which)
{
- int i, found = 0;
+ int i, found = 0;
- tib_expr_foreach (expr, i)
- {
- if (is_sign_operator (expr->data[i]) && ++found == which)
- break;
- }
+ tib_expr_foreach(expr, i)
+ {
+ if (is_sign_operator(expr->data[i]) && ++found == which)
+ break;
+ }
- return i;
+ return i;
}
static bool
-good_sign_pos (const struct tib_expr *expr, int numsign, int numi)
+good_sign_pos(const struct tib_expr *expr, int numsign, int numi)
{
- switch (numsign)
- {
- case 0:
- return true;
-
- case 1:
- if (!numi && get_sign_pos (expr, 1) != 0)
- return false;
- break;
-
- case 2:
- if (!numi || get_sign_pos (expr, 1) != 0
- || get_sign_pos (expr, 2) > get_char_pos (expr, 'i', 1))
- return false;
- break;
-
- default:
- return false;
- }
-
- return true;
+ switch (numsign)
+ {
+ case 0:
+ return true;
+
+ case 1:
+ if (!numi && get_sign_pos(expr, 1) != 0)
+ return false;
+ break;
+
+ case 2:
+ if (!numi || get_sign_pos(expr, 1) != 0
+ || get_sign_pos(expr, 2) > get_char_pos(expr, 'i', 1))
+ return false;
+ break;
+
+ default:
+ return false;
+ }
+
+ return true;
}
bool
-tib_eval_isnum (const struct tib_expr *expr)
+tib_eval_isnum(const struct tib_expr *expr)
{
- int signs = sign_count (expr);
- int dots = dot_count (expr);
- int is = i_count (expr);
+ int signs = sign_count(expr);
+ int dots = dot_count(expr);
+ int is = i_count(expr);
- if (signs > 2 || dots > 2 || is > 1)
- return false;
+ if (signs > 2 || dots > 2 || is > 1)
+ return false;
- if (!good_sign_pos (expr, signs, is))
- return false;
+ if (!good_sign_pos(expr, signs, is))
+ return false;
- if (is && get_char_pos (expr, 'i', 1) < expr->len - 1)
- return false;
+ if (is && get_char_pos(expr, 'i', 1) < expr->len - 1)
+ return false;
- int i;
- tib_expr_foreach (expr, i)
- if (!is_number_char (expr->data[i]))
- return false;
+ int i;
+ tib_expr_foreach(expr, i)
+ if (!is_number_char(expr->data[i]))
+ return false;
- return true;
+ return true;
}
bool
-tib_eval_isstr (const struct tib_expr *expr)
+tib_eval_isstr(const struct tib_expr *expr)
{
- int len = expr->len;
+ int len = expr->len;
- if (len > 1 && '"' == expr->data[0])
- {
- for (int i = 1; i < len-1; ++i)
- {
- int c = expr->data[i];
+ if (len > 1 && '"' == expr->data[0])
+ {
+ for (int i = 1; i < len - 1; ++i)
+ {
+ int c = expr->data[i];
- if (c > 127 || '"' == c)
- return false;
- }
+ if (c > 127 || '"' == c)
+ return false;
+ }
- return true;
- }
+ return true;
+ }
- return false;
+ return false;
}
bool
-tib_eval_islist (const struct tib_expr *expr)
+tib_eval_islist(const struct tib_expr *expr)
{
- int len = expr->len;
+ int len = expr->len;
- if (len > 2 && '{' == expr->data[0] && '}' == expr->data[len - 1])
- {
- for (int i = 1; i < len-1; ++i)
- {
- int c = expr->data[i];
+ if (len > 2 && '{' == expr->data[0] && '}' == expr->data[len - 1])
+ {
+ for (int i = 1; i < len - 1; ++i)
+ {
+ int c = expr->data[i];
- if ('{' == c || '}' == c)
- return false;
- }
+ if ('{' == c || '}' == c)
+ return false;
+ }
- return true;
- }
+ return true;
+ }
- return false;
+ return false;
}
static bool
-sub_isnum (const struct tib_expr *expr, int beg, int end)
+sub_isnum(const struct tib_expr *expr, int beg, int end)
{
- if (end <= beg)
- return false;
+ if (end <= beg)
+ return false;
- struct tib_expr temp;
- int rc = tib_subexpr (&temp, expr, beg, end);
- if (rc)
- return false;
+ struct tib_expr temp;
+ int rc = tib_subexpr(&temp, expr, beg, end);
+ if (rc)
+ return false;
- return tib_eval_isnum (&temp);
+ return tib_eval_isnum(&temp);
}
bool
-tib_eval_ismatrix (const struct tib_expr *expr)
+tib_eval_ismatrix(const struct tib_expr *expr)
{
- int len = expr->len;
-
- if (len > 4 && '[' == expr->data[0] && '[' == expr->data[1]
- && ']' == expr->data[len - 1])
- {
- int i = 2;
- int open_brackets = i, fdim = 1, dim = 1, beg = i, end = i;
- bool first = true;
-
- for (; i < len; ++i)
- {
- int c = expr->data[i];
-
- switch (c)
- {
- case '[':
- ++open_brackets;
- beg = i + 1;
- break;
-
- case ']':
- --open_brackets;
-
- if (!first && dim != fdim)
- return false;
-
- first = false;
- dim = 1;
- end = i - 1;
-
- if (!sub_isnum (expr, beg, end))
- return false;
- break;
-
- case ',':
- if (first)
- ++fdim;
- else
- ++dim;
-
- end = i - 1;
- if (!sub_isnum (expr, beg, end))
- return false;
- beg = i + 1;
- break;
- }
-
- if ((0 == open_brackets && i != len-1) || open_brackets > 2)
- return false;
- }
-
- return true;
- }
-
- return false;
+ int len = expr->len;
+
+ if (len > 4 && '[' == expr->data[0] && '[' == expr->data[1]
+ && ']' == expr->data[len - 1])
+ {
+ int i = 2;
+ int open_brackets = i, fdim = 1, dim = 1, beg = i, end = i;
+ bool first = true;
+
+ for (; i < len; ++i)
+ {
+ int c = expr->data[i];
+
+ switch (c)
+ {
+ case '[':
+ ++open_brackets;
+ beg = i + 1;
+ break;
+
+ case ']':
+ --open_brackets;
+
+ if (!first && dim != fdim)
+ return false;
+
+ first = false;
+ dim = 1;
+ end = i - 1;
+
+ if (!sub_isnum(expr, beg, end))
+ return false;
+ break;
+
+ case ',':
+ if (first)
+ ++fdim;
+ else
+ ++dim;
+
+ end = i - 1;
+ if (!sub_isnum(expr, beg, end))
+ return false;
+ beg = i + 1;
+ break;
+ }
+
+ if ((0 == open_brackets && i != len - 1)
+ || open_brackets > 2)
+ return false;
+ }
+
+ return true;
+ }
+
+ return false;
}
int
-tib_eval_close_parens (struct tib_expr *expr)
+tib_eval_close_parens(struct tib_expr *expr)
{
- int count = 0, len = expr->len;
- bool str = false;
-
- for (int i = 0; i < len; ++i)
- {
- int c = expr->data[i];
-
- if ('"' == c)
- str = !str;
-
- if (!str)
- {
- if (tib_is_func (c))
- ++count;
-
- if (')' == c)
- --count;
- }
- }
-
- while (count--)
- {
- int rc = tib_expr_push (expr, ')');
- if (rc)
- return rc;
- }
-
- return 0;
+ int count = 0, len = expr->len;
+ bool str = false;
+
+ for (int i = 0; i < len; ++i)
+ {
+ int c = expr->data[i];
+
+ if ('"' == c)
+ str = !str;
+
+ if (!str)
+ {
+ if (tib_is_func(c))
+ ++count;
+
+ if (')' == c)
+ --count;
+ }
+ }
+
+ while (count--)
+ {
+ int rc = tib_expr_push(expr, ')');
+ if (rc)
+ return rc;
+ }
+
+ return 0;
}