[gcalctool/gcalctool-new-parser] Fix more errors
- From: Robert Ancell <rancell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gcalctool/gcalctool-new-parser] Fix more errors
- Date: Sun, 16 Oct 2011 05:38:07 +0000 (UTC)
commit b57887a8256186ec53e09ae5746279be40350b3f
Author: Robert Ancell <robert ancell canonical com>
Date: Sun Oct 16 16:37:49 2011 +1100
Fix more errors
src/mp-equation.c | 299 +++++++++++++++++++++++-------------------------
src/mp.c | 2 +-
src/test-mp-equation.c | 6 +-
3 files changed, 146 insertions(+), 161 deletions(-)
---
diff --git a/src/mp-equation.c b/src/mp-equation.c
index 48cb0a3..46fd8c1 100644
--- a/src/mp-equation.c
+++ b/src/mp-equation.c
@@ -15,6 +15,48 @@
#include "mp-equation.h"
+static gboolean
+unichar_issubdigit(gunichar c)
+{
+ return c >= 0x2080 && c <= 0x2089;
+}
+
+
+static gint
+unichar_subdigit_value(gunichar c)
+{
+ return c - 0x2080;
+}
+
+
+static gboolean
+unichar_issuperdigit(gunichar c)
+{
+ return c == 0x2070 || c == 0x00B9 || c == 0x00B2 || c == 0x00B3 || (c >= 0x2074 && c <= 0x2079);
+}
+
+
+static gboolean
+unichar_isfraction(gunichar c)
+{
+ return c == 0x00BC /* Â */ || c == 0x00BD /* Â */ || c == 0x00BE /* Â */;
+}
+
+
+static gint
+unichar_superdigit_value(gunichar c)
+{
+ if (c == 0x00B9)
+ return 1;
+ else if (c == 0x00B2)
+ return 2;
+ else if (c == 0x00B3)
+ return 3;
+ else
+ return c - 0x2070;
+}
+
+
static int
variable_is_defined(MPEquationOptions *options, const char *name)
{
@@ -60,6 +102,33 @@ set_variable(MPEquationOptions *options, const char *name, const MPNumber *x)
static int
+get_log_base(const char *name)
+{
+ int base = 0;
+ const char *suffix, *i;
+
+ if (!g_str_has_prefix (name, "log"))
+ return 0;
+
+ suffix = name + 3;
+
+ // FIXME: Default to ln
+ if (*suffix == '\0')
+ return 10;
+
+ for (i = suffix; *i; i = g_utf8_next_char(i))
+ {
+ gunichar c = g_utf8_get_char(i);
+ if (!unichar_issubdigit (c))
+ return 0;
+ base = base * 10 + unichar_subdigit_value (c);
+ }
+
+ return base;
+}
+
+
+static int
function_is_defined(MPEquationOptions *options, const char *name)
{
char *c, *lower_name;
@@ -67,9 +136,9 @@ function_is_defined(MPEquationOptions *options, const char *name)
lower_name = strdup(name);
for (c = lower_name; *c; c++)
*c = tolower(*c);
-
+
/* FIXME: Make more generic */
- if (strcmp(lower_name, "log") == 0 ||
+ if (get_log_base (lower_name) ||
strcmp(lower_name, "ln") == 0 ||
strcmp(lower_name, "sqrt") == 0 ||
strcmp(lower_name, "abs") == 0 ||
@@ -106,6 +175,7 @@ get_function(MPEquationOptions *options, const char *name, const MPNumber *x, MP
{
char *c, *lower_name;
int result = 1;
+ int base;
lower_name = strdup(name);
for (c = lower_name; *c; c++)
@@ -113,8 +183,8 @@ get_function(MPEquationOptions *options, const char *name, const MPNumber *x, MP
// FIXME: Re Im ?
- if (strcmp(lower_name, "log") == 0)
- mp_logarithm(10, x, z); // FIXME: Default to ln
+ if ((base = get_log_base (lower_name)))
+ mp_logarithm(base, x, z);
else if (strcmp(lower_name, "ln") == 0)
mp_ln(x, z);
else if (strcmp(lower_name, "sqrt") == 0) // âx
@@ -258,72 +328,35 @@ token_get_string (Token *token)
}
-static gboolean
-unichar_issubdigit(gunichar c)
-{
- return c >= 0x2080 && c <= 0x2089;
-}
-
-
-static gint
-unichar_subdigit_value(gunichar c)
-{
- return c - 0x2080;
-}
-
-
-static gboolean
-unichar_issuperdigit(gunichar c)
-{
- return c == 0x2070 || c == 0x00B9 || c == 0x00B2 || c == 0x00B3 || (c >= 0x2074 && c <= 0x2079);
-}
-
-
-static gboolean
-unichar_isfraction(gunichar c)
-{
- return c == 0x00BC /* Â */ || c == 0x00BD /* Â */ || c == 0x00BE /* Â */;
-}
-
-
static gint
-unichar_superdigit_value(gunichar c)
-{
- if (c == 0x00B9)
- return 1;
- else if (c == 0x00B2)
- return 2;
- else if (c == 0x00B3)
- return 3;
- else
- return c - 0x2070;
-}
-
-
-static int
peek_base(MPEquationOptions *options, const gchar *number)
{
const gchar *i;
+ gunichar c = '\0';
+ int base = 0;
- for (i = number; *i; i = g_utf8_next_char(i)) {
- gunichar c = g_utf8_get_char(i);
-
- if (unichar_issubdigit(c)) {
- int base = 0;
- do
- {
- base = base * 10 + unichar_subdigit_value(c);
- i = g_utf8_next_char(i);
- c = g_utf8_get_char(i);
- } while (unichar_issubdigit(c));
- return base;
- }
-
- if (!g_unichar_isxdigit(c) || c != '.')
+ /* Find the end of the number */
+ for (i = number; *i; i = g_utf8_next_char(i))
+ {
+ c = g_utf8_get_char(i);
+ if (g_unichar_isxdigit(c) || c == '.')
+ continue;
+ else
break;
}
-
- return options->base;
+
+ if (!unichar_issubdigit(c))
+ return options->base;
+
+ /* Convert suffix */
+ do
+ {
+ base = base * 10 + unichar_subdigit_value(c);
+ i = g_utf8_next_char(i);
+ c = g_utf8_get_char(i);
+ } while (unichar_issubdigit(c));
+
+ return base;
}
@@ -332,96 +365,94 @@ parse(MPEquationOptions *options, const gchar *expression, GList **tokens)
{
TokenType current_token = TOKEN_NONE;
const gchar *i, *token_start = NULL;
- int number_base = 0;
*tokens = NULL;
i = expression;
while (TRUE) {
gboolean refeed = FALSE;
gunichar c = g_utf8_get_char(i);
- //g_debug ("%d '%c'", current_token, c);
switch (current_token)
{
case TOKEN_NONE:
token_start = i;
- /* FIXME, check ahead for explicit base */
- if (g_unichar_isxdigit(c) || c == '.' || unichar_isfraction(c))
+ refeed = TRUE;
+ if (g_unichar_isdigit (c) || c == '.')
+ current_token = TOKEN_NUMBER;
+ else if (g_unichar_isxdigit (c) && peek_base (options, i) > g_unichar_xdigit_value (c))
+ current_token = TOKEN_NUMBER;
+ else if (unichar_isfraction(c))
+ current_token = TOKEN_NUMBER;
+ else if (unichar_issuperdigit(c) || c == 0x207B /* â */)
{
- number_base = peek_base(options, i);
- g_debug("base=%d", number_base);
- if (g_unichar_xdigit_value(c) < number_base)
- current_token = TOKEN_NUMBER;
- }
-
- if (unichar_issuperdigit(c) || c == 0x207B /* â */)
current_token = TOKEN_SUPER_NUMBER;
+ refeed = FALSE;
+ }
else if (unichar_issubdigit(c))
current_token = TOKEN_SUB_NUMBER;
else if (g_unichar_isalpha(c))
current_token = TOKEN_VARIABLE;
else if (c == '+')
- *tokens = g_list_append(*tokens, token_new(TOKEN_ADD, i, i));
+ current_token = TOKEN_ADD;
else if (c == '-' || c == 0x2212 /* â */ )
- *tokens = g_list_append(*tokens, token_new(TOKEN_SUBTRACT, i, i));
+ current_token = TOKEN_SUBTRACT;
else if (c == '*' || c == 0x00D7 /* Ã */)
- *tokens = g_list_append(*tokens, token_new(TOKEN_MULTIPLY, i, i));
+ current_token = TOKEN_MULTIPLY;
else if (c == '/' || c == 0x2215 /* â */ || c == 0x00F7 /* Ã */)
- *tokens = g_list_append(*tokens, token_new(TOKEN_DIVIDE, i, i));
+ current_token = TOKEN_DIVIDE;
else if (c == '^')
- *tokens = g_list_append(*tokens, token_new(TOKEN_EXPONENT, i, i));
+ current_token = TOKEN_EXPONENT;
else if (c == 0x221A /* â */)
- *tokens = g_list_append(*tokens, token_new(TOKEN_ROOT, i, i));
+ current_token = TOKEN_ROOT;
else if (c == 0x221B /* â */)
- *tokens = g_list_append(*tokens, token_new(TOKEN_CUBE_ROOT, i, i));
+ current_token = TOKEN_CUBE_ROOT;
else if (c == 0x221C /* â */)
- *tokens = g_list_append(*tokens, token_new(TOKEN_FOURTH_ROOT, i, i));
+ current_token = TOKEN_FOURTH_ROOT;
else if (c == '%')
- *tokens = g_list_append(*tokens, token_new(TOKEN_PERCENTAGE, i, i));
+ current_token = TOKEN_PERCENTAGE;
else if (c == '!')
- *tokens = g_list_append(*tokens, token_new(TOKEN_FACTORIAL, i, i));
+ current_token = TOKEN_FACTORIAL;
else if (c == 0x2227 /* â */)
- *tokens = g_list_append(*tokens, token_new(TOKEN_BOOLEAN_AND, i, i));
+ current_token = TOKEN_BOOLEAN_AND;
else if (c == 0x2228 /* â */)
- *tokens = g_list_append(*tokens, token_new(TOKEN_BOOLEAN_OR, i, i));
+ current_token = TOKEN_BOOLEAN_OR;
else if (c == 0x22BB /* â */ || c == 0x2295 /* â */)
- *tokens = g_list_append(*tokens, token_new(TOKEN_BOOLEAN_XOR, i, i));
+ current_token = TOKEN_BOOLEAN_XOR;
else if (c == '~')
- *tokens = g_list_append(*tokens, token_new(TOKEN_BOOLEAN_NOT, i, i));
+ current_token = TOKEN_BOOLEAN_NOT;
else if (c == 0x22BC /* â */)
- *tokens = g_list_append(*tokens, token_new(TOKEN_BOOLEAN_NAND, i, i));
+ current_token = TOKEN_BOOLEAN_NAND;
else if (c == 0x22BD /* â */)
- *tokens = g_list_append(*tokens, token_new(TOKEN_BOOLEAN_NOR, i, i));
+ current_token = TOKEN_BOOLEAN_NOR;
else if (c == '(')
- *tokens = g_list_append(*tokens, token_new(TOKEN_LEFT_BLOCK, i, i));
+ current_token = TOKEN_LEFT_BLOCK;
else if (c == ')')
- *tokens = g_list_append(*tokens, token_new(TOKEN_RIGHT_BLOCK, i, i));
+ current_token = TOKEN_RIGHT_BLOCK;
else if (c == '|')
- *tokens = g_list_append(*tokens, token_new(TOKEN_ABS_BLOCK, i, i));
+ current_token = TOKEN_ABS_BLOCK;
else if (c == '[')
- *tokens = g_list_append(*tokens, token_new(TOKEN_LEFT_ROUND, i, i));
+ current_token = TOKEN_LEFT_ROUND;
else if (c == ']')
- *tokens = g_list_append(*tokens, token_new(TOKEN_RIGHT_ROUND, i, i));
+ current_token = TOKEN_RIGHT_ROUND;
else if (c == 0x2308 /* â */)
- *tokens = g_list_append(*tokens, token_new(TOKEN_LEFT_CEILING, i, i));
+ current_token = TOKEN_LEFT_CEILING;
else if (c == 0x2309 /* â */)
- *tokens = g_list_append(*tokens, token_new(TOKEN_RIGHT_CEILING, i, i));
+ current_token = TOKEN_RIGHT_CEILING;
else if (c == 0x230A /* â */)
- *tokens = g_list_append(*tokens, token_new(TOKEN_LEFT_FLOOR, i, i));
+ current_token = TOKEN_LEFT_FLOOR;
else if (c == 0x230B /* â */)
- *tokens = g_list_append(*tokens, token_new(TOKEN_RIGHT_FLOOR, i, i));
+ current_token = TOKEN_RIGHT_FLOOR;
else if (c == '{')
- *tokens = g_list_append(*tokens, token_new(TOKEN_LEFT_FRACTION, i, i));
+ current_token = TOKEN_LEFT_FRACTION;
else if (c == '}')
- *tokens = g_list_append(*tokens, token_new(TOKEN_RIGHT_FRACTION, i, i));
+ current_token = TOKEN_RIGHT_FRACTION;
else if (c == ' ')
- ;
+ refeed = FALSE;
else if (c == '\0')
return PARSER_ERR_NONE;
-
- if (current_token == TOKEN_NONE)
+ else
{
- g_debug ("unknown 0x%04X", c);
+ g_debug ("unknown '%c' 0x%04X", c, c);
return PARSER_ERR_INVALID;
}
break;
@@ -435,7 +466,7 @@ parse(MPEquationOptions *options, const gchar *expression, GList **tokens)
}
else if (c == '"') {
}
- else if ((g_unichar_isxdigit(c) && (g_unichar_xdigit_value(c) < number_base)) || unichar_issubdigit(c) || unichar_isfraction(c)) {
+ else if (g_unichar_isxdigit(c) || unichar_issubdigit(c) || unichar_isfraction(c)) {
}
else {
Token *t;
@@ -477,7 +508,7 @@ parse(MPEquationOptions *options, const gchar *expression, GList **tokens)
break;
case TOKEN_VARIABLE:
- if (!g_unichar_isalpha(c)) {
+ if (!g_unichar_isalpha(c) && !unichar_issubdigit(c)) {
gchar *name;
name = g_strdup_printf("%.*s", (int)(i - token_start), token_start);
@@ -548,6 +579,8 @@ parse(MPEquationOptions *options, const gchar *expression, GList **tokens)
break;
default:
+ *tokens = g_list_append(*tokens, token_new(current_token, token_start, i));
+ current_token = TOKEN_NONE;
break;
}
@@ -677,8 +710,6 @@ do_root(GList **first, GList **last, GList *function)
return PARSER_ERR_INVALID;
}
- //g_debug("root %d", n);
-
if (!function->next)
return PARSER_ERR_INVALID;
arg = function->next->data;
@@ -698,7 +729,7 @@ do_function(MPEquationOptions *options, GList **first, GList **last, GList *func
Token *name, *arg;
gchar *string;
MPNumber result;
- int exponent = 1, base = -1;
+ int exponent = 1;
if (!function->next)
return PARSER_ERR_INVALID;
@@ -722,19 +753,6 @@ do_function(MPEquationOptions *options, GList **first, GList **last, GList *func
end = end->next;
arg = end->data;
}
- else if (arg->type == TOKEN_SUB_NUMBER)
- {
- const gchar *i;
-
- base = 0;
- for (i = arg->start; i != arg->end; i = g_utf8_next_char(i))
- base = base * 10 + unichar_subdigit_value(g_utf8_get_char(i));
-
- if (!end->next)
- return PARSER_ERR_INVALID;
- end = end->next;
- arg = end->data;
- }
if (!has_value (arg))
return PARSER_ERR_INVALID;
@@ -749,19 +767,7 @@ do_function(MPEquationOptions *options, GList **first, GList **last, GList *func
else
string = token_get_string(name);
- if (base >= 0) {
- //g_debug ("%s base %d", string, base);
- if (strcmp(string, "log") == 0)
- mp_logarithm(base, &arg->value, &result);
- else {
- g_free(string);
- return PARSER_ERR_INVALID;
- }
- }
- else {
- //g_debug ("function '%s'", string);
- get_function(options, string, &arg->value, &result);
- }
+ get_function(options, string, &arg->value, &result);
g_free(string);
if (exponent != 1)
@@ -789,49 +795,38 @@ do_operation (MPEquationOptions *options, GList **first, GList **last, GList *op
switch (o->type) {
case TOKEN_ADD:
- //g_debug ("+");
mp_add(&a->value, &b->value, &result);
break;
case TOKEN_SUBTRACT:
- //g_debug ("-");
mp_subtract(&a->value, &b->value, &result);
break;
case TOKEN_MULTIPLY:
- //g_debug ("*");
mp_multiply(&a->value, &b->value, &result);
break;
case TOKEN_DIVIDE:
- //g_debug ("/");
mp_divide(&a->value, &b->value, &result);
break;
case TOKEN_MODULUS_DIVIDE:
- //g_debug ("mod");
mp_modulus_divide(&a->value, &b->value, &result);
break;
case TOKEN_EXPONENT:
- //g_debug ("^");
mp_xpowy(&a->value, &b->value, &result);
break;
case TOKEN_BOOLEAN_AND:
- //g_debug ("and");
mp_and(&a->value, &b->value, &result);
break;
case TOKEN_BOOLEAN_OR:
- //g_debug ("or");
mp_or(&a->value, &b->value, &result);
break;
case TOKEN_BOOLEAN_NAND:
- //g_debug ("nand");
mp_and(&a->value, &b->value, &result);
mp_not(&result, options->wordlen, &result);
break;
case TOKEN_BOOLEAN_NOR:
- //g_debug ("nor");
mp_or(&a->value, &b->value, &result);
mp_not(&result, options->wordlen, &result);
break;
case TOKEN_BOOLEAN_XOR:
- //g_debug ("xor");
mp_xor(&a->value, &b->value, &result);
break;
default:
@@ -864,7 +859,6 @@ do_super(GList **first, GList **last, GList *super)
if (g_utf8_get_char(t->start) == 0x207B /* â */)
value = -value;
- //g_debug ("x^%d", value);
t = super->prev->data;
mp_xpowy_integer(&t->value, value, &result);
replace_block(first, last, super->prev, super, &result);
@@ -892,17 +886,12 @@ print_tokens(GList *first, GList *last)
static MPErrorCode
solve(MPEquationOptions *options, GList *first, GList *last, MPNumber *result)
{
- //Token *t_start = first->data, *t_last = last->data;
- //g_debug ("solve '%.*s'", (int) (t_last->end - t_start->start + 1), t_start->start);
-
while (TRUE) {
GList *link;
GList *p_start;
Token *t;
MPErrorCode error;
- //print_tokens (first, last);
-
// FIXME: Make a generic parenthesis style handler
/* Collapse parenthesis */
@@ -913,7 +902,6 @@ solve(MPEquationOptions *options, GList *first, GList *last, MPNumber *result)
// FIXME: Check have a next and disallow ()
- //g_debug ("(");
for (p_end = p_start->next; p_end; p_end = p_end->next) {
Token *t = p_end->data;
if (t->type == TOKEN_LEFT_BLOCK)
@@ -1061,7 +1049,6 @@ solve(MPEquationOptions *options, GList *first, GList *last, MPNumber *result)
return PARSER_ERR_INVALID;
arg = link->next->data;
- //g_debug("invert");
mp_invert_sign(&arg->value, &r);
replace_block(&first, &last, link, link->next, &r);
continue;
@@ -1115,7 +1102,6 @@ solve(MPEquationOptions *options, GList *first, GList *last, MPNumber *result)
}
if (link) {
Token *x = link->next->data;
- //g_debug("plus sign");
replace_block(&first, &last, link, link->next, &x->value);
continue;
}
@@ -1153,7 +1139,6 @@ solve(MPEquationOptions *options, GList *first, GList *last, MPNumber *result)
Token *t = link->data, *t2 = link->next->data;
MPNumber r;
- //g_debug("implied multiply");
mp_multiply(&t->value, &t2->value, &r);
replace_block(&first, &last, link, link->next, &r);
continue;
diff --git a/src/mp.c b/src/mp.c
index 8e9ede6..c49fb06 100644
--- a/src/mp.c
+++ b/src/mp.c
@@ -563,8 +563,8 @@ mp_ceiling(const MPNumber *x, MPNumber *z)
{
MPNumber f;
- mp_floor(x, z);
mp_fractional_component(x, &f);
+ mp_floor(x, z);
if (mp_is_zero(&f))
return;
mp_add_integer(z, 1, z);
diff --git a/src/test-mp-equation.c b/src/test-mp-equation.c
index a046816..dac35ec 100644
--- a/src/test-mp-equation.c
+++ b/src/test-mp-equation.c
@@ -34,14 +34,14 @@ static void fail(const char *format, ...) __attribute__((format(printf, 1, 2)));
static void pass(const char *format, ...)
{
-/* va_list args;
+ /*va_list args;
printf(" PASS: ");
va_start(args, format);
vprintf(format, args);
va_end(args);
- printf("\n");
-*/
+ printf("\n");*/
+
passes += 1;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]