Skip to content
This repository was archived by the owner on Jun 15, 2023. It is now read-only.

Commit c1632be

Browse files
authored
Fix printers and parsers (#24)
1 parent d2d8bbd commit c1632be

File tree

2 files changed

+49
-21
lines changed

2 files changed

+49
-21
lines changed

src/Data/Json/Extended/Signature/Parse.purs

+39-8
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import Prelude
1515
import Control.Alt ((<|>))
1616

1717
import Data.Array as A
18+
import Data.Char as Char
1819
import Data.Foldable as F
1920
import Data.HugeNum as HN
2021
import Data.HugeInt as HI
@@ -23,11 +24,13 @@ import Data.Json.Extended.Signature.Core (EJsonF(..), EJsonMap(..))
2324
import Data.List as L
2425
import Data.Maybe as M
2526
import Data.String as S
27+
import Data.Traversable (sequence)
2628
import Data.Tuple as T
2729

2830
import Text.Parsing.Parser as P
2931
import Text.Parsing.Parser.Combinators as PC
3032
import Text.Parsing.Parser.String as PS
33+
import Text.Parsing.Parser.Token as PT
3134

3235
squares
3336
m a
@@ -64,11 +67,29 @@ commaSep p = do
6467
pure o
6568

6669
stringInner m . Monad m P.ParserT String m String
67-
stringInner = A.many stringChar <#> S.fromCharArray
70+
stringInner = A.many charAtom <#> S.fromCharArray
6871
where
69-
stringChar = PC.try stringEscape <|> stringLetter
70-
stringLetter = PS.satisfy (_ /= '"')
71-
stringEscape = PS.string "\\\"" $> '"'
72+
charAtom = PC.tryRethrow do
73+
ch ← PS.anyChar
74+
case ch of
75+
'"'P.fail "Expected string character"
76+
'\\' → charEscape
77+
_ → pure ch
78+
79+
charEscape = do
80+
ch ← PS.anyChar
81+
case ch of
82+
't' → pure '\t'
83+
'r' → pure '\r'
84+
'n' → pure '\n'
85+
'u' → hexEscape
86+
_ → pure ch
87+
88+
hexEscape = do
89+
hex ← S.fromCharArray <$> sequence (A.replicate 4 PT.hexDigit)
90+
case Int.fromStringAs Int.hexadecimal hex of
91+
M.NothingP.fail "Expected character escape sequence"
92+
M.Just i → pure $ Char.fromCharCode i
7293

7394
quoted a m. Monad m P.ParserT String m a P.ParserT String m a
7495
quoted = PC.between quote quote
@@ -185,10 +206,20 @@ parseHugeNum
185206
. Monad m
186207
P.ParserT String m HN.HugeNum
187208
parseHugeNum = do
188-
chars ← A.many (PS.oneOf ['0','1','2','3','4','5','6','7','8','9','-','.']) <#> S.fromCharArray
189-
case HN.fromString chars of
209+
head ← parseDigits
210+
_ ← PS.char '.'
211+
str ← PC.tryRethrow do
212+
tail ← parseDigits
213+
when (tail == "") do
214+
P.fail "Expected decimal part"
215+
pure (head <> "." <> tail)
216+
case HN.fromString str of
190217
M.Just num → pure num
191-
M.NothingP.fail $ "Failed to parse decimal: " <> chars
218+
M.NothingP.fail $ "Failed to parse decimal: " <> str
219+
where
220+
parseDigits =
221+
S.fromCharArray
222+
<$> A.many (PS.oneOf ['0','1','2','3','4','5','6','7','8','9'])
192223

193224
parseScientific
194225
m
@@ -208,7 +239,7 @@ parseBooleanLiteral =
208239
]
209240

210241
parseDecimalLiteral m. Monad m P.ParserT String m HN.HugeNum
211-
parseDecimalLiteral = parseHugeNum <|> parseScientific
242+
parseDecimalLiteral = parseSigned (parseHugeNum <|> parseScientific)
212243

213244
parseHugeIntLiteral m. Monad m P.ParserT String m HI.HugeInt
214245
parseHugeIntLiteral = parseSigned (parseNat (HI.fromInt 10) HI.fromInt)

src/Data/Json/Extended/Signature/Render.purs

+10-13
Original file line numberDiff line numberDiff line change
@@ -4,39 +4,36 @@ module Data.Json.Extended.Signature.Render
44

55
import Prelude
66

7-
import Data.Either (fromRight)
87
import Data.Foldable as F
98
import Data.HugeInt as HI
109
import Data.HugeNum as HN
1110
import Data.Json.Extended.Signature.Core (EJsonF(..), EJsonMap(..))
12-
import Data.Maybe (fromMaybe)
1311
import Data.String as Str
14-
import Data.String.Regex as RX
15-
import Data.String.Regex.Flags as RXF
1612
import Data.Tuple as T
1713
import Matryoshka (Algebra)
18-
import Partial.Unsafe (unsafePartial)
1914

2015
renderEJsonF Algebra EJsonF String
2116
renderEJsonF = case _ of
2217
Null"null"
2318
Boolean b → if b then "true" else "false"
24-
Integer i →
25-
let s = HN.toString (HI.toHugeNum i)
26-
in fromMaybe s $ Str.stripSuffix (Str.Pattern ".0") s
19+
Integer i → Str.takeWhile (_ /= '.') $ HN.toString $ HI.toHugeNum i
2720
Decimal a → HN.toString a
2821
String str → stringEJson str
2922
Array ds → squares $ commaSep ds
3023
Map (EJsonMap ds) → braces $ renderPairs ds
3124

32-
replaceAll String String String String
33-
replaceAll i =
34-
RX.replace $ unsafePartial fromRight $ RX.regex i RXF.global
35-
3625
-- | Surround text in double quotes, escaping internal double quotes.
3726
stringEJson String String
3827
stringEJson str =
39-
"\"" <> replaceAll "\"" "\\\"" str <> "\""
28+
"\"" <> escaped <> "\""
29+
where
30+
escaped =
31+
str
32+
# Str.replaceAll (Str.Pattern "\\") (Str.Replacement "\\\\")
33+
# Str.replaceAll (Str.Pattern "\t") (Str.Replacement "\\t")
34+
# Str.replaceAll (Str.Pattern "\r") (Str.Replacement "\\r")
35+
# Str.replaceAll (Str.Pattern "\n") (Str.Replacement "\\n")
36+
# Str.replaceAll (Str.Pattern "\"") (Str.Replacement "\\\"")
4037

4138
commaSep Array String String
4239
commaSep = F.intercalate ", "

0 commit comments

Comments
 (0)