on master help sign in
Start escaping \n in multi-line strings and \' in all strings
9a407c5Evan Czaplicki
src/Parse/Primitives.hs+43−17
@@ -20,6 +20,7 @@ import Prelude hiding (length)
20import qualified Control.Applicative as Applicative ( Applicative(..), Alternative(..) )
20import qualified Control.Applicative as Applicative ( Applicative(..), Alternative(..) )
21import Control.Monad
21import Control.Monad
22import qualified Data.Char as Char
22import qualified Data.Char as Char
23+import Data.Monoid ((<>))
23import qualified Data.Set as Set
24import qualified Data.Set as Set
24import Data.Text (Text)
25import Data.Text (Text)
25import qualified Data.Text as Text
26import qualified Data.Text as Text
@@ -688,8 +689,10 @@ string =
688 Left err ->
689 Left err ->
689 cerr err
690 cerr err
690
691
691− Right ( newOffset, newLength, newCol, str ) ->
692+ Right ( newOffset, newLength, newCol, builder ) ->
693+ cok
694+ (LT.toStrict (LB.toLazyText builder))
692− cok str (State array newOffset newLength indent row newCol)
695+ (State array newOffset newLength indent row newCol)
693
696
694
697
695{-# INLINE isQuote #-}
698{-# INLINE isQuote #-}
@@ -702,7 +705,7 @@ isQuote array offset =
702-- SINGLE STRINGS
705-- SINGLE STRINGS
703
706
704
707
705−singleString :: Text.Array -> Int -> Int -> Int -> Int -> Int -> LB.Builder -> Either ParseError ( Int, Int, Int, Text.Text )
708+singleString :: Text.Array -> Int -> Int -> Int -> Int -> Int -> LB.Builder -> Either ParseError ( Int, Int, Int, LB.Builder )
706singleString array offset length row col initialOffset builder =
709singleString array offset length row col initialOffset builder =
707 if length == 0 then
710 if length == 0 then
708 Left (ParseError row col EndOfFile_String)
711 Left (ParseError row col EndOfFile_String)
@@ -716,15 +719,21 @@ singleString array offset length row col initialOffset builder =
716 finalBuilder =
719 finalBuilder =
717 mappend builder $ LB.fromText $
720 mappend builder $ LB.fromText $
718 Text.Text array initialOffset (offset - initialOffset)
721 Text.Text array initialOffset (offset - initialOffset)
719−
720− str =
721− LT.toStrict (LB.toLazyTextWith (offset - initialOffset) finalBuilder)
722 in
722 in
723− Right ( offset + 1, length - 1, col + 1, str )
723+ Right ( offset + 1, length - 1, col + 1, finalBuilder )
724
724
725 else if word == 0x000A {- \n -} then
725 else if word == 0x000A {- \n -} then
726 Left (ParseError row col NewLineInString)
726 Left (ParseError row col NewLineInString)
727
727
728+ else if word == 0x0027 {- ' -} then
729+
730+ let
731+ !newOffset = offset + 1
732+ chunk = Text.Text array initialOffset (offset - initialOffset)
733+ newBuilder = builder <> LB.fromText chunk <> LB.fromText "\\'"
734+ in
735+ singleString array newOffset (length - 1) row (col + 1) newOffset newBuilder
736+
728 else if word == 0x005C {- \ -} then
737 else if word == 0x005C {- \ -} then
729 case eatEscape array (offset + 1) (length - 1) row (col + 1) EndOfFile_String of
738 case eatEscape array (offset + 1) (length - 1) row (col + 1) EndOfFile_String of
730 Left err ->
739 Left err ->
@@ -734,7 +743,7 @@ singleString array offset length row col initialOffset builder =
734 let
743 let
735 !newOffset = offset + size
744 !newOffset = offset + size
736 chunk = Text.Text array initialOffset (offset - initialOffset)
745 chunk = Text.Text array initialOffset (offset - initialOffset)
737− newBuilder = mappend builder (mappend (LB.fromText chunk) (LB.singleton char))
746+ newBuilder = builder <> LB.fromText chunk <> LB.singleton char
738 in
747 in
739 singleString array newOffset (length - size) row (col + size) newOffset newBuilder
748 singleString array newOffset (length - size) row (col + size) newOffset newBuilder
740
749
@@ -803,9 +812,9 @@ eatHex array offset length n =
803-- MULTI STRINGS
812-- MULTI STRINGS
804
813
805
814
806−multiString :: Text.Array -> Int -> Int -> Int -> Int -> Int -> LB.Builder -> Either ParseError ( Int, Int, Int, Text.Text )
815+multiString :: Text.Array -> Int -> Int -> Int -> Int -> Int -> LB.Builder -> Either ParseError ( Int, Int, Int, LB.Builder )
807multiString array offset length row col initialOffset builder =
816multiString array offset length row col initialOffset builder =
808− if length == 0 then
817+ if length < 3 then
809 Left (ParseError row col EndOfFile_MultiString)
818 Left (ParseError row col EndOfFile_MultiString)
810
819
811 else
820 else
@@ -813,17 +822,34 @@ multiString array offset length row col initialOffset builder =
813 !word = Text.unsafeIndex array offset
822 !word = Text.unsafeIndex array offset
814 in
823 in
815 if word == 0x0022 {- " -} && isQuote array (offset + 1) && isQuote array (offset + 2) then
824 if word == 0x0022 {- " -} && isQuote array (offset + 1) && isQuote array (offset + 2) then
825+
826+ let
827+ finalBuilder =
828+ mappend builder $ LB.fromText $
829+ Text.Text array initialOffset (offset - initialOffset)
830+ in
831+ Right ( offset + 3, length - 3, col + 3, finalBuilder )
832+
833+ else if word == 0x0027 {- ' -} then
834+
816 let
835 let
817− finalBuilder =
836+ !newOffset = offset + 1
837+ chunk = Text.Text array initialOffset (offset - initialOffset)
818− mappend builder $ LB.fromText $
838+ newBuilder = builder <> LB.fromText chunk <> LB.fromText "\\'"
819− Text.Text array initialOffset (offset - initialOffset)
839+ in
840+ multiString array newOffset (length - 1) row (col + 1) newOffset newBuilder
841+
842+ else if word == 0x000A {- \n -} then
820
843
821− str =
844+ let
822− LT.toStrict (LB.toLazyTextWith (offset - initialOffset) finalBuilder)
845+ !newOffset = offset + 1
846+ chunk = Text.Text array initialOffset (offset - initialOffset)
847+ newBuilder = builder <> LB.fromText chunk <> LB.fromText "\\n"
823 in
848 in
824− Right ( offset + 3, length - 3, col + 3, str )
849+ multiString array newOffset (length - 1) (row + 1) 1 newOffset newBuilder
825
850
826 else if word == 0x005C {- \ -} then
851 else if word == 0x005C {- \ -} then
852+
827 case eatEscape array (offset + 1) (length - 1) row (col + 1) EndOfFile_MultiString of
853 case eatEscape array (offset + 1) (length - 1) row (col + 1) EndOfFile_MultiString of
828 Left err ->
854 Left err ->
829 Left err
855 Left err
@@ -832,7 +858,7 @@ multiString array offset length row col initialOffset builder =
832 let
858 let
833 !newOffset = offset + size
859 !newOffset = offset + size
834 chunk = Text.Text array initialOffset (offset - initialOffset)
860 chunk = Text.Text array initialOffset (offset - initialOffset)
835− newBuilder = mappend builder (mappend (LB.fromText chunk) (LB.singleton char))
861+ newBuilder = builder <> LB.fromText chunk <> LB.singleton char
836 in
862 in
837 multiString array newOffset (length - size) row (col + size) newOffset newBuilder
863 multiString array newOffset (length - size) row (col + size) newOffset newBuilder
838
864