diff --git a/CONTRIBUTORS.markdown b/CONTRIBUTORS.markdown index 8466a7fff..e5e77f69f 100644 --- a/CONTRIBUTORS.markdown +++ b/CONTRIBUTORS.markdown @@ -19,3 +19,4 @@ The format for this list: name, GitHub handle, and then optional blurb about wha * Billy Kaplan (@billy1kaplan) * Tomas Mikula (@TomasMikula) * William Carroll (@wpcarro) +* Scott Christopher (@scott-christopher) diff --git a/parser-typechecker/src/Unison/Lexer.hs b/parser-typechecker/src/Unison/Lexer.hs index b159e7c89..ab9e86101 100644 --- a/parser-typechecker/src/Unison/Lexer.hs +++ b/parser-typechecker/src/Unison/Lexer.hs @@ -30,6 +30,7 @@ data Err | InvalidShortHash String | Both Err Err | MissingFractional String -- ex `1.` rather than `1.04` + | MissingExponent String -- ex `1e` rather than `1e3` | UnknownLexeme | TextLiteralMissingClosingQuote String | InvalidEscapeCharacter Char @@ -507,11 +508,24 @@ numericLit = go (fractional@(_:_), []) -> pure $ pure (sign ++ num ++ "." ++ fractional, []) (fractional@(_:_), c:rem) + | c `elem` "eE" -> goExp (sign ++ num ++ "." ++ fractional) rem | isSep c -> pure $ pure (sign ++ num ++ "." ++ fractional, c:rem) | otherwise -> pure Nothing ([], _) -> Left (MissingFractional (sign ++ num ++ ".")) + (num@(_:_), c:rem) | c `elem` "eE" -> goExp (sign ++ num) rem (num@(_:_), c:rem) -> pure $ pure (sign ++ num, c:rem) ([], _) -> pure Nothing + goExp signNum rem = case rem of + ('+':s) -> goExp' signNum "+" s + ('-':s) -> goExp' signNum "-" s + s -> goExp' signNum "" s + goExp' signNum expSign exp = case span isDigit exp of + ((_:_), []) -> + pure $ pure (signNum ++ "e" ++ expSign ++ exp, []) + (exp'@(_:_), c:rem) + | isSep c -> pure $ pure (signNum ++ "e" ++ expSign ++ exp', c:rem) + | otherwise -> pure Nothing + ([], _) -> Left (MissingExponent (signNum ++ "e" ++ expSign)) isSep :: Char -> Bool isSep c = isSpace c || Set.member c delimiters diff --git a/parser-typechecker/src/Unison/TermParser.hs b/parser-typechecker/src/Unison/TermParser.hs index 4a4d368ad..4ff72660b 100644 --- a/parser-typechecker/src/Unison/TermParser.hs +++ b/parser-typechecker/src/Unison/TermParser.hs @@ -16,7 +16,6 @@ import Control.Monad.Reader (asks, local) import Data.Foldable (asum) import Data.Functor import Data.Int (Int64) -import Data.List (elem) import Data.Maybe (isJust, fromMaybe) import Data.Word (Word64) import Prelude hiding (and, or, seq) @@ -525,10 +524,11 @@ number' -> P v a number' i u f = fmap go numeric where - go num@(L.payload -> p) | '.' `elem` p = f (read <$> num) - | take 1 p == "+" = i (read . drop 1 <$> num) - | take 1 p == "-" = i (read <$> num) - | otherwise = u (read <$> num) + go num@(L.payload -> p) | any (\c -> c == '.' || c == 'e') p && take 1 p == "+" = f (read . drop 1 <$> num) + | any (\c -> c == '.' || c == 'e') p = f (read <$> num) + | take 1 p == "+" = i (read . drop 1 <$> num) + | take 1 p == "-" = i (read <$> num) + | otherwise = u (read <$> num) tupleOrParenthesizedTerm :: Var v => TermP v tupleOrParenthesizedTerm = label "tuple" $ tupleOrParenthesized term DD.unitTerm pair diff --git a/parser-typechecker/tests/Unison/Test/Lexer.hs b/parser-typechecker/tests/Unison/Test/Lexer.hs index 92af140d6..5a8f173c3 100644 --- a/parser-typechecker/tests/Unison/Test/Lexer.hs +++ b/parser-typechecker/tests/Unison/Test/Lexer.hs @@ -12,6 +12,44 @@ test = , t "-1" [Numeric "-1"] , t "-1.0" [Numeric "-1.0"] , t "+1.0" [Numeric "+1.0"] + + , t "1e3" [Numeric "1e3"] + , t "1e+3" [Numeric "1e+3"] + , t "1e-3" [Numeric "1e-3"] + , t "+1e3" [Numeric "+1e3"] + , t "+1e+3" [Numeric "+1e+3"] + , t "+1e-3" [Numeric "+1e-3"] + , t "-1e3" [Numeric "-1e3"] + , t "-1e+3" [Numeric "-1e+3"] + , t "-1e-3" [Numeric "-1e-3"] + , t "1.2e3" [Numeric "1.2e3"] + , t "1.2e+3" [Numeric "1.2e+3"] + , t "1.2e-3" [Numeric "1.2e-3"] + , t "+1.2e3" [Numeric "+1.2e3"] + , t "+1.2e+3" [Numeric "+1.2e+3"] + , t "+1.2e-3" [Numeric "+1.2e-3"] + , t "-1.2e3" [Numeric "-1.2e3"] + , t "-1.2e+3" [Numeric "-1.2e+3"] + , t "-1.2e-3" [Numeric "-1.2e-3"] + , t "1E3" [Numeric "1e3"] + , t "1E+3" [Numeric "1e+3"] + , t "1E-3" [Numeric "1e-3"] + , t "+1E3" [Numeric "+1e3"] + , t "+1E+3" [Numeric "+1e+3"] + , t "+1E-3" [Numeric "+1e-3"] + , t "-1E3" [Numeric "-1e3"] + , t "-1E+3" [Numeric "-1e+3"] + , t "-1E-3" [Numeric "-1e-3"] + , t "1.2E3" [Numeric "1.2e3"] + , t "1.2E+3" [Numeric "1.2e+3"] + , t "1.2E-3" [Numeric "1.2e-3"] + , t "+1.2E3" [Numeric "+1.2e3"] + , t "+1.2E+3" [Numeric "+1.2e+3"] + , t "+1.2E-3" [Numeric "+1.2e-3"] + , t "-1.2E3" [Numeric "-1.2e3"] + , t "-1.2E+3" [Numeric "-1.2e+3"] + , t "-1.2E-3" [Numeric "-1.2e-3"] + , t "1-1" [Numeric "1", simpleSymbolyId "-", Numeric "1"] , t "1+1" [Numeric "1", simpleSymbolyId "+", Numeric "1"] , t "1 +1" [Numeric "1", Numeric "+1"] diff --git a/parser-typechecker/tests/Unison/Test/TermParser.hs b/parser-typechecker/tests/Unison/Test/TermParser.hs index 3afcc9d6f..33513bf81 100644 --- a/parser-typechecker/tests/Unison/Test/TermParser.hs +++ b/parser-typechecker/tests/Unison/Test/TermParser.hs @@ -22,8 +22,29 @@ test1 = scope "termparser" . tests . map parses $ , "1.0" , "+1" , "-1" + , "+1.0" , "-1.0" - , "4th" + + , "1e3" + , "1e+3" + , "1e-3" + , "+1e3" + , "+1e+3" + , "+1e-3" + , "-1e3" + , "-1e+3" + , "-1e-3" + , "1.2e3" + , "1.2e+3" + , "1.2e-3" + , "+1.2e3" + , "+1.2e+3" + , "+1.2e-3" + , "-1.2e3" + , "-1.2e+3" + , "-1.2e-3" + + , "-4th" , "()" , "(0)" , "forty"