on 2deedfb help sign in
elk/src/Parse/Primitives/Kernel.hs
118 lines 3.0 kB history raw
1{-# OPTIONS_GHC -Wall -fno-warn-unused-do-bind #-}
2{-# LANGUAGE BangPatterns, UnboxedTuples, OverloadedStrings #-}
3module Parse.Primitives.Kernel
4 ( Special(..)
5 , chunk
6 )
7 where
10import Prelude hiding (length)
11import qualified Data.ByteString.Internal as B
12import qualified Data.Text.Encoding as Text
13import Data.Text (Text)
14import Data.Word (Word8)
15import Foreign.ForeignPtr (ForeignPtr)
17import qualified Elm.Name as N
18import Parse.Primitives.Internals (Parser(..), State(..), noError)
19import qualified Parse.Primitives.Internals as I
20import qualified Parse.Primitives.Variable as Var
24-- SPECIAL
27data Special
28 = Enum Word8 Text
29 | Prod
30 | Debug
31 | Import Text
32 | JsField Text
33 | ElmField N.Name
37-- CHUNK
40chunk :: Parser (B.ByteString, Maybe Special)
41chunk =
42 Parser $ \(State fp offset terminal indent row col ctx) cok _ _ _ ->
43 let
44 (# maybeSpecial, jsOffset, newOffset, newRow, newCol #) =
45 chompChunk fp offset terminal row col
47 !javascript = B.PS fp offset (jsOffset - offset)
48 !newState = State fp newOffset terminal indent newRow newCol ctx
49 in
50 cok (javascript, maybeSpecial) newState noError
54-- CHOMP CHUNK
57chompChunk :: ForeignPtr Word8 -> Int -> Int -> Int -> Int -> (# Maybe Special, Int, Int, Int, Int #)
58chompChunk fp offset terminal row col =
59 if offset >= terminal then
60 (# Nothing, offset, offset, row, col #)
62 else
63 let !word = I.unsafeIndex fp offset in
64 if word == 0x5F {- _ -} then
66 let
67 !offset1 = offset + 1
68 !offset3 = offset + 3
69 in
70 if offset3 <= terminal && I.unsafeIndex fp offset1 == 0x5F {- _ -} then
71 chompSpecial fp offset3 terminal row (col + 3) offset
72 else
73 chompChunk fp offset1 terminal row (col + 1)
75 else if word == 0x0A {- \n -} then
76 chompChunk fp (offset + 1) terminal (row + 1) 1
78 else
79 let !newOffset = offset + I.getCharWidth fp offset terminal word in
80 chompChunk fp newOffset terminal row (col + 1)
84-- CHOMP TAG
87-- relies on external checks in chompChunk
88chompSpecial :: ForeignPtr Word8 -> Int -> Int -> Int -> Int -> Int -> (# Maybe Special, Int, Int, Int, Int #)
89chompSpecial fp offset terminal row col jsOffset =
90 let
91 (# newOffset, newCol #) =
92 Var.chompInnerChars fp offset terminal col
94 !tagOffset = offset - 1
95 !word = I.unsafeIndex fp tagOffset
97 !special =
98 if word == 0x24 {- $ -} then
99 ElmField (Text.decodeUtf8 (B.PS fp offset (newOffset - offset)))
101 else
102 let !name = Text.decodeUtf8 (B.PS fp tagOffset (newOffset - tagOffset)) in
103 if 0x30 <= word && word <= 0x39 then
104 Enum (fromIntegral (word - 0x30)) name
106 else if 0x61 {- a -} <= word && word <= 0x7A {- z -} then
107 JsField name
109 else if name == "DEBUG" then
110 Debug
112 else if name == "PROD" then
113 Prod
115 else
116 Import name
117 in
118 (# Just special, jsOffset, newOffset, row, newCol #)