[gcalctool/gcalctool-new-parser] Fix more errors



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]