1{-# OPTIONS_GHC -Wall -fno-warn-unused-do-bind #-}
2{-# LANGUAGE BangPatterns, MagicHash, OverloadedStrings, UnboxedTuples #-}
5 -- re-export from Json.Decode.Internals
7 , Json.string, Json.text, Json.name, Json.bool, Json.int
8 , Json.list, Json.dict, Json.pairs, Json.maybe
11 , Json.map, Json.map2, Json.mapError
12 , Json.succeed, Json.fail
13 , Json.andThen, Json.oneOf
18import Prelude hiding (length)
19import qualified Data.ByteString.Char8 as Char8
20import qualified Data.ByteString.Internal as B
21import qualified Data.HashMap.Strict as HashMap
22import qualified Data.Text as Text
23import qualified Data.Text.Encoding as Text
24import qualified Data.Vector as Vector
25import Foreign.ForeignPtr (ForeignPtr)
26import GHC.Word (Word8(..))
28import qualified Json.Decode.Internals as Json
29import qualified Parse.Primitives as P
30import qualified Parse.Primitives.Internals as I
31import Parse.Primitives.Internals (Parser(..), State(..), noError)
32import qualified Parse.Primitives.Keyword as Keyword
33import qualified Parse.Primitives.Number as Number
34import qualified Parse.Primitives.Symbol as Symbol
35import qualified Reporting.Error.Syntax as E
36import qualified Reporting.Error.Json as J
37import qualified Reporting.Helpers as H
38import qualified Reporting.Region as R
39import qualified Reporting.Render.Code as Code
46parse :: FilePath -> String -> (e -> [H.Doc]) -> Json.Decoder e a -> B.ByteString -> Either H.Doc a
47parse path rootName userErrorToDocs (Json.Decoder run) bytestring =
50 Code.toSource (Text.replace "\t" " " (Text.decodeUtf8 bytestring))
53 J.toDoc path rootName source userErrorToDocs err
55 case P.run jsonFile bytestring of
57 Left (toDoc (J.BadJson err))
62 Left (toDoc (J.BadContent err))
72jsonFile :: Parser Json.Value
81jsonValue :: Parser Json.Value
83 do start <- P.getPosition
85 [ Json.String <$> string
89 , Keyword.jsonTrue >> return Json.TRUE
90 , Keyword.jsonFalse >> return Json.FALSE
91 , Keyword.jsonNull >> return Json.NULL
99object :: R.Position -> Parser Json.Value
102 P.inContext start E.ExprRecord $
108 , do Symbol.rightCurly
109 return (Json.Object [] HashMap.empty)
113objectHelp :: [(Text.Text, Json.Value)] -> Parser Json.Value
114objectHelp revEntries =
121 objectHelp (entry:revEntries)
124 return (Json.Object (reverse revEntries) (HashMap.fromList revEntries))
128field :: Parser (Text.Text, Json.Value)
142array :: R.Position -> Parser Json.Value
145 P.inContext start E.ExprList $
148 [ do entry <- jsonValue
151 , do Symbol.rightSquare
152 return (Json.Array Vector.empty)
156arrayHelp :: Int -> [Json.Value] -> Parser Json.Value
157arrayHelp !length revEntries =
164 arrayHelp (length + 1) (entry:revEntries)
166 do Symbol.rightSquare
167 return $ Json.Array $ Vector.reverse $
168 Vector.fromListN length revEntries
176number :: Parser Json.Value
178 Parser $ \(State fp offset terminal indent row col ctx) cok cerr _ eerr ->
179 if offset < terminal then
182 !word = I.unsafeIndex fp offset
183 !offset1 = offset + 1
185 if word <= 0x39 {- 9 -} && word >= 0x31 {- 1 -} then
186 case Number.chompInt fp offset1 terminal (fromIntegral (word - 0x30 {- 0 -})) of
187 Number.Err newOffset problem ->
188 cerr (E.ParseError row (col + (newOffset - offset)) problem)
190 Number.OkInt newOffset n ->
192 !newState = State fp newOffset terminal indent row (col + (newOffset - offset)) ctx
194 cok (Json.Integer n) newState noError
196 Number.OkFloat newOffset ->
198 !length = newOffset - offset
199 !scientific = read $ Char8.unpack $ B.PS fp offset length
200 !newState = State fp newOffset terminal indent row (col + length) ctx
202 cok (Json.Float scientific) newState noError
204 else if word == 0x30 {- 0 -} then
205 cok (Json.Integer 0) (State fp offset1 terminal indent row (col + 1) ctx) noError
219string :: Parser Text.Text
221 Parser $ \(State fp offset terminal indent row col ctx) cok cerr _ eerr ->
222 if offset < terminal && I.unsafeIndex fp offset == 0x22 {- " -} then
225 !offset1 = offset + 1
227 case stringHelp fp offset1 terminal row (col + 1) of
231 Ok newOffset newRow newCol ->
233 !newState = State fp newOffset terminal indent newRow newCol ctx
234 !content = Text.decodeUtf8 (B.PS fp offset1 (newOffset - offset1 - 1))
236 cok content newState noError
247stringHelp :: ForeignPtr Word8 -> Int -> Int -> Int -> Int -> StringResult
248stringHelp fp offset terminal row col =
249 if offset >= terminal then
250 Err (E.ParseError row col E.EndOfFile_String)
253 case I.unsafeIndex fp offset of
255 Ok (offset + 1) row (col + 1)
258 Err (E.ParseError row col E.NewLineInString)
262 !offset1 = offset + 1
264 if offset1 < terminal then
267 !word = I.unsafeIndex fp offset1
268 !newOffset = offset1 + I.getCharWidth fp offset1 terminal word
270 stringHelp fp newOffset terminal row (col + 2)
273 Err (E.ParseError (row + 1) col E.EndOfFile_String)
276 let !newOffset = offset + I.getCharWidth fp offset terminal word in
277 stringHelp fp newOffset terminal row (col + 1)
287 Parser $ \(State fp offset terminal indent row col ctx) cok _ _ _ ->
289 (# newOffset, newRow, newCol #) =
290 eatSpaces fp offset terminal row col
293 State fp newOffset terminal indent newRow newCol ctx
295 cok () newState noError
298eatSpaces :: ForeignPtr Word8 -> Int -> Int -> Int -> Int -> (# Int, Int, Int #)
299eatSpaces fp offset terminal row col =
300 if offset >= terminal then
301 (# offset, row, col #)
304 case I.unsafeIndex fp offset of
305 0x20 {- -} -> eatSpaces fp (offset + 1) terminal row (col + 1)
306 0x09 {- \t -} -> eatSpaces fp (offset + 1) terminal row (col + 1)
307 0x0A {- \n -} -> eatSpaces fp (offset + 1) terminal (row + 1) 1
308 0x0D {- \r -} -> eatSpaces fp (offset + 1) terminal row col
310 (# offset, row, col #)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list