[gcalctool] Make parser support sexagesimal input (Bug #616067)



commit 4c1badf02232a620ef4017aac0db25ffc19f05a3
Author: Robert Ancell <robert ancell gmail com>
Date:   Sun Apr 18 18:07:49 2010 +1000

    Make parser support sexagesimal input (Bug #616067)

 src/math-display.c      |    3 +++
 src/mp-convert.c        |   34 ++++++++++++++++++++++++++++++++++
 src/mp-equation-lexer.l |    7 ++++++-
 src/unittest.c          |    5 +++++
 4 files changed, 48 insertions(+), 1 deletions(-)
---
diff --git a/src/math-display.c b/src/math-display.c
index 8c37b59..acdfc26 100644
--- a/src/math-display.c
+++ b/src/math-display.c
@@ -136,6 +136,9 @@ display_key_press_cb(GtkWidget *widget, GdkEventKey *event, MathDisplay *display
         case GDK_minus:
              math_equation_insert(display->priv->equation, "â?»");
              return TRUE;
+        case GDK_apostrophe:
+             math_equation_insert(display->priv->equation, "°");
+             return TRUE;
         }
     }
 
diff --git a/src/mp-convert.c b/src/mp-convert.c
index 2013be1..5b4e4e5 100644
--- a/src/mp-convert.c
+++ b/src/mp-convert.c
@@ -18,6 +18,7 @@
  */
 
 #include <stdlib.h>
+#include <stdio.h>
 #include <string.h>
 #include <ctype.h>
 #include <math.h>
@@ -717,6 +718,36 @@ ends_with(const char *start, const char *end, const char *word)
 }
 
 
+// FIXME: Doesn't handle errors well (e.g. trailing space)
+static bool
+set_from_sexagesimal(const char *str, int length, MPNumber *z)
+{
+    int degrees = 0, minutes = 0;
+    char seconds[length+1];
+    MPNumber t;
+    int n_matched;
+
+    seconds[0] = '\0';
+    n_matched = sscanf(str, "%d°%d'%s\"\0", &degrees, &minutes, seconds);
+
+    if (n_matched < 1)
+        return true;
+    mp_set_from_integer(degrees, z);
+    if (n_matched > 1) {
+        mp_set_from_integer(minutes, &t);
+        mp_divide_integer(&t, 60, &t);
+        mp_add(z, &t, z);
+    }
+    if (n_matched > 2) {
+        mp_set_from_string(seconds, 10, &t);
+        mp_divide_integer(&t, 3600, &t);
+        mp_add(z, &t, z);
+    }
+
+    return false;
+}
+
+
 bool
 mp_set_from_string(const char *str, int default_base, MPNumber *z)
 {
@@ -728,6 +759,9 @@ mp_set_from_string(const char *str, int default_base, MPNumber *z)
     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};
+  
+    if (strstr(str, "°"))
+        return set_from_sexagesimal(str, strlen(str), z);
 
     /* Find the base */
     end = str;
diff --git a/src/mp-equation-lexer.l b/src/mp-equation-lexer.l
index 497a926..17956c6 100644
--- a/src/mp-equation-lexer.l
+++ b/src/mp-equation-lexer.l
@@ -54,16 +54,21 @@ SUPER_MINUS   "â?»"
 SUB_DIGITS    "â??"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"
 FRACTION      "½"|"â??"|"â??"|"¼"|"¾"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"|"â??"
 GREEKS        "α"|"β"|"γ"|"δ"|"ε"|"ζ"|"η"|"θ"|"ι"|"κ"|"λ"|"μ"|"ν"|"ξ"|"ο"|"Ï?"|"Ï?"|"Ï?"|"Ï?"|"Ï?"|"Ï?"|"Ï?"|"Ï?"|"Ï?"|"Ï?"
+DEGREES       "°"
+MINUTES       "'"
+SECONDS       "\""
 LETTERS       [a-zA-Z]|{GREEKS}
 
 SUP_NUM  {SUPER_DIGITS}+
 NSUP_NUM {SUPER_MINUS}{SUPER_DIGITS}+
 SUB_NUM  {SUB_DIGITS}+
 WORD     {LETTERS}+
+DEC_NUM  {DEC}+|{DEC}*{DECIMAL}{DEC}+
 DEF_NUM  {HEX}+|{HEX}*{DECIMAL}{HEX}+
 BASE_NUM {HEX}+{SUB_NUM}|{HEX}*{DECIMAL}{HEX}+{SUB_NUM}
+ANGLE_NUM {DEC_NUM}{DEGREES}|{DEC}+{DEGREES}{DEC_NUM}{MINUTES}|{DEC}+{DEGREES}{DEC}+{MINUTES}{DEC_NUM}{SECONDS}
 
-NUMBER   {DEF_NUM}|{BASE_NUM}|{FRACTION}|{DEC}+{FRACTION}
+NUMBER   {DEF_NUM}|{BASE_NUM}|{FRACTION}|{DEC}+{FRACTION}|{ANGLE_NUM}
 VARIABLE {WORD}|{WORD}{SUB_NUM}|{GREEKS}
 
 MOD  [mM][oO][dD]
diff --git a/src/unittest.c b/src/unittest.c
index 7c39ef2..145a430 100644
--- a/src/unittest.c
+++ b/src/unittest.c
@@ -210,6 +210,11 @@ test_equations()
     test("256", "256", 0);
     test("½", "0.5", 0);
     test("1½", "1.5", 0);
+    test("0°", "0", 0);
+    test("1°", "1", 0);
+    test("0°30'", "0.5", 0);
+    test("0°0'1\"", "0.000277778", 0);
+    test("0°0'0.1\"", "0.000027778", 0);
     test("1.00", "1", 0);
     test("1.01", "1.01", 0);
 



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