[gcalctool/gcalctool-newui2] ...



commit a2d88f137c959f3b01fbccf7728a36e78af5aabb
Author: Robert Ancell <robert ancell gmail com>
Date:   Sun Jul 5 06:18:25 2009 +1000

    ...

 data/gcalctool.ui        |   38 +-----
 src/calctool.c           |    1 +
 src/gtk.c                |    2 -
 src/mp-binary.c          |   11 +--
 src/mp-convert.c         |    6 +-
 src/mp-equation-lexer.l  |   75 +++++--------
 src/mp-equation-parser.y |  273 +++++++++++++++-------------------------------
 src/mp-equation.c        |   70 +++++++++++-
 src/mp-equation.h        |    7 +-
 src/mp.c                 |    2 +-
 src/mp.h                 |    2 +-
 src/unittest.c           |   30 +++--
 12 files changed, 218 insertions(+), 299 deletions(-)
---
diff --git a/data/gcalctool.ui b/data/gcalctool.ui
index 80e963a..c6438d6 100644
--- a/data/gcalctool.ui
+++ b/data/gcalctool.ui
@@ -3329,24 +3329,6 @@
                     <signal name="clicked" handler="button_cb"/>
                   </object>
                   <packing>
-                    <property name="left_attach">7</property>
-                    <property name="right_attach">8</property>
-                    <property name="x_options">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
-                    <property name="y_options">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkButton" id="calc_xor_button">
-                    <property name="label" translatable="yes" comments="Boolean exlcusive OR button">xor</property>
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">True</property>
-                    <property name="border_width">3</property>
-                    <property name="use_underline">True</property>
-                    <property name="focus_on_click">False</property>
-                    <signal name="clicked" handler="button_cb"/>
-                  </object>
-                  <packing>
                     <property name="left_attach">8</property>
                     <property name="right_attach">9</property>
                     <property name="x_options">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
@@ -3354,8 +3336,8 @@
                   </packing>
                 </child>
                 <child>
-                  <object class="GtkButton" id="calc_xnor_button">
-                    <property name="label" translatable="yes" comments="Boolean exclusive NOR button">xnor</property>
+                  <object class="GtkButton" id="calc_xor_button">
+                    <property name="label" translatable="yes" comments="Boolean exlcusive OR button">xor</property>
                     <property name="visible">True</property>
                     <property name="can_focus">True</property>
                     <property name="receives_default">True</property>
@@ -3365,8 +3347,8 @@
                     <signal name="clicked" handler="button_cb"/>
                   </object>
                   <packing>
-                    <property name="left_attach">9</property>
-                    <property name="right_attach">10</property>
+                    <property name="left_attach">7</property>
+                    <property name="right_attach">8</property>
                     <property name="x_options">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
                     <property name="y_options">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
                   </packing>
@@ -3610,6 +3592,9 @@
                     <property name="y_options">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
                   </packing>
                 </child>
+                <child>
+                  <placeholder/>
+                </child>
               </object>
               <packing>
                 <property name="right_attach">10</property>
@@ -5043,15 +5028,6 @@
                 <property name="bottom_attach">5</property>
               </packing>
             </child>
-            <child>
-              <placeholder/>
-            </child>
-            <child>
-              <placeholder/>
-            </child>
-            <child>
-              <placeholder/>
-            </child>
           </object>
           <packing>
             <property name="position">1</property>
diff --git a/src/calctool.c b/src/calctool.c
index bd6fa6f..1927a01 100644
--- a/src/calctool.c
+++ b/src/calctool.c
@@ -1,4 +1,5 @@
 
