@@ -22,19 +22,19 @@ import Prelude
22
22
23
23
import Data.Array (elem , notElem )
24
24
import Data.CodePoint.Unicode (isAlpha , isAlphaNum , isDecDigit , isHexDigit , isLower , isOctDigit , isSpace , isUpper )
25
- import Data.Either (Either (..))
25
+ import Data.Either (Either (..), either )
26
26
import Data.Int as Data.Int
27
27
import Data.Maybe (Maybe (..))
28
28
import Data.Number (infinity , nan )
29
29
import Data.Number as Data.Number
30
30
import Data.String (CodePoint , singleton , takeWhile )
31
31
import Data.String.CodePoints (codePointFromChar )
32
32
import Data.String.CodeUnits as SCU
33
- import Data.Tuple (Tuple (..), fst )
33
+ import Data.Tuple (fst )
34
34
import Parsing (ParserT , fail )
35
- import Parsing.Combinators (choice , skipMany , (<?>), (<~?>))
36
- import Parsing.String (consumeWith , match , satisfy , satisfyCodePoint )
37
- import Parsing.String as Parser.String
35
+ import Parsing.Combinators (choice , tryRethrow , (<?>), (<| >), (<~?>))
36
+ import Parsing.String (consumeWith , match , regex , satisfy , satisfyCodePoint , string )
37
+ import Partial.Unsafe ( unsafeCrashWith )
38
38
39
39
-- | Parse a digit. Matches any char that satisfies `Data.CodePoint.Unicode.isDecDigit`.
40
40
digit :: forall m . ParserT String m Char
@@ -84,26 +84,27 @@ alphaNum = satisfyCP isAlphaNum <?> "letter or digit"
84
84
-- | * `"NaN"`
85
85
-- | * `"-Infinity"`
86
86
number :: forall m . ParserT String m Number
87
- -- TODO because the JavaScript parseFloat function will successfully parse
88
- -- a Number up until it doesn't understand something and then return
89
- -- the partially parsed Number, this parser will sometimes consume more
90
- -- String that it actually parses. Example "1..3" will parse as 1.0.
91
- -- So this needs improvement.
92
87
number =
93
88
choice
94
- [ Parser.String .string " Infinity" *> pure infinity
95
- , Parser.String .string " +Infinity" *> pure infinity
96
- , Parser.String .string " -Infinity" *> pure (negate infinity)
97
- , Parser.String .string " NaN" *> pure nan
98
- , do
99
- Tuple section _ <- Parser.String .match do
100
- _ <- oneOf [ ' +' , ' -' , ' .' , ' 0' , ' 1' , ' 2' , ' 3' , ' 4' , ' 5' , ' 6' , ' 7' , ' 8' , ' 9' ]
101
- skipMany $ oneOf [ ' e' , ' E' , ' +' , ' -' , ' .' , ' 0' , ' 1' , ' 2' , ' 3' , ' 4' , ' 5' , ' 6' , ' 7' , ' 8' , ' 9' ]
89
+ [ string " Infinity" *> pure infinity
90
+ , string " +Infinity" *> pure infinity
91
+ , string " -Infinity" *> pure (negate infinity)
92
+ , string " NaN" *> pure nan
93
+ , tryRethrow $ do
94
+ section <- numberRegex
102
95
-- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseFloat
103
96
case Data.Number .fromString section of
104
- Nothing -> fail $ " Could not parse Number " <> section
97
+ Nothing -> fail $ " Number.fromString failed"
98
+ -- Maybe this parser should set consumed flag if regex matches but fromString fails?
99
+ -- But currently regex allows some illegal inputs, like "."
100
+ -- Anyway this primitiv-ish parser should always backtrack on fail.
105
101
Just x -> pure x
106
- ]
102
+ ] <|> fail " Expected Number"
103
+
104
+ numberRegex :: forall m . ParserT String m String
105
+ numberRegex = either unsafeCrashWith identity $ regex pattern mempty
106
+ where
107
+ pattern = " [+-]?[0-9]*(\\ .[0-9]*)?([eE][+-]?[0-9]*(\\ .[0-9]*))?"
107
108
108
109
-- | Parser based on the __Data.Int.fromString__ function.
109
110
-- |
@@ -114,17 +115,20 @@ number =
114
115
-- | * `"-3"`
115
116
-- | * `"+300"`
116
117
intDecimal :: forall m . ParserT String m Int
117
- intDecimal = do
118
- Tuple section _ <- Parser.String .match do
119
- _ <- oneOf [ ' +' , ' -' , ' 0' , ' 1' , ' 2' , ' 3' , ' 4' , ' 5' , ' 6' , ' 7' , ' 8' , ' 9' ]
120
- skipMany $ oneOf [ ' 0' , ' 1' , ' 2' , ' 3' , ' 4' , ' 5' , ' 6' , ' 7' , ' 8' , ' 9' ]
118
+ intDecimal = tryRethrow do
119
+ section <- intDecimalRegex <|> fail " Expected Int"
121
120
case Data.Int .fromString section of
122
- Nothing -> fail $ " Could not parse Int " <> section
121
+ Nothing -> fail $ " Int.fromString failed "
123
122
Just x -> pure x
124
123
124
+ intDecimalRegex :: forall m . ParserT String m String
125
+ intDecimalRegex = either unsafeCrashWith identity $ regex pattern mempty
126
+ where
127
+ pattern = " [+-]?[0-9]*"
128
+
125
129
-- | Helper function
126
130
satisfyCP :: forall m . (CodePoint -> Boolean ) -> ParserT String m Char
127
- satisfyCP p = Parser.String . satisfy (p <<< codePointFromChar)
131
+ satisfyCP p = satisfy (p <<< codePointFromChar)
128
132
129
133
-- | Match zero or more whitespace characters satisfying
130
134
-- | `Data.CodePoint.Unicode.isSpace`. Always succeeds.
0 commit comments