[gcalctool] Merged parser improvements from gcalctool-newui2 branch



commit 65657629b9d9a170f84b73fabd59368cc844a5eb
Author: Robert Ancell <robert ancell gmail com>
Date:   Sun Jun 28 16:09:03 2009 +1000

    Merged parser improvements from gcalctool-newui2 branch

 src/mp-convert.c         |  184 ++++++++++++++++++++--------------------------
 src/mp-equation-lexer.l  |   68 +++++++++++++----
 src/mp-equation-parser.y |   56 +++++---------
 src/mp-equation.c        |    2 +-
 src/unittest.c           |   37 ++++++---
 5 files changed, 178 insertions(+), 169 deletions(-)
---
diff --git a/src/mp-convert.c b/src/mp-convert.c
index c7d1a3f..4a3512e 100644
--- a/src/mp-convert.c
+++ b/src/mp-convert.c
@@ -479,29 +479,19 @@ mp_cast_to_double(const MPNumber *x)
  * maximum number of digits specified.
  */
 void
-mp_cast_to_string(const MPNumber *MPnumber, int base, int accuracy, int trim_zeroes, char *buffer, int buffer_length)
+mp_cast_to_string(const MPNumber *x, int base, int accuracy, int trim_zeroes, char *buffer, int buffer_length)
 {
     static char digits[] = "0123456789ABCDEF";
-    char *optr, *start, *end, *stopper, *last_non_zero;
     MPNumber number, integer_component, fractional_component, MPbase, temp;
-    int i;
-   
-    optr = buffer;
-    stopper = buffer + buffer_length - 1;
-
-    /* Insert sign */
-    if (mp_is_negative(MPnumber)) {
-        if (optr + strlen("â??") >= stopper) {
-            mperr(_("Number too big to represent"));
-            *optr = '\0';
-            return;
-        }
-        strcpy(optr, "â??");
-        optr += strlen("â??");
-        mp_abs(MPnumber, &number);
-    } else  {
-        mp_set_from_mp(MPnumber, &number);	
-    }
+    int i, last_non_zero;
+    GString *string;
+    
+    string = g_string_sized_new(buffer_length);
+
+    if (mp_is_negative(x))
+        mp_abs(x, &number);
+    else
+        mp_set_from_mp(x, &number);
    
     /* Add rounding factor */
     mp_set_from_integer(base, &MPbase);
@@ -515,7 +505,6 @@ mp_cast_to_string(const MPNumber *MPnumber, int base, int accuracy, int trim_zer
     mp_fractional_component(&number, &fractional_component);  
 
     /* Write out the integer component least significant digit to most */
-    start = optr;
     mp_set_from_mp(&integer_component, &temp);
     do {
         MPNumber t, t2, t3;
@@ -527,29 +516,13 @@ mp_cast_to_string(const MPNumber *MPnumber, int base, int accuracy, int trim_zer
         mp_subtract(&temp, &t2, &t3);
         mp_integer_component(&t3, &t3);
 
-        if (optr == stopper) {
-            mperr(_("Number too big to represent"));
-            *optr = '\0';
-            return;
-        }
-        *optr++ = digits[mp_cast_to_int(&t3)];
+        g_string_prepend_c(string, digits[mp_cast_to_int(&t3)]);
        
         mp_set_from_mp(&t, &temp);
     } while (!mp_is_zero(&temp));
-   
-    /* Reverse digits */
-    end = optr - 1;
-    while(start < end) {
-        char t;
-        t = *start;
-        *start = *end;
-        *end = t;
-        start++;
-        end--;
-    }
-   
-    last_non_zero = optr;
-    *optr++ = '.';
+
+    last_non_zero = string->len;
+    g_string_append_c(string, '.');
    
     /* Write out the fractional component */
     mp_set_from_mp(&fractional_component, &temp);
@@ -561,29 +534,24 @@ mp_cast_to_string(const MPNumber *MPnumber, int base, int accuracy, int trim_zer
         mp_integer_component(&temp, &digit);
         d = mp_cast_to_int(&digit);
        
-        if (optr == stopper) {
-            mperr(_("Number too big to represent"));
-            *optr = '\0';
-            return;
-        }        
-        *optr++ = digits[d];
+        g_string_append_c(string, digits[d]);
 
         if(d != 0)
-            last_non_zero = optr;
+            last_non_zero = string->len;
         mp_subtract(&temp, &digit, &temp);
     }
 
     /* Strip trailing zeroes */
     if (trim_zeroes || accuracy == 0)
-       optr = last_non_zero;
-
-    *optr = '\0';
+        g_string_truncate(string, last_non_zero);
     
     /* Remove negative sign if the number was rounded down to zero */
-    if (strcmp(buffer, "â??0") == 0) {
-        buffer[0] = '0';
-        buffer[1] = '\0';
-    }
+    if (mp_is_negative(x) && strcmp(string->str, "0") != 0)
+        g_string_prepend(string, "â??");
+    
+    // FIXME: Check for truncation
+    strncpy(buffer, string->str, buffer_length);
+    g_string_free(string, TRUE);
 }
 
 
@@ -606,81 +574,93 @@ char_val(char chr, int base)
 }
 
 
-/* Convert string into an MP number, in the given base
- */
+/* Convert string into an MP number */
 void
-mp_set_from_string(const char *str, int base, MPNumber *MPval)
+mp_set_from_string(const char *str, int base, MPNumber *z)
 {
-    const char *optr;
-    int inum;
-    int negate = 0;
-
-    optr = str;
-
-    /* Remove leading whitespace */
-    while (isspace(*optr)) {
-        optr++;
-    }
+    int i, negate = 0;
+    const char *c, *end;
+    const char *fractions[] = {"½", "â??", "â??", "¼", "¾", "â??", "â??", "â??", "â??", "â??", "â??", "â??", "â??", "â??", "â??", NULL};
+    int numerators[]        = { 1,   1,   2,   1,   3,   1,   2,   3,   4,   1,   5,   1,   3,   5,   7};
+    int denominators[]      = { 2,   3,   3,   4,   4,   5,   5,   5,   5,   6,   6,   8,   8,   8,   8};
+    
+    end = str;
+    while (*end != '\0')
+        end++;
 
-    /* Check if this is a negative number. */
-    if (*optr == '-') {
+    /* Check if this is a negative number */
+    c = str;
+    if (*c == '-') {
         negate = 1;
-        optr++;
-    } else if (strncmp(optr, "â??", strlen("â??")) == 0) {
+        c++;
+    } else if (strncmp(c, "â??", strlen("â??")) == 0) {
         negate = 1;
-        optr += strlen("â??");
+        c += strlen("â??");
     }
 
     /* Convert integer part */
-    mp_set_from_integer(0, MPval);
-    while ((inum = char_val(*optr, base)) >= 0) {
-        mp_multiply_integer(MPval, base, MPval);
-        mp_add_integer(MPval, inum, MPval);
-        optr++;
+    mp_set_from_integer(0, z);
+    while ((i = char_val(*c, base)) >= 0) {
+        mp_multiply_integer(z, base, z);
+        mp_add_integer(z, i, z);
+        c++;
+    }
+    
+    /* Look for fraction characters */
+    for (i = 0; fractions[i] != NULL; i++) {
+        if (end - strlen(fractions[i]) < str)
+            continue;
+        if (strcmp(end - strlen(fractions[i]), fractions[i]) == 0)
+            break;
+    }
+    if (fractions[i] != NULL) {
+        MPNumber fraction;
+        mp_set_from_fraction(numerators[i], denominators[i], &fraction);
+        mp_add(z, &fraction, z);
     }
    
     /* Convert fractional part */
-    if (*optr == '.') {
+    if (*c == '.') {
         MPNumber numerator, denominator;
        
-        optr++;
+        c++;
 
         mp_set_from_integer(0, &numerator);
         mp_set_from_integer(1, &denominator);
-        while ((inum = char_val(*optr, base)) >= 0) {
+        while ((i = char_val(*c, base)) >= 0) {
             mp_multiply_integer(&denominator, base, &denominator);
             mp_multiply_integer(&numerator, base, &numerator);
-            mp_add_integer(&numerator, inum, &numerator);
-            optr++;
+            mp_add_integer(&numerator, i, &numerator);
+            c++;
         }
         mp_divide(&numerator, &denominator, &numerator);
-        mp_add(MPval, &numerator, MPval);
+        mp_add(z, &numerator, z);
     }
    
     /* Convert exponential part */
-    if (*optr == 'e' || *optr == 'E') {
+    if (*c == 'e' || *c == 'E') {
         int negate = 0;
         MPNumber MPbase, MPexponent, temp;
 
-        optr++;       
+        c++;
 
         /* Get sign */
-        if (*optr == '-') {
+        if (*c == '-') {
             negate = 1;
-            optr++;
-        } else if (strncmp(optr, "â??", strlen("â??")) == 0) {
+            c++;
+        } else if (strncmp(c, "â??", strlen("â??")) == 0) {
             negate = 1;
-            optr += strlen("â??");
-        } else if (*optr == '+') {
-            optr++;
+            c += strlen("â??");
+        } else if (*c == '+') {
+            c++;
         }
 
         /* Get magnitude */
         mp_set_from_integer(0, &MPexponent);
-        while ((inum = char_val(*optr, base)) >= 0) {
+        while ((i = char_val(*c, base)) >= 0) {
             mp_multiply_integer(&MPexponent, base, &MPexponent);
-            mp_add_integer(&MPexponent, inum, &MPexponent);
-            optr++;
+            mp_add_integer(&MPexponent, i, &MPexponent);
+            c++;
         }
         if (negate) {
             mp_invert_sign(&MPexponent, &MPexponent);
@@ -688,19 +668,13 @@ mp_set_from_string(const char *str, int base, MPNumber *MPval)
 
         mp_set_from_integer(base, &MPbase);       
         mp_pwr(&MPbase, &MPexponent, &temp);
-        mp_multiply(MPval, &temp, MPval);
-    }
-
-    /* Strip trailing whitespace */
-    while (isspace(*optr)) {
-        optr++;
+        mp_multiply(z, &temp, z);
     }
    
-    if (*optr != '\0') {
+    if (c != end) {
        // FIXME: Error decoding
     }
  
-    if (negate == 1) {
-        mp_invert_sign(MPval, MPval);
-    }
+    if (negate == 1)
+        mp_invert_sign(z, z);
 }
diff --git a/src/mp-equation-lexer.l b/src/mp-equation-lexer.l
index 3c1a971..d6e35be 100644
--- a/src/mp-equation-lexer.l
+++ b/src/mp-equation-lexer.l
@@ -10,6 +10,7 @@
 /*  $Header: /cvs/gnome/gcalctool/gcalctool/ce_tokeniser.l,v 1.16 2006/12/15 15:27:37 richb Exp $
  *
  *  Copyright (C) 2004-2008 Sami Pietila
+ *  Copyright (C) 2008-2009 Robert Ancell
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -35,19 +36,56 @@
 #include "calctool.h"
 #include "mp-equation.h"
 #include "mp-equation-parser.h"
+
+static int super_atoi(const char *data)
+{
+   int i, value = 0;
+   const char *digits[11] = {"�", "¹", "²", "³", "�", "�", "�", "�", "�", "�", NULL};
+   
+   while(*data != '\0') {
+      for(i = 0; digits[i] != NULL && strncmp(data, digits[i], strlen(digits[i])) != 0; i++);
+      if(digits[i] == NULL)
+         return 0;
+      value = value * 10 + i;
+      data += strlen(digits[i]);
+   }
+   
+   return value;
+}
+
+static int sub_atoi(const char *data)
+{
+   int i, value = 0;
+   const char *digits[11] = {"â??", "â??", "â??", "â??", "â??", "â??", "â??", "â??", "â??", "â??", NULL};
+
+   while(*data != '\0') {
+      for(i = 0; digits[i] != NULL && strncmp(data, digits[i], strlen(digits[i])) != 0; i++);
+      if(digits[i] == NULL)
+         return 0;
+      data += strlen(digits[i]);
+      value = value * 10 + i;
+   }
+   
+   return value;
+}
 %}
 
-DECIMAL	"."|","
-SIGN	"+"|"-"|"â??"
-BIN     [0-1]
-OCT     [0-7]
-DEC     [0-9]
-HEX     [0-9]|[A-F]|[a-f]
-EXP     "e"|"e+"|"e-"|"E"|"E+"|"E-"
-HEX_NUM {HEX}+|{HEX}*{DECIMAL}{HEX}*
-DEC_NUM{DEC}+|{DEC}*{DECIMAL}{DEC}*
-OCT_NUM{OCT}+|{OCT}*{DECIMAL}{OCT}*
-BIN_NUM{BIN}+|{BIN}*{DECIMAL}{BIN}*
+DECIMAL	     "."|","
+BIN          [0-1]
+OCT          [0-7]
+DEC          [0-9]
+HEX          [0-9]|[A-F]|[a-f]
+EXP          "e"|"e+"|"e-"|"E"|"E+"|"E-"
+SUPER_DIGITS "�"|"¹"|"²"|"³"|"�"|"�"|"�"|"�"|"�"|"�"
+SUB_DIGITS   "â??"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"
+FRACTION     "½"|"â??"|"â??"|"¼"|"¾"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"
+
+HEX_NUM {HEX}+|{HEX}*{DECIMAL}{HEX}+
+DEC_NUM {DEC}+|{DEC}*{DECIMAL}{DEC}+|{FRACTION}|{DEC}{FRACTION}
+OCT_NUM {OCT}+|{OCT}*{DECIMAL}{OCT}+
+BIN_NUM {BIN}+|{BIN}*{DECIMAL}{BIN}+
+SUP_NUM {SUPER_DIGITS}+
+SUB_NUM {SUB_DIGITS}+
 
 %%
 
@@ -77,8 +115,7 @@ BIN_NUM{BIN}+|{BIN}*{DECIMAL}{BIN}*
 "frac"|"Frac"|"FRAC" {return tFRAC;}
 "int"|"Int"|"INT" {return tINT;}
 "ln"|"Ln"|"LN" {return tLN;}
-"log"|"Log"|"LOG" {return tLOG10;}
-"logâ??"|"Logâ??"|"log_2"|"Log_2"|"LOG_2" {return tLOG2;}
+"log"|"Log"|"LOG" {return tLOG;}
 "mod"|"Mod"|"MOD" {return tMOD;}
 "¬"|"~" {return tNOT;}
 "â?¨"|"or"|"Or"|"OR" {return tOR;}
@@ -88,8 +125,6 @@ BIN_NUM{BIN}+|{BIN}*{DECIMAL}{BIN}*
 "â??"|"sqrt"|"Sqrt"|"SQRT" {return tROOT;}
 "â??"|"cbrt"|"Cbrt"|"CBRT" {return tROOT3;}
 "â??" {return tROOT4;}
-"²" {return tSQUARED;}
-"³" {return tCUBED;}
 "sto"|"Sto"|"STO" {return tSTO;}
 "trunc"|"Trunc"|"TRUNC" {return tTRUNC;}
 "ones" {return t1S;}
@@ -102,6 +137,9 @@ yylval->integer = atoi(yytext+1);
 return tREG;
 }
 
+{SUP_NUM} { yylval->integer = super_atoi(yytext); return tSUPNUM; }
+{SUB_NUM} { yylval->integer = sub_atoi(yytext); return tSUBNUM; }
+
 {DEC_NUM}{EXP}{DEC_NUM} {
 if (_mp_equation_get_extra(yyscanner)->base == 16) REJECT;
 if (strlen(yytext) > MAX_DIGITS) yyextra->error = -PARSER_ERR_TOO_LONG_NUMBER;
diff --git a/src/mp-equation-parser.y b/src/mp-equation-parser.y
index a8c6976..e14b8c7 100644
--- a/src/mp-equation-parser.y
+++ b/src/mp-equation-parser.y
@@ -3,6 +3,7 @@
 /*  $Header: /cvs/gnome/gcalctool/gcalctool/ce_parser.y,v 1.16 2006/12/08 15:54:43 richb Exp $
  *
  *  Copyright (C) 2004-2008 Sami Pietila
+ *  Copyright (C) 2008-2009 Robert Ancell
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -65,8 +66,7 @@
 %token tFRAC
 %token tINT
 %token tLN
-%token tLOG10
-%token tLOG2
+%token tLOG
 %token tMOD
 %token t1S
 %token t2S
@@ -80,8 +80,6 @@
 %token tROOT
 %token tROOT3
 %token tROOT4
-%token tSQUARED
-%token tCUBED
 %token tSQRT
 %token tSTO
 %token tTAN
@@ -91,11 +89,11 @@
 %token tXOR
 
 %token <int_t> tNUMBER
-%token <integer> tREG
+%token <integer> tREG tSUBNUM tSUPNUM
 
 %token NEG
 
-%type  <int_t> exp rcl value term reg func number parenthesis
+%type  <int_t> exp rcl value term func number
 
 %start statement
 %left tADD tSUBTRACT tMULTIPLY tDIVIDE
@@ -148,17 +146,13 @@ value:
 
 exp: 
   term {mp_set_from_mp(&$1, &$$);}
-
 | exp tADD term '%' {mp_add_integer(&$3, 100, &$3); mp_divide_integer(&$3, 100, &$3); mp_multiply(&$1, &$3, &$$);}
 | exp tSUBTRACT term '%' {mp_add_integer(&$3, -100, &$3); mp_divide_integer(&$3, -100, &$3); mp_multiply(&$1, &$3, &$$);}
-
 | exp tROOT term {MPNumber t; mp_sqrt(&$3, &t); mp_multiply(&$1, &t, &$$);}
 | exp tROOT3 term {MPNumber t; mp_root(&$3, 3, &t); mp_multiply(&$1, &t, &$$);}
 | exp tROOT4 term {MPNumber t; mp_root(&$3, 4, &t); mp_multiply(&$1, &t, &$$);}
-
 | exp tADD exp {mp_add(&$1, &$3, &$$);}
 | exp tSUBTRACT exp {mp_subtract(&$1, &$3, &$$);}
-
 | exp tMOD exp %prec MED {
     if (!mp_is_integer(&$1) || !mp_is_integer(&$3)) {
 	(_mp_equation_get_extra(yyscanner))->error = -PARSER_ERR_MODULUSOP;
@@ -168,7 +162,6 @@ exp:
       }			   
     }
 }
-
 | exp tAND exp {
     if (!mp_is_natural(&$1) || !mp_is_natural(&$3)) {
 	(_mp_equation_get_extra(yyscanner))->error = -PARSER_ERR_BITWISEOP;
@@ -200,16 +193,16 @@ term:
   number {mp_set_from_mp(&$1, &$$);}
 | tPI {mp_get_pi(&$$);}
 | rcl {mp_set_from_mp(&$1, &$$);}
+| tSUBNUM tROOT term {mp_root(&$3, $1, &$$);}
 | tROOT term {mp_sqrt(&$2, &$$);}
 | tROOT3 term {mp_root(&$2, 3, &$$);}
 | tROOT4 term {mp_root(&$2, 4, &$$);}
 | term tDIVIDE term {mp_divide(&$1, &$3, &$$);}
 | term tMULTIPLY term {mp_multiply(&$1, &$3, &$$);}
-| tABS exp tABS {mp_abs(&$2, &$$);} 
+| tABS exp tABS {mp_abs(&$2, &$$);}
 | 'e' '^' term {mp_epowy(&$3, &$$);} 
 | term '!' {mp_factorial(&$1, &$$);}
-| term tSQUARED {mp_pwr_integer(&$1, 2, &$$);}
-| term tCUBED {mp_pwr_integer(&$1, 3, &$$);}
+| term tSUPNUM {mp_pwr_integer(&$1, $2, &$$);}
 | term '%' {mp_divide_integer(&$1, 100, &$$);}
 | tNOT term %prec LNEG {
     if (!mp_is_natural(&$2)) {
@@ -219,49 +212,42 @@ term:
     }
     mp_not(&$2, _mp_equation_get_extra(yyscanner)->wordlen, &$$);
 }
-| tSUBTRACT term %prec NEG {mp_invert_sign(&$2, &$$);}
-| tADD term %prec POS {mp_set_from_mp(&$2, &$$);}
+| tSUBTRACT term {mp_invert_sign(&$2, &$$);}
+| tADD term {mp_set_from_mp(&$2, &$$);}
 | term '^' term {mp_xpowy(&$1, &$3, &$$);}
-
 | term func {mp_multiply(&$1, &$2, &$$);}
 | func {mp_set_from_mp(&$1, &$$);}
-| reg {mp_set_from_mp(&$1, &$$);}
-
-| parenthesis {mp_set_from_mp(&$1, &$$);}
+| tREG {register_get($1, &$$);}
+| '(' exp ')' {mp_set_from_mp(&$2, &$$);}
 ;
 
-parenthesis:
-  '(' exp ')' {mp_set_from_mp(&$2, &$$);}
-  ;
-
-reg: 
-  tREG {register_get($1, &$$);}
-  ;
-
 func:
-  tLOG10 term %prec HIGH {mp_logarithm(10, &$2, &$$);}
-| tLOG2 term %prec HIGH {mp_logarithm(2, &$2, &$$);}
-| tSQRT term %prec HIGH {mp_sqrt(&$2, &$$);}
+  tLOG term %prec HIGH {mp_logarithm(10, &$2, &$$);}
 | tLN term %prec HIGH {mp_ln(&$2, &$$);}
+| tLOG tSUBNUM term %prec HIGH {mp_logarithm($2, &$3, &$$);}
 | tRAND %prec HIGH {mp_set_from_random(&$$);}
 | tABS_FUNC term %prec HIGH {mp_abs(&$2, &$$);}
 | tFRAC term %prec HIGH {mp_fractional_component(&$2, &$$);}
 | tINT term %prec HIGH {mp_integer_component(&$2, &$$);}
 | tCHS term %prec HIGH {mp_invert_sign(&$2, &$$);}
-
 | tSIN term %prec HIGH {mp_sin(&$2, _mp_equation_get_extra(yyscanner)->angle_units, &$$);}
 | tCOS term %prec HIGH {mp_cos(&$2, _mp_equation_get_extra(yyscanner)->angle_units, &$$);}
 | tTAN term %prec HIGH {mp_tan(&$2, _mp_equation_get_extra(yyscanner)->angle_units, &$$);}
+| tSIN tSUPNUM term %prec HIGH {MPNumber t; mp_sin(&$3, _mp_equation_get_extra(yyscanner)->angle_units, &t); mp_pwr_integer(&t, $2, &$$);}
+| tCOS tSUPNUM term %prec HIGH {MPNumber t; mp_cos(&$3, _mp_equation_get_extra(yyscanner)->angle_units, &t); mp_pwr_integer(&t, $2, &$$);}
+| tTAN tSUPNUM term %prec HIGH {MPNumber t; mp_tan(&$3, _mp_equation_get_extra(yyscanner)->angle_units, &t); mp_pwr_integer(&t, $2, &$$);}
 | tASIN term %prec HIGH {mp_asin(&$2, _mp_equation_get_extra(yyscanner)->angle_units, &$$);}
 | tACOS term %prec HIGH {mp_acos(&$2, _mp_equation_get_extra(yyscanner)->angle_units, &$$);}
 | tATAN term %prec HIGH {mp_atan(&$2, _mp_equation_get_extra(yyscanner)->angle_units, &$$);}
 | tSINH term %prec HIGH {mp_sinh(&$2, &$$);}
 | tCOSH term %prec HIGH {mp_cosh(&$2, &$$);}
 | tTANH term %prec HIGH {mp_tanh(&$2, &$$);}
+| tSINH tSUPNUM term %prec HIGH {MPNumber t; mp_sinh(&$3, &t); mp_pwr_integer(&t, $2, &$$);}
+| tCOSH tSUPNUM term %prec HIGH {MPNumber t; mp_cosh(&$3, &t); mp_pwr_integer(&t, $2, &$$);}
+| tTANH tSUPNUM term %prec HIGH {MPNumber t; mp_tanh(&$3, &t); mp_pwr_integer(&t, $2, &$$);}
 | tASINH term %prec HIGH {mp_asinh(&$2, &$$);}
 | tACOSH term %prec HIGH {mp_acosh(&$2, &$$);}
 | tATANH term %prec HIGH {mp_atanh(&$2, &$$);}
-
 | tTRUNC term %prec HIGH {mp_mask(&$2, _mp_equation_get_extra(yyscanner)->wordlen, &$$);}
 | t1S term %prec HIGH  {
     if (!mp_is_natural(&$2)) {
@@ -290,9 +276,7 @@ rcl:
 
 number:
   tNUMBER {mp_set_from_mp(&$1, &$$);}
-| tANS {
-  mp_set_from_mp(&_mp_equation_get_extra(yyscanner)->ans, &$$);
-}
+| tANS {mp_set_from_mp(&_mp_equation_get_extra(yyscanner)->ans, &$$);}
 ;
 
 %%
diff --git a/src/mp-equation.c b/src/mp-equation.c
index e5b3e9b..b93427c 100644
--- a/src/mp-equation.c
+++ b/src/mp-equation.c
@@ -43,7 +43,7 @@ mp_equation_parse_(const char *expression, MPNumber *result, int need_result)
     state.angle_units = v->ttype;
     mp_set_from_mp(display_get_answer(&v->display), &state.ans);
     v->math_error = 0;
-        
+
     _mp_equation_lex_init_extra(&state, &yyscanner);
     buffer = _mp_equation__scan_string(expression, yyscanner);
 
diff --git a/src/unittest.c b/src/unittest.c
index 58278e0..5271ed2 100644
--- a/src/unittest.c
+++ b/src/unittest.c
@@ -97,7 +97,7 @@ test_parser()
     v->ttype = MP_DEGREES;
     v->wordlen = 32;
     v->accuracy = 9;
-
+    
     test("0", "0", 0);
     test("1", "1", 0);
     test("+1", "1", 0);
@@ -105,12 +105,12 @@ test_parser()
     test("â??â??1", "1", 0);
     test("255", "255", 0);
     test("256", "256", 0);
+    test("½", "0.5", 0);
+    test("1½", "1.5", 0);    
     test("1.00", "1", 0);
     test("1.01", "1.01", 0);
     test("Ï?", "3.141592654", 0);
-    test("1e3", "1000", 0);
-    test("1e+3", "1000", 0);
-    test("1e-3", "0.001", 0);
+    test("e^1", "2.718281828", 0);
 
     test("0+0", "0", 0);
     test("1+1", "2", 0);
@@ -130,6 +130,12 @@ test_parser()
     test("â??2Ã?3", "â??6", 0);
     test("2Ã?â??3", "â??6", 0);
     test("â??2Ã?â??3", "6", 0);
+    
+    test("2e3", "2000", 0);
+    test("2e+3", "2000", 0);
+    test("2e-3", "0.002", 0);
+    test("2Ã?10^3", "2000", 0);
+    test("2Ã?10^â??3", "0.002", 0);
 
     test("6/3", "2", 0);
     test("6÷3", "2", 0);
@@ -168,6 +174,7 @@ test_parser()
 
     test("2²", "4", 0);
     test("2³", "8", 0);
+    test("2¹�", "1024", 0);
     test("2^0", "1", 0);
     test("2^1", "2", 0);
     test("2^2", "4", 0);
@@ -183,6 +190,8 @@ test_parser()
     test("â??4â??2", "0", 0);
     test("â??8", "2", 0);
     test("â??16", "2", 0);
+    test("â??â??8", "2", 0);
+    test("â??â??â??1024", "2", 0);
     test("â??(2+2)", "2", 0);
     test("2â??4", "4", 0);
     test("2Ã?â??4", "4", 0);
@@ -231,6 +240,7 @@ test_parser()
     test("sin 90", "1", 0);
     test("sin 180", "0", 0);
     test("2 sin 90", "2", 0);
+    test("sin²45", "0.5", 0);
    
     test("cos 0", "1", 0);
     test("cos 45 â?? 1÷â??2", "0", 0);
@@ -238,10 +248,13 @@ test_parser()
     test("cos 90", "0", 0);
     test("cos 180", "â??1", 0);
     test("2 cos 0", "2", 0);
+    test("cos²45", "0.5", 0);
 
     test("tan 0", "0", 0);
     test("tan 10 â?? sin 10÷cos 10", "0", 0);
     test("tan 90", "", -20001);
+    test("tan 10", "0.176326981", 0);    
+    test("tan²10", "0.031091204", 0);
 
     test("cos�¹ 0", "90", 0);
     test("cos�¹ 1", "0", 0);
@@ -254,15 +267,15 @@ test_parser()
     test("sinâ?»Â¹ (1÷â??2)", "45", 0);
 
     test("cosh 0", "1", 0);
-    test("cosh 10 â?? (e^(10)+e^(â??10))÷2", "0", 0);
+    test("cosh 10 â?? (e^10 + e^â??10)÷2", "0", 0);
 
     test("sinh 0", "0", 0);
-    test("sinh 10 â?? (e^(10)â??e^(â??10))÷2", "0", 0);
+    test("sinh 10 â?? (e^10 â?? e^â??10)÷2", "0", 0);
     test("sinh â??10 + sinh 10", "0", 0);
 
-    test("(cosh â??5)² â?? (sinh â??5)²", "1", 0);
+    test("cosh² â??5 â?? sinh² â??5", "1", 0);
     test("tanh 0", "0", 0);
-    test("tanh 10 â?? sinh(10)÷cosh(10)", "0", 0);
+    test("tanh 10 â?? sinh 10 ÷ cosh 10", "0", 0);
 
     test("atanh 0", "0", 0);
     test("atanh (1÷10) â?? 0.5 ln(11÷9)", "0", 0);
@@ -277,10 +290,10 @@ test_parser()
     test("sin 100", "1", 0);
 
     v->base = HEX;
-    test("3 And 5", "1", 0);
-    test("3 Or 5", "7", 0);
-    test("3 Xor 5", "6", 0);
-    test("3 Xnor 5", "FFFFFFF9", 0);
+    test("3 and 5", "1", 0);
+    test("3 or 5", "7", 0);
+    test("3 xor 5", "6", 0);
+    test("3 xnor 5", "FFFFFFF9", 0);
     test("~7A", "FFFFFF85", 0);
 }
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]