+// FIXME: Remove Header in all files
 /*  $Header$
  *
  *  Copyright (c) 1987-2008 Sun Microsystems, Inc. All Rights Reserved.
diff --git a/src/gtk.c b/src/gtk.c
index 82cc876..d1d390e 100644
--- a/src/gtk.c
+++ b/src/gtk.c
@@ -101,7 +101,6 @@ static ButtonData button_data[] = {
     {"and",                "and"},
     {"or",                 "or"},
     {"xor",                "xor"},
-    {"xnor",               "xnor"},
     {"not",                "not"},
     {"integer_portion",    "int"},
     {"fractional_portion", "frac"},
@@ -1974,7 +1973,6 @@ add_buttons_to_size_group()
         "calc_or_button",
         "calc_not_button",
         "calc_xor_button",
-        "calc_xnor_button",
         "calc_ones_complement_button",
         "calc_twos_complement_button",
         "calc_shift_right_button",
diff --git a/src/mp-binary.c b/src/mp-binary.c
index 8e36fd0..740c86b 100644
--- a/src/mp-binary.c
+++ b/src/mp-binary.c
@@ -60,7 +60,6 @@ mp_bitwise(const MPNumber *x, const MPNumber *y, int (*bitwise_operator)(int, in
 static int mp_bitwise_and(int v1, int v2) { return v1 & v2; }
 static int mp_bitwise_or(int v1, int v2) { return v1 | v2; }
 static int mp_bitwise_xor(int v1, int v2) { return v1 ^ v2; }
-static int mp_bitwise_xnor(int v1, int v2) { return v1 ^ v2 ^ 0xF; }
 static int mp_bitwise_not(int v1, int dummy) { return v1 ^ 0xF; }
 
 
@@ -96,13 +95,6 @@ mp_xor(const MPNumber *x, const MPNumber *y, MPNumber *z)
 
 
 void
-mp_xnor(const MPNumber *x, const MPNumber *y, int wordlen, MPNumber *z)
-{
-    mp_bitwise(x, y, mp_bitwise_xnor, z, wordlen);
-}
-
-
-void
 mp_not(const MPNumber *x, int wordlen, MPNumber *z)
 {
     MPNumber temp;
@@ -151,7 +143,8 @@ mp_1s_complement(const MPNumber *x, int wordlen, MPNumber *z)
 {
     MPNumber t;
     mp_set_from_integer(0, &t);
-    mp_bitwise(x, &t, mp_bitwise_xnor, z, wordlen);
+    mp_bitwise(x, &t, mp_bitwise_xor, z, wordlen);
+    mp_not(z, wordlen, z);
 }
 
 
diff --git a/src/mp-convert.c b/src/mp-convert.c
index 1505f5c..7c885ea 100644
--- a/src/mp-convert.c
+++ b/src/mp-convert.c
@@ -618,9 +618,11 @@ mp_set_from_string(const char *str, MPNumber *z)
     }
     base = base_values[i];
 
-    /* Check if this is a negative number */
+    /* Check if this has a sign */
     c = str;
