@@ -9,7 +9,7 @@ module Parse.Primitives
9 , lowVar, capVar, infixOp
9 , lowVar, capVar, infixOp
10 , getPosition, getCol
10 , getPosition, getCol
11 , getIndent, setIndent
11 , getIndent, setIndent
12− , Space(..), whitespace
12+ , SPos(..), whitespace
13 , docComment
13 , docComment
14 , string, character
14 , string, character
15 , digit, number
15 , digit, number
@@ -166,8 +166,8 @@ oneOf parsers =
167allTheOptionsFailed :: Parser a
167allTheOptionsFailed :: Parser a
168allTheOptionsFailed =
168allTheOptionsFailed =
169− Parser $ \_ _ _ _ eerr ->
169+ Parser $ \(State _ _ _ _ row col) _ _ _ eerr ->
170− eerr $ error "TODO allTheOptionsFailed"
170+ eerr (Error row col)
173oneOfHelp :: Parser a -> Parser a -> Parser a
173oneOfHelp :: Parser a -> Parser a -> Parser a
@@ -177,7 +177,7 @@ oneOfHelp parser1 parser2 =
177 meerr err =
177 meerr err =
179 neok y state' = eok y state'
179 neok y state' = eok y state'
180− neerr err' = eerr (error "TODO oneOfHelp" err err')
180+ neerr _err' = eerr err -- TODO merge things properly
182 _run parser2 state cok cerr neok neerr
182 _run parser2 state cok cerr neok neerr
@@ -199,14 +199,14 @@ instance Monad Parser where
199 cok' x state1 =
199 cok' x state1 =
201 peok y state2 = cok y state2
201 peok y state2 = cok y state2
202− peerr err = cerr (error "TODO >>= cok" err)
202+ peerr err = cerr err -- TODO is this correct?
204 _run (callback x) state1 cok cerr peok peerr
204 _run (callback x) state1 cok cerr peok peerr
206 eok' x state1 =
206 eok' x state1 =
208 peok y state2 = eok y state2
208 peok y state2 = eok y state2
209− peerr err = eerr (error "TODO >>= eok" err)
209+ peerr err = eerr err -- TODO is this correct?
211 _run (callback x) state1 cok cerr peok peerr
211 _run (callback x) state1 cok cerr peok peerr
@@ -228,7 +228,7 @@ text (Text.Text tArray tOffset tLen) =
228 cok () (State array (offset + tLen) (length - tLen) indent newRow newCol)
228 cok () (State array (offset + tLen) (length - tLen) indent newRow newCol)
231− eerr (error "TODO text")
231+ eerr (Error row col)
234moveCursor :: Text.Array -> Int -> Int -> Int -> Int -> (# Int, Int #)
234moveCursor :: Text.Array -> Int -> Int -> Int -> Int -> (# Int, Int #)
@@ -259,7 +259,7 @@ keyword (Text.Text tArray tOffset tLen) =
259 Parser $ \(State array offset length indent row col) cok _ _ eerr ->
259 Parser $ \(State array offset length indent row col) cok _ _ eerr ->
260 if tLen <= length && Text.equal tArray tOffset array offset tLen then
260 if tLen <= length && Text.equal tArray tOffset array offset tLen then
262− if Char.isAlphaNum (peekChar array (offset + tLen)) then
262+ if isInnerVarChar (peekChar array (offset + tLen)) then
263 eerr (error "TODO keyword 1")
263 eerr (error "TODO keyword 1")
@@ -269,7 +269,7 @@ keyword (Text.Text tArray tOffset tLen) =
269 cok () (State array (offset + tLen) (length - tLen) indent newRow newCol)
269 cok () (State array (offset + tLen) (length - tLen) indent newRow newCol)
272− eerr (error "TODO keyword 2")
272+ eerr (Error row col)
275keywords :: Set.Set Text
275keywords :: Set.Set Text
@@ -369,13 +369,19 @@ varPrimHelp array offset length col =
370 (Text.Iter char size) = peek array offset -- TODO look for latin chars directly?
370 (Text.Iter char size) = peek array offset -- TODO look for latin chars directly?
372− if Char.isAlphaNum char || char == '_' then
372+ if isInnerVarChar char then
373 varPrimHelp array (offset + size) (length - size) (col + 1)
373 varPrimHelp array (offset + size) (length - size) (col + 1)
376 (# offset, length, col #)
376 (# offset, length, col #)
379+{-# INLINE isInnerVarChar #-}
380+isInnerVarChar :: Char -> Bool
381+isInnerVarChar char =
382+ Char.isAlphaNum char || char == '_'
380-- INFIX OPS
386-- INFIX OPS
@@ -461,16 +467,11 @@ setIndent indent =
461-- WHITESPACE
467-- WHITESPACE
464−data Space
470+newtype SPos =
465− = None
471+ SPos Region.Position
473−whitespace :: Parser Space
474+whitespace :: Parser SPos
474whitespace =
475whitespace =
475 Parser $ \(State array offset length indent row col) cok cerr _ _ ->
476 Parser $ \(State array offset length indent row col) cok cerr _ _ ->
476 case eatSpaces array offset length row col of
477 case eatSpaces array offset length row col of
@@ -478,20 +479,9 @@ whitespace =
480 Right (newOffset, newLength, newRow, newCol) ->
481 Right (newOffset, newLength, newRow, newCol) ->
482− !space =
483+ (SPos (Region.Position newRow newCol))
483− if newOffset == offset then
484− None -- TODO empty success?
485− else if newCol == 1 then
487− else if newCol > indent then
489− else if newCol == indent then
494− cok space (State array newOffset newLength indent newRow newCol)
484+ (State array newOffset newLength indent newRow newCol)
497eatSpaces :: Text.Array -> Int -> Int -> Int -> Int -> Either Error ( Int, Int, Int, Int )
487eatSpaces :: Text.Array -> Int -> Int -> Int -> Int -> Either Error ( Int, Int, Int, Int )
@@ -661,16 +651,26 @@ string =
661 if word /= 0x0022 {- " -} then
651 if word /= 0x0022 {- " -} then
662 eerr (Error row col)
652 eerr (Error row col)
664− else if Text.unsafeIndex array (offset + 1) == 0x0022 {- " -} && Text.unsafeIndex array (offset + 2) == 0x0022 {- " -} then
665− error "TODO multiString"
657+ if length >= 3 && isQuote array (offset + 1) && isQuote array (offset + 2) then
658+ multiString array (offset + 3) (length - 3) row (col + 3) (offset + 3) mempty
668− case singleString array (offset + 1) (length - 1) row (col + 1) (offset + 1) mempty of
660+ singleString array (offset + 1) (length - 1) row (col + 1) (offset + 1) mempty
662+ case stringResult of
669− Left msg ->
663+ Left msg ->
670− cerr msg
664+ cerr msg
666+ Right ( newOffset, newLength, newCol, str ) ->
667+ cok str (State array newOffset newLength indent row newCol)
672− Right ( newOffset, newLength, newCol, str ) ->
669+
673− cok str (State array newOffset newLength indent row newCol)
670+{-# INLINE isQuote #-}
671+isQuote :: Text.Array -> Int -> Bool
672+isQuote array offset =
673+ Text.unsafeIndex array offset == 0x0022 {- " -}
@@ -744,7 +744,7 @@ eatEscape array offset length row col =
745 Just (newOffset, code) ->
745 Just (newOffset, code) ->
746 if code <= 0x10FFFF then
746 if code <= 0x10FFFF then
747− Right ( newOffset - offset + 1, toEnum (fromInteger code) )
747+ Right ( 1 + (newOffset - offset), toEnum (fromInteger code) )
749 Left (Error row col)
749 Left (Error row col)
@@ -754,7 +754,7 @@ eatEscape array offset length row col =
755eatHex :: Text.Array -> Int -> Int -> Integer -> Maybe ( Int, Integer )
755eatHex :: Text.Array -> Int -> Int -> Integer -> Maybe ( Int, Integer )
756eatHex array offset length n =
756eatHex array offset length n =
757− if length == 0 then
757+ if length < 3 then
@@ -775,6 +775,50 @@ eatHex array offset length n =
781+multiString :: Text.Array -> Int -> Int -> Int -> Int -> Int -> LB.Builder -> Either Error ( Int, Int, Int, Text.Text )
782+multiString array offset length row col initialOffset builder =
784+ Left (Error row col)
788+ !word = Text.unsafeIndex array offset
790+ if word == 0x0022 {- " -} && isQuote array (offset + 1) && isQuote array (offset + 2) then
793+ mappend builder $ LB.fromText $
794+ Text.Text array initialOffset (offset - initialOffset)
797+ LT.toStrict (LB.toLazyTextWith (offset - initialOffset) finalBuilder)
799+ Right ( offset + 3, length - 3, col + 3, str )
801+ else if word == 0x005C {- \ -} then
802+ case eatEscape array (offset + 1) (length - 1) row (col + 1) of
806+ Right ( size, char ) ->
808+ !newOffset = offset + size
809+ chunk = Text.Text array initialOffset (offset - initialOffset)
810+ newBuilder = mappend builder (mappend (LB.fromText chunk) (LB.singleton char))
812+ multiString array newOffset (length - size) row (col + size) newOffset newBuilder
814+ else if word < 0xD800 || word > 0xDBFF then
815+ multiString array (offset + 1) (length - 1) row (col + 1) initialOffset builder
818+ multiString array (offset + 2) (length - 2) row (col + 1) initialOffset builder
778-- CHARACTER
822-- CHARACTER
@@ -798,14 +842,14 @@ character =
799 Right ( size, char ) ->
843 Right ( size, char ) ->
801− !newOffset = offset + size
845+ !newOffset = offset + size + 1
802− !newLength = length + size
846+ !newLength = length - size - 1
804 if newLength == 0 then
848 if newLength == 0 then
805 cerr (Error row col)
849 cerr (Error row col)
807 else if Text.unsafeIndex array newOffset == 0x0027 {- ' -} then
851 else if Text.unsafeIndex array newOffset == 0x0027 {- ' -} then
808− cok char (State array newOffset newLength indent row (col + size + 2))
852+ cok char (State array (newOffset + 1) (newLength - 1) indent row (col + size + 2))
811 cerr (Error row col)
855 cerr (Error row col)
@@ -828,7 +872,7 @@ characterHelp array offset length row col =
828 else if word < 0xD800 || word > 0xDBFF then
872 else if word < 0xD800 || word > 0xDBFF then
829 Right (1, unsafeChr word)
873 Right (1, unsafeChr word)
831− else if length > 0 then
875+ else if length > 2 then
832 Right (2, chr2 word (Text.unsafeIndex array offset))
876 Right (2, chr2 word (Text.unsafeIndex array offset))