From e587614c22e7785e600e4952c2ed1a46cacaa71a Mon Sep 17 00:00:00 2001 From: David Huynh Date: Tue, 28 Sep 2010 04:21:44 +0000 Subject: [PATCH] Fixed Issue 126: Large integers formatted in scientific notation in formulas git-svn-id: http://google-refine.googlecode.com/svn/trunk@1373 7d457c2a-affb-35e4-300a-418c747d4874 --- main/src/com/google/refine/gel/Parser.java | 5 +- main/src/com/google/refine/gel/Scanner.java | 50 +++++++++++-------- .../refine/gel/ast/OperatorCallExpr.java | 46 +++++++++++++---- 3 files changed, 71 insertions(+), 30 deletions(-) diff --git a/main/src/com/google/refine/gel/Parser.java b/main/src/com/google/refine/gel/Parser.java index adebfe737..a52319630 100644 --- a/main/src/com/google/refine/gel/Parser.java +++ b/main/src/com/google/refine/gel/Parser.java @@ -155,7 +155,10 @@ public class Parser { next(true); if (_token != null && _token.type == TokenType.Number) { - eval = new LiteralExpr(-((NumberToken)_token).value); + Number n = ((NumberToken)_token).value; + + eval = new LiteralExpr(n instanceof Long ? -n.longValue() : -n.doubleValue()); + next(false); } else { throw makeException("Bad negative number"); diff --git a/main/src/com/google/refine/gel/Scanner.java b/main/src/com/google/refine/gel/Scanner.java index bd2080f49..5d07ee875 100644 --- a/main/src/com/google/refine/gel/Scanner.java +++ b/main/src/com/google/refine/gel/Scanner.java @@ -35,9 +35,9 @@ public class Scanner { } static public class NumberToken extends Token { - final public double value; + final public Number value; - public NumberToken(int start, int end, String text, double value) { + public NumberToken(int start, int end, String text, Number value) { super(start, end, TokenType.Number, text); this.value = value; } @@ -94,34 +94,44 @@ public class Scanner { String detail = null; if (Character.isDigit(c)) { // number literal - double value = 0; + long value = 0; while (_index < _limit && Character.isDigit(c = _text.charAt(_index))) { value = value * 10 + (c - '0'); _index++; } - if (_index < _limit && c == '.') { - _index++; - - double division = 1; - while (_index < _limit && Character.isDigit(c = _text.charAt(_index))) { - value = value * 10 + (c - '0'); - division *= 10; + if (_index < _limit && (c == '.' || c == 'e')) { + double value2 = value; + if (c == '.') { _index++; + + double division = 1; + while (_index < _limit && Character.isDigit(c = _text.charAt(_index))) { + value2 = value2 * 10 + (c - '0'); + division *= 10; + _index++; + } + + value2 /= division; } - value /= division; + // TODO: support exponent e notation + + return new NumberToken( + start, + _index, + _text.substring(start, _index), + value2 + ); + } else { + return new NumberToken( + start, + _index, + _text.substring(start, _index), + value + ); } - - // TODO: support exponent e notation - - return new NumberToken( - start, - _index, - _text.substring(start, _index), - value - ); } else if (c == '"' || c == '\'') { /* * String Literal diff --git a/main/src/com/google/refine/gel/ast/OperatorCallExpr.java b/main/src/com/google/refine/gel/ast/OperatorCallExpr.java index e28183e70..dbaf14594 100644 --- a/main/src/com/google/refine/gel/ast/OperatorCallExpr.java +++ b/main/src/com/google/refine/gel/ast/OperatorCallExpr.java @@ -29,23 +29,47 @@ public class OperatorCallExpr implements Evaluable { if (args.length == 2) { if (args[0] != null && args[1] != null) { - if (args[0] instanceof Number && args[1] instanceof Number) { + if (isIntegral(args[0]) && isIntegral(args[1])) { + long n1 = ((Number) args[0]).longValue(); + long n2 = ((Number) args[1]).longValue(); + if ("+".equals(_op)) { - return ((Number) args[0]).doubleValue() + ((Number) args[1]).doubleValue(); + return n1 + n2; } else if ("-".equals(_op)) { - return ((Number) args[0]).doubleValue() - ((Number) args[1]).doubleValue(); + return n1 - n2; } else if ("*".equals(_op)) { - return ((Number) args[0]).doubleValue() * ((Number) args[1]).doubleValue(); + return n1 * n2; } else if ("/".equals(_op)) { - return ((Number) args[0]).doubleValue() / ((Number) args[1]).doubleValue(); + return n1 / n2; } else if (">".equals(_op)) { - return ((Number) args[0]).doubleValue() > ((Number) args[1]).doubleValue(); + return n1 > n2; } else if (">=".equals(_op)) { - return ((Number) args[0]).doubleValue() >= ((Number) args[1]).doubleValue(); + return n1 >= n2; } else if ("<".equals(_op)) { - return ((Number) args[0]).doubleValue() < ((Number) args[1]).doubleValue(); + return n1 < n2; } else if ("<=".equals(_op)) { - return ((Number) args[0]).doubleValue() <= ((Number) args[1]).doubleValue(); + return n1 <= n2; + } + } else if (args[0] instanceof Number && args[1] instanceof Number) { + double n1 = ((Number) args[0]).doubleValue(); + double n2 = ((Number) args[1]).doubleValue(); + + if ("+".equals(_op)) { + return n1 + n2; + } else if ("-".equals(_op)) { + return n1 - n2; + } else if ("*".equals(_op)) { + return n1 * n2; + } else if ("/".equals(_op)) { + return n1 / n2; + } else if (">".equals(_op)) { + return n1 > n2; + } else if (">=".equals(_op)) { + return n1 >= n2; + } else if ("<".equals(_op)) { + return n1 < n2; + } else if ("<=".equals(_op)) { + return n1 <= n2; } } @@ -86,4 +110,8 @@ public class OperatorCallExpr implements Evaluable { return sb.toString(); } + + private boolean isIntegral(Object n) { + return n instanceof Long || n instanceof Integer; + } }