-    if (*c == '-') {
+    if (*c == '+') {
+        c++;
+    } else if (*c == '-') {
         negate = 1;
         c++;
     } else if (strncmp(c, "â??", strlen("â??")) == 0) {
diff --git a/src/mp-equation-lexer.l b/src/mp-equation-lexer.l
index 111973f..0fd19fb 100644
--- a/src/mp-equation-lexer.l
+++ b/src/mp-equation-lexer.l
@@ -7,9 +7,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) 2004-2008 Sami Pietila
  *  Copyright (C) 2008-2009 Robert Ancell
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -81,6 +79,8 @@ SI_SUFFIX    "T"|"G"|"M"|"k"|"d"|"c"|"m"|"u"|"µ"|"n"|"p"|"f"
 SUPER_DIGITS "�"|"¹"|"²"|"³"|"�"|"�"|"�"|"�"|"�"|"�"
 SUB_DIGITS   "â??"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"
 FRACTION     "½"|"â??"|"â??"|"¼"|"¾"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"
+VARIABLE_C   [a-z]|[A-Z]
+INVERSE      "�¹"
 
 HEX_NUM {HEX}+{HEX_SUFFIX}|{HEX}*{DECIMAL}{HEX}+{HEX_SUFFIX}
 DEC_NUM {DEC}+|{DEC}+{SI_SUFFIX}|{DEC}*{DECIMAL}{DEC}+|{DEC}*{SI_SUFFIX}{DEC}+|{FRACTION}|{DEC}{FRACTION}
@@ -89,53 +89,34 @@ BIN_NUM {BIN}+{BIN_SUFFIX}|{BIN}*{DECIMAL}{BIN}+{BIN_SUFFIX}
 SUP_NUM {SUPER_DIGITS}+
 SUB_NUM {SUB_DIGITS}+
 NUMBER  {BIN_NUM}|{OCT_NUM}|{DEC_NUM}|{HEX_NUM}
+VARIABLE {VARIABLE_C}+|"Ï?"|{VARIABLE_C}+{INVERSE}|{VARIABLE_C}+{SUB_NUM}
 
-%%
+MOD  [mM][oO][dD]
+AND  "â?§"|[aA][nN][dD]
+OR   "â?¨"|[oO][rR]
+XOR  "â??"|[xX][oO][rR]
+NOT  "¬"|"~"|[nN][oO][tT]
 
-"+"     {return tADD;}
-"-"|"â??" {return tSUBTRACT;}
-"*"|"Ã?" {return tMULTIPLY;}
-"/"|"÷" {return tDIVIDE;}
-"|" {return tABS;}
-"abs"|"Abs"|"ABS" {return tABS_FUNC;}
-"sin"|"Sin"|"SIN" {return tSIN;}
-"cos"|"Cos"|"COS" {return tCOS;}
-"tan"|"Tan"|"TAN" {return tTAN;}
-"sin�¹"|"asin"|"Asin"|"ASIN" {return tASIN;}
-"cos�¹"|"acos"|"Acos"|"ACOS" {return tACOS;}
-"tan�¹"|"atan"|"Atan"|"ATAN" {return tATAN;}
-"sinh"|"Sinh"|"SINH" {return tSINH;}
-"cosh"|"Cosh"|"COSH" {return tCOSH;}
-"tanh"|"Tanh"|"TANH" {return tTANH;}
-"sinh�¹"|"asinh"|"Asinh"|"ASINH" {return tASINH;}
-"cosh�¹"|"acosh"|"Acosh"|"ACOSH" {return tACOSH;}
-"tanh�¹"|"atanh"|"Atanh"|"ATANH" {return tATANH;}
-"ans"|"Ans"|"ANS" {return tANS;}
-"frac"|"Frac"|"FRAC" {return tFRAC;}
-"int"|"Int"|"INT" {return tINT;}
-"ln"|"Ln"|"LN" {return tLN;}
-"log"|"Log"|"LOG" {return tLOG;}
-"mod"|"Mod"|"MOD" {return tMOD;}
-"e" {return tEULERS;}
-"Ï?"|"pi"|"Pi"|"PI" {return tPI;}
-"rand"|"Rand"|"RAND" {return tRAND;}
-"â??"|"sqrt"|"Sqrt"|"SQRT" {return tROOT;}
-"â??"|"cbrt"|"Cbrt"|"CBRT" {return tROOT3;}
-"â??" {return tROOT4;}
-"¬"|"~"|"not"|"Not"|"NOT" {return tNOT;}
-"â?§"|"and"|"And"|"AND" {return tAND;}
-"â?¨"|"or"|"Or"|"OR" {return tOR;}
-"â??"|"xor"|"Xor"|"XOR" {return tXOR;}
-"xnor"|"Xnor"|"XNOR" {return tXNOR;}
-"ones" {return tONES;}
-"twos" {return tTWOS;}
-"trunc"|"Trunc"|"TRUNC" {return tTRUNC;}
+%%
 
-"R"{DEC}+ {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; }
-{NUMBER}  {mp_set_from_string(yytext, &yylval->int_t); return tNUMBER;}
+"+"        {return tADD;}
+"-"|"â??"    {return tSUBTRACT;}
+"*"|"Ã?"    {return tMULTIPLY;}
+"/"|"÷"    {return tDIVIDE;}
+{MOD}      {return tMOD;}
+"â??"        {return tROOT;}
+"â??"        {return tROOT3;}
+"â??"        {return tROOT4;}
+{NOT}      {return tNOT;}
+{AND}      {return tAND;}
+{OR}       {return tOR;}
+{XOR}      {return tXOR;}
+{SUP_NUM}  {yylval->integer = super_atoi(yytext); return tSUPNUM; }
+{SUB_NUM}  {yylval->integer = sub_atoi(yytext); return tSUBNUM; }
+{NUMBER}   {mp_set_from_string(yytext, &yylval->int_t); return tNUMBER;}
+{VARIABLE} {yylval->name = strdup(yytext); return tVARIABLE;}
+{INVERSE}  {return tINVERSE;}
 [ \t\n]
-.         {return *yytext;}
+.          {return *yytext;}
 
 %% 
diff --git a/src/mp-equation-parser.y b/src/mp-equation-parser.y
index f3148b6..869cd7e 100644
--- a/src/mp-equation-parser.y
+++ b/src/mp-equation-parser.y
@@ -1,8 +1,6 @@
 %{
 
-/*  $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) 2004-2008 Sami Pietila
  *  Copyright (C) 2008-2009 Robert Ancell
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -30,22 +28,49 @@
 #include "mp-equation-parser.h"
 #include "mp-equation-lexer.h"
 
-static const MPNumber *get_variable(yyscan_t yyscanner, const char *name)
+static void get_variable(yyscan_t yyscanner, const char *name, MPNumber *z)
 {
-    return _mp_equation_get_extra(yyscanner)->get_variable(_mp_equation_get_extra(yyscanner), name);
+    _mp_equation_get_extra(yyscanner)->get_variable(_mp_equation_get_extra(yyscanner), name, z);
 }
 
-static const MPNumber *get_register(yyscan_t yyscanner, int index)
+static void get_function(yyscan_t yyscanner, const char *name, const MPNumber *x, MPNumber *z)
 {
-    char name[3];
-    snprintf(name, 3, "R%d", index);
-    return get_variable(yyscanner, name);
+    _mp_equation_get_extra(yyscanner)->get_function(_mp_equation_get_extra(yyscanner), name, x, z);
 }
 
 static void set_error(yyscan_t yyscanner, int error)
 {
     _mp_equation_get_extra(yyscanner)->error = error;
 }
+
+static void do_bitwise(yyscan_t yyscanner, void (*mp_fn)(const MPNumber *x, const MPNumber *y, MPNumber *z), const MPNumber *x, const MPNumber *y, MPNumber *z)
+{
+    if (!mp_is_natural(x) || !mp_is_natural(y))
+	set_error(yyscanner, -PARSER_ERR_BITWISEOP);
+    else
+        mp_fn(x, y, z);
+}
+
+static void do_not(yyscan_t yyscanner, const MPNumber *x, MPNumber *z)
+{
+    if (!mp_is_natural(x)) {
+	set_error(yyscanner, -PARSER_ERR_BITWISEOP);
+    } else if (!mp_is_overflow(x, _mp_equation_get_extra(yyscanner)->wordlen)) {
+	set_error(yyscanner, -PARSER_ERR_OVERFLOW);
+    }
+    mp_not(x, _mp_equation_get_extra(yyscanner)->wordlen, z);
+}
+
+static void do_mod(yyscan_t yyscanner, const MPNumber *x, const MPNumber *y, MPNumber *z)
+{
+    if (!mp_is_integer(x) || !mp_is_integer(y)) {
+	set_error(yyscanner, -PARSER_ERR_MODULUSOP);
+    } else {
+      if (mp_modulus_divide(x, y, z)) {
+        set_error(yyscanner, -EINVAL);
+      }
+    }
+}
 %}
 
 %define api.pure
@@ -57,198 +82,72 @@ static void set_error(yyscan_t yyscanner, int error)
 %union {
   MPNumber int_t;
   int integer;
+  char *name;
 }
 
-%token tADD
-%token tSUBTRACT
-%token tMULTIPLY
-%token tDIVIDE
-%token tABS
-%token tABS_FUNC
-%token tACOS
-%token tACOSH
-%token tAND
-%token tANS
-%token tASIN
-%token tASINH
-%token tATAN
-%token tATANH
-%token tCHS
-%token tCLR
-%token tCOS
-%token tCOSH
-%token tEXP
-%token tFRAC
-%token tINT
-%token tLN
-%token tLOG
-%token tMOD
-%token tONES
-%token tTWOS
-%token tNOT
-%token tOR
-%token tEULERS
-%token tPI
-%token tRAND
-%token tSIN
-%token tSINH
-%token tROOT
-%token tROOT3
-%token tROOT4
-%token tSQRT
-%token tTAN
-%token tTANH
-%token tTRUNC
-%token tXNOR
-%token tXOR
-
-%token <int_t> tNUMBER
-%token <integer> tREG tSUBNUM tSUPNUM
-
-%type  <int_t> exp term func number constant
-
+%token <int_t>   tNUMBER
+%token <integer> tSUBNUM tSUPNUM
+%token <name>    tVARIABLE
+
+%left UNARY_PLUS
+%left tADD tSUBTRACT
+%left tAND tOR tXOR tXNOR
+%left tMULTIPLY tDIVIDE tMOD
+%left tNOT
+%right '^' tSQUARED tCUBED tINVERSE
+%left tROOT tROOT3 tROOT4
+%right '!'
+%left VARIABLE
+%left FUNCTION
+%left BOOLEAN_OPERATOR
+%left PERCENTAGE
+%left UNARY_MINUS
+
+%type <int_t> exp function
 %start statement
-%left tADD tSUBTRACT tMULTIPLY tDIVIDE
-%left MED
-%left LNEG
-%right '^' '!' '%' tSQUARED tCUBED
-%left HIGH
 
 %%
 
-statement: 
-  exp { mp_set_from_mp(&$1, &(_mp_equation_get_extra(yyscanner))->ret); set_error(yyscanner, 0); }
+statement:
+  exp { mp_set_from_mp(&$1, &(_mp_equation_get_extra(yyscanner))->ret); set_error(yyscanner, 0);}
 ;
 
-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:
+  tNUMBER {mp_set_from_mp(&$1, &$$);}
+| tSUBTRACT exp %prec UNARY_MINUS {mp_invert_sign(&$2, &$$);}
+| tADD tNUMBER %prec UNARY_PLUS {mp_set_from_mp(&$2, &$$);}
+| tVARIABLE {get_variable(yyscanner, $1, &$$); free($1);}
+| tNUMBER tVARIABLE %prec VARIABLE {get_variable(yyscanner, $2, &$$); mp_multiply(&$1, &$$, &$$); free($2);}
+| function {mp_set_from_mp(&$1, &$$);}
+| tNUMBER function %prec FUNCTION {mp_multiply(&$1, &$2, &$$);}
+| exp tDIVIDE exp {mp_divide(&$1, &$3, &$$);}
+| exp tMOD exp {do_mod(yyscanner, &$1, &$3, &$$);}
+| exp tMULTIPLY exp {mp_multiply(&$1, &$3, &$$);}
 | 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)) {
-	set_error(yyscanner, -PARSER_ERR_MODULUSOP);
-    } else {
-      if (mp_modulus_divide(&$1, &$3, &$$)) {
-        set_error(yyscanner, -EINVAL);
-      }			   
-    }
-}
-| exp tAND exp {
-    if (!mp_is_natural(&$1) || !mp_is_natural(&$3)) {
-	set_error(yyscanner, -PARSER_ERR_BITWISEOP);
-    }
-    mp_and(&$1, &$3, &$$);
-}
-| exp tOR exp {
-    if (!mp_is_natural(&$1) || !mp_is_natural(&$3)) {
-	set_error(yyscanner, -PARSER_ERR_BITWISEOP);
-    }
-    mp_or(&$1, &$3, &$$);
-}
-| exp tXNOR exp {
-    if (!mp_is_natural(&$1) || !mp_is_natural(&$3)) {
-	set_error(yyscanner, -PARSER_ERR_BITWISEOP);
-    }
-    mp_xnor(&$1, &$3, _mp_equation_get_extra(yyscanner)->wordlen, &$$);
-}
-| exp tXOR exp {
-    if (!mp_is_natural(&$1) || !mp_is_natural(&$3)) {
-	set_error(yyscanner, -PARSER_ERR_BITWISEOP);
-    }
-    mp_xor(&$1, &$3, &$$);
-}
-;
-
-
-term:
-  number {mp_set_from_mp(&$1, &$$);}
-| constant {mp_set_from_mp(&$1, &$$);}  
-| number constant {mp_multiply(&$1, &$2, &$$);}  
-| 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, &$$);}
-| term '!' {mp_factorial(&$1, &$$);}
-| term tSUPNUM {mp_pwr_integer(&$1, $2, &$$);}
-| term '%' {mp_divide_integer(&$1, 100, &$$);}
-| tNOT term %prec LNEG {
-    if (!mp_is_natural(&$2)) {
-	set_error(yyscanner, -PARSER_ERR_BITWISEOP);
-    } else if (!mp_is_overflow(&$2, _mp_equation_get_extra(yyscanner)->wordlen)) {
-	set_error(yyscanner, -PARSER_ERR_OVERFLOW);
-    }
-    mp_not(&$2, _mp_equation_get_extra(yyscanner)->wordlen, &$$);
-}
-| 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, &$$);}
-| tREG {mp_set_from_mp(get_register(yyscanner, $1), &$$);}
+| exp tADD exp '%' %prec PERCENTAGE {mp_add_integer(&$3, 100, &$3); mp_divide_integer(&$3, 100, &$3); mp_multiply(&$1, &$3, &$$);}
+| exp tSUBTRACT exp '%' %prec PERCENTAGE {mp_add_integer(&$3, -100, &$3); mp_divide_integer(&$3, -100, &$3); mp_multiply(&$1, &$3, &$$);}
+| exp '^' exp {mp_xpowy(&$1, &$3, &$$);}
+| exp tSUPNUM {mp_pwr_integer(&$1, $2, &$$);}
+| exp tINVERSE {mp_reciprocal(&$1, &$$);}
 | '(' exp ')' {mp_set_from_mp(&$2, &$$);}
+| '|' exp '|' {mp_abs(&$2, &$$);}
+| exp '!' {mp_factorial(&$1, &$$);}
+| tNOT exp {do_not(yyscanner, &$2, &$$);}
+| exp tAND exp %prec BOOLEAN_OPERATOR {do_bitwise(yyscanner, mp_and, &$1, &$3, &$$);}
+| exp tOR exp %prec BOOLEAN_OPERATOR {do_bitwise(yyscanner, mp_or, &$1, &$3, &$$);}
+| exp tXOR exp %prec BOOLEAN_OPERATOR {do_bitwise(yyscanner, mp_xor, &$1, &$3, &$$);}
+| exp '%' {mp_divide_integer(&$1, 100, &$$);}
 ;
 
-func:
-  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, &$$);}
-| 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, &$$);}
-| tONES term %prec HIGH  {
-    if (!mp_is_natural(&$2)) {
-	set_error(yyscanner, -PARSER_ERR_BITWISEOP);
-    } else if (!mp_is_overflow(&$2, _mp_equation_get_extra(yyscanner)->wordlen)) {
-	set_error(yyscanner, -PARSER_ERR_OVERFLOW);
-    }
-    mp_1s_complement(&$2, _mp_equation_get_extra(yyscanner)->wordlen, &$$);
-}
-| tTWOS term %prec HIGH {
-    if (!mp_is_natural(&$2)) {
-	set_error(yyscanner, -PARSER_ERR_BITWISEOP);
-    } else if (!mp_is_overflow(&$2, _mp_equation_get_extra(yyscanner)->wordlen)) {
-	set_error(yyscanner, -PARSER_ERR_OVERFLOW);
-    }
-    mp_2s_complement(&$2, _mp_equation_get_extra(yyscanner)->wordlen, &$$);
-}
-;
-
-number:
-  tNUMBER {mp_set_from_mp(&$1, &$$);}
-| tANS {mp_set_from_mp(get_variable(yyscanner, "ans"), &$$);}
-;
 
-constant:
-  tEULERS {mp_get_eulers(&$$);}
-| tPI {mp_get_pi(&$$);}
+function:
+  tVARIABLE exp %prec FUNCTION {get_function(yyscanner, $1, &$2, &$$); free($1);}
+| tVARIABLE tSUPNUM exp %prec FUNCTION {get_function(yyscanner, $1, &$3, &$$); mp_pwr_integer(&$$, $2, &$$); free($1);}
+| tSUBNUM tROOT exp %prec FUNCTION {mp_root(&$3, $1, &$$);}
+| tROOT exp %prec FUNCTION {mp_sqrt(&$2, &$$);}
+| tROOT3 exp %prec FUNCTION {mp_root(&$2, 3, &$$);}
+| tROOT4 exp %prec FUNCTION {mp_root(&$2, 4, &$$);}
 ;
 
 %%
diff --git a/src/mp-equation.c b/src/mp-equation.c
index e5e252d..dedfe38 100644
--- a/src/mp-equation.c
+++ b/src/mp-equation.c
@@ -19,6 +19,8 @@
  *  02111-1307, USA.
  */
 
+#include <ctype.h>
+
 #include "mp-equation.h"
 #include "calctool.h"
 #include "register.h"
@@ -27,17 +29,74 @@
 
 extern int _mp_equation_parse(yyscan_t yyscanner);
 
-static const MPNumber *
-get_variable(MPEquationParserState *state, const char *name)
+static void
+get_variable(MPEquationParserState *state, const char *name, MPNumber *z)
 {
     if (name[0] == 'R' || name[0] == 'r')
-        return register_get_value(atoi(name+1));
+        mp_set_from_mp(register_get_value(atoi(name+1)), z);
     else if (strcmp(name, "ans") == 0)
-        return display_get_answer(&v->display);
+        mp_set_from_mp(display_get_answer(&v->display), z);
+    else if (strcmp(name, "e") == 0)
+        mp_get_eulers(z);
+    else if (strcmp(name, "Ï?") == 0)
+        mp_get_pi(z);
     else
-        return NULL;
+        mp_set_from_integer(0, z); // FIXME
 }
 
+
+static void
+get_function(MPEquationParserState *state, const char *name, const MPNumber *x, MPNumber *z)
+{
+    char *c, *lower_name;
+    
+    lower_name = strdup(name);
+    for (c = lower_name; *c; c++)
+        *c = tolower(*c);
+    
+    if (strcmp(lower_name, "log") == 0)
+        mp_logarithm(10, x, z);
+    else if (strcmp(lower_name, "ln") == 0)
+        mp_ln(x, z);
+    else if (strcmp(lower_name, "sqrt") == 0) // â??x
+        mp_sqrt(x, z);
+    else if (strcmp(lower_name, "abs") == 0) // |x|
+        mp_abs(x, z);
+    else if (strcmp(lower_name, "int") == 0)
+        mp_integer_component(x, z);
+    else if (strcmp(lower_name, "frac") == 0)
+        mp_fractional_component(x, z);
+    else if (strcmp(lower_name, "sin") == 0)
+        mp_sin(x, state->angle_units, z);
+    else if (strcmp(lower_name, "cos") == 0)
+        mp_cos(x, state->angle_units, z);
+    else if (strcmp(lower_name, "tan") == 0)
+        mp_tan(x, state->angle_units, z);    
+    else if (strcmp(lower_name, "sin�¹") == 0 || strcmp(lower_name, "asin") == 0)
+        mp_asin(x, state->angle_units, z);
+    else if (strcmp(lower_name, "cos�¹") == 0 || strcmp(lower_name, "acos") == 0)
+        mp_acos(x, state->angle_units, z);
+    else if (strcmp(lower_name, "tan�¹") == 0 || strcmp(lower_name, "atan") == 0)
+        mp_atan(x, state->angle_units, z);    
+    else if (strcmp(lower_name, "sinh") == 0)
+        mp_sinh(x, z);
+    else if (strcmp(lower_name, "cosh") == 0)
+        mp_cosh(x, z);
+    else if (strcmp(lower_name, "tanh") == 0)
+        mp_tanh(x, z);
+    else if (strcmp(lower_name, "sinh�¹") == 0 || strcmp(lower_name, "asinh") == 0)
+        mp_asinh(x, z);
+    else if (strcmp(lower_name, "cosh�¹") == 0 || strcmp(lower_name, "acosh") == 0)
+        mp_acosh(x, z);
+    else if (strcmp(lower_name, "tanh�¹") == 0 || strcmp(lower_name, "atanh") == 0)
+        mp_atanh(x, z);
+    else
+        mp_set_from_integer(0, z); // FIXME
+    
+    free(lower_name);
+}
+
+
 int 
 mp_equation_parse(const char *expression, MPNumber *result)
 {
@@ -54,6 +113,7 @@ mp_equation_parse(const char *expression, MPNumber *result)
     state.wordlen = v->wordlen;
     state.angle_units = v->ttype;
     state.get_variable = get_variable;
+    state.get_function = get_function;    
     state.error = -EINVAL;
     v->math_error = 0;
         
diff --git a/src/mp-equation.h b/src/mp-equation.h
index 37eac5b..2625ec9 100644
--- a/src/mp-equation.h
+++ b/src/mp-equation.h
@@ -44,7 +44,12 @@ struct MPEquationParserState {
     MPAngleUnit angle_units;
     
     /* Function to get variable values */
-    const MPNumber *(*get_variable)(MPEquationParserState *state, const char *name);
+    void (*get_variable)(MPEquationParserState *state, const char *name, MPNumber *z);
+
+    /* Function to solve functions */
+    void (*get_function)(MPEquationParserState *state, const char *name, const MPNumber *x, MPNumber *z);
+    
+    // FIXME: get_operator??
 
     /* Error returned from parser */
     int error;
diff --git a/src/mp.c b/src/mp.c
index 214f500..c5e57a7 100644
--- a/src/mp.c
+++ b/src/mp.c
@@ -1372,7 +1372,7 @@ mp_ln(const MPNumber *x, MPNumber *z)
  *  1. log10(x) = log10(e) * log(x)
  */
 void
-mp_logarithm(int n, MPNumber *x, MPNumber *z)
+mp_logarithm(int n, const MPNumber *x, MPNumber *z)
 {
     MPNumber t1, t2;
 
diff --git a/src/mp.h b/src/mp.h
index f01b7fa..1fc782a 100644
--- a/src/mp.h
+++ b/src/mp.h
@@ -143,7 +143,7 @@ void   mp_integer_component(const MPNumber *x, MPNumber *z);
 void   mp_ln(const MPNumber *x, MPNumber *z);
 
 /* Sets z = log_n(x) */
-void   mp_logarithm(int n, MPNumber *x, MPNumber *z);
+void   mp_logarithm(int n, const MPNumber *x, MPNumber *z);
 
 /* Sets z = Ï? */
 void   mp_get_pi(MPNumber *z);
diff --git a/src/unittest.c b/src/unittest.c
index 6bcd123..c6ff1e8 100644
--- a/src/unittest.c
+++ b/src/unittest.c
@@ -101,7 +101,10 @@ test_parser()
     test("0", "0", 0);
     test("1", "1", 0);
     test("+1", "1", 0);
-    test("++1", "1", 0);
+    test("â??1", "â??1", 0);
+    test("+ 1", "1", 0); // FIXME: Should this be allowed?
+    test("â?? 1", "â??1", 0); // FIXME: Should this be allowed?
+    test("++1", "1", -22);
     test("â??â??1", "1", 0);
     test("255", "255", 0);
     test("256", "256", 0);
@@ -196,8 +199,9 @@ test_parser()
     test("5!", "120", 0);
     test("69!", "171122452428141311372468338881272839092270544893520369393648040923257279754140647424000000000000000", 0);
     test("0.1!", "", -20001);
-    test("â??1!", "â??1", 0); // FIXME: Should be an error
+    test("â??1!", "", -20001);
     test("(â??1)!", "", -20001);
+    test("â??(1!)", "â??1", 0);
 
     test("2²", "4", 0);
     test("2³", "8", 0);
@@ -206,11 +210,12 @@ test_parser()
     test("2^1", "2", 0);
     test("2^2", "4", 0);
     test("2�¹", "0.5", 0);
-    test("2â?»", "", -20001);    
+    //test("2â?»", "", -20001); // FIXME: Maybe an error in bison?
     test("2^â??1", "0.5", 0);
     test("2^(â??1)", "0.5", 0);
-    test("â??10^2", "â??100", 0);
+    test("â??10^2", "100", 0);
     test("(â??10)^2", "100", 0);
+    test("â??(10^2)", "â??100", 0);
     test("2^100", "1267650600228229401496703205376", 0);
     test("4^3^2", "262144", 0);
     test("4^(3^2)", "262144", 0);
@@ -231,11 +236,11 @@ test_parser()
     test("â??4^0.5", "", -20001);
     test("â??8^(1÷3)", "â??2", 0);
     
-    test("0 Mod 7", "0", 0);
-    test("6 Mod 7", "6", 0);
-    test("7 Mod 7", "0", 0);
-    test("8 Mod 7", "1", 0);
-    test("â??1 Mod 7", "6", 0);
+    test("0 mod 7", "0", 0);
+    test("6 mod 7", "6", 0);
+    test("7 mod 7", "0", 0);
+    test("8 mod 7", "1", 0);
+    test("â??1 mod 7", "6", 0);
     
     test("Int(3.2)", "3", 0);
     test("Frac(3.2)", "0.2", 0);
@@ -318,12 +323,11 @@ test_parser()
     v->ttype = MP_GRADIANS;
     test("sin 100", "1", 0);
 
-    test("3 And 5", "1", 0);
-    test("3 Or 5", "7", 0);
-    test("3 Xor 5", "6", 0);
+    test("3 and 5", "1", 0);
+    test("3 or 5", "7", 0);
+    test("3 xor 5", "6", 0);
     
     v->base = 16;
-    test("3 Xnor 5", "FFFFFFF9â??â??", 0);
     test("~7Aâ??â??", "FFFFFF85â??â??", 0);
 }
 



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