on c19392f help sign in
elk/src/Parse/Primitives/Kernel.hs
117 lines 2.9 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 Parse.Primitives.Internals (Parser(..), State(..), noError)
18import qualified Parse.Primitives.Internals as I
19import qualified Parse.Primitives.Variable as Var
23-- SPECIAL
26data Special
27 = Enum Word8 Text
28 | Prod
29 | Debug
30 | Import Text
31 | JsField Text
32 | ElmField Text
36-- CHUNK
39chunk :: Parser (B.ByteString, Maybe Special)
40chunk =
41 Parser $ \(State fp offset terminal indent row col ctx) cok _ _ _ ->
42 let
43 (# maybeSpecial, jsOffset, newOffset, newRow, newCol #) =
44 chompChunk fp offset terminal row col
46 !javascript = B.PS fp offset (jsOffset - offset)
47 !newState = State fp newOffset terminal indent newRow newCol ctx
48 in
49 cok (javascript, maybeSpecial) newState noError
53-- CHOMP CHUNK
56chompChunk :: ForeignPtr Word8 -> Int -> Int -> Int -> Int -> (# Maybe Special, Int, Int, Int, Int #)
57chompChunk fp offset terminal row col =
58 if offset >= terminal then
59 (# Nothing, offset, offset, row, col #)
61 else
62 let !word = I.unsafeIndex fp offset in
63 if word == 0x5F {- _ -} then
65 let
66 !offset1 = offset + 1
67 !offset3 = offset + 3
68 in
69 if offset3 <= terminal && I.unsafeIndex fp offset1 == 0x5F {- _ -} then
70 chompSpecial fp offset3 terminal row (col + 3) offset
71 else
72 chompChunk fp offset1 terminal row (col + 1)
74 else if word == 0x0A {- \n -} then
75 chompChunk fp (offset + 1) terminal (row + 1) 1
77 else
78 let !newOffset = offset + I.getCharWidth fp offset terminal word in
79 chompChunk fp newOffset terminal row (col + 1)
83-- CHOMP TAG
86-- relies on external checks in chompChunk
87chompSpecial :: ForeignPtr Word8 -> Int -> Int -> Int -> Int -> Int -> (# Maybe Special, Int, Int, Int, Int #)
88chompSpecial fp offset terminal row col jsOffset =
89 let
90 (# newOffset, newCol #) =
91 Var.chompInnerChars fp offset terminal col
93 !tagOffset = offset - 1
94 !word = I.unsafeIndex fp tagOffset
96 !special =
97 if word == 0x24 {- $ -} then
98 ElmField (Text.decodeUtf8 (B.PS fp offset (newOffset - offset)))
100 else
101 let !name = Text.decodeUtf8 (B.PS fp tagOffset (newOffset - tagOffset)) in
102 if 0x30 <= word && word <= 0x39 then
103 Enum (fromIntegral (word - 0x30)) name
105 else if 0x61 {- a -} <= word && word <= 0x7A {- z -} then
106 JsField name
108 else if name == "DEBUG" then
109 Debug
111 else if name == "PROD" then
112 Prod
114 else
115 Import name
116 in
117 (# Just special, jsOffset, newOffset, row, newCol #)