commit 3107e00748d5f097eadd6639da1725f638acf093
parent 803c6ea7ce96c1809b5d44edc9a12fd1d587ea8b
Author: Ed van Bruggen <edvb@uw.edu>
Date: Wed, 4 Apr 2018 13:07:25 -0700
Add negative integers and fractions
Change read_int to read_num which calls a new read_int to parse the
numerator and, if it's a ratio, the denominator as well. Ratios always
simplify to only the numerator is negative if the fraction is negative,
or cancel out if the numerator and denominator are both negative
Diffstat:
5 files changed, 41 insertions(+), 12 deletions(-)
diff --git a/t/simple/frac.expect b/t/simple/frac.expect
@@ -5,3 +5,7 @@
2
1/2
1192/3619
+-1/2
+-1/2
+-2
+2
diff --git a/t/simple/frac.tsp b/t/simple/frac.tsp
@@ -5,3 +5,7 @@
8/4
4/8
02384/7238
+-1/2
+1/-2
+-6/3
+-6/-3
diff --git a/t/simple/self.expect b/t/simple/self.expect
@@ -3,6 +3,10 @@
0
30
12
+-4
+-83
+0
"foo"
"foo bar"
t
+()
diff --git a/t/simple/self.tsp b/t/simple/self.tsp
@@ -3,6 +3,10 @@
0
30
12
+-4
+-083
+-0
"foo"
"foo bar"
t
+()
diff --git a/tisp.c b/tisp.c
@@ -63,7 +63,7 @@ vals_eq(Val a, Val b)
static void
frac_reduce(int *num, int *den)
{
- int a = *num, b = *den, c = a % b;
+ int a = abs(*num), b = abs(*den), c = a % b;
while(c > 0) {
a = b;
b = c;
@@ -224,7 +224,11 @@ mk_rat(int num, int den)
if (den == 0)
warn("division by zero");
frac_reduce(&num, &den);
- if (den == 1) /* simplify fraction into integer if denominator is 1 */
+ if (den < 0) { /* simplify so only numerator is negative */
+ den = abs(den);
+ num = -num;
+ }
+ if (den == 1) /* simplify into integer if denominator is 1 */
return mk_int(num);
Val ret = emalloc(sizeof(struct Val));
ret->t = RATIONAL;
@@ -263,17 +267,26 @@ mk_list(int n, Val *a)
return b;
}
+static int
+read_int(Str str) {
+ int ret, sign = 1;
+ if (*str->d == '-') {
+ str->d++;
+ sign = -1;
+ }
+ for (ret = 0; isdigit(*str->d); str->d++)
+ ret = ret * 10 + *str->d - '0';
+ return sign * ret;
+}
+
Val
-read_int(Str str)
+read_num(Str str)
{
- int i, j;
- for (i = 0; isdigit(*str->d); str->d++)
- i = i * 10 + *str->d - '0';
+ int num = read_int(str);
if (*str->d != '/')
- return mk_int(i);
- for (j = 0, *str->d++; isdigit(*str->d); str->d++)
- j = j * 10 + *str->d - '0';
- return mk_rat(i, j);
+ return mk_int(num);
+ str->d++;
+ return mk_rat(num, read_int(str));
}
Val
@@ -326,8 +339,8 @@ Val
tisp_read(Str str)
{
skip_spaces(str);
- if (isdigit(*str->d)) /* TODO negative numbers */
- return read_int(str);
+ if (isdigit(*str->d) || (*str->d == '-' && isdigit(str->d[1])))
+ return read_num(str);
if (*str->d == '"')
return read_str(str);
if (*str->d == '\'') {