@@ -491,7 +491,7 @@ anyUntilPos pos =
491491
492492
493493
494−-- BASIC LANGUAGE LITERALS
494+-- SHADERS
495495
496496
497497shader :: IParser (String, L.GLShaderTipe)
@@ -565,38 +565,84 @@ glSource src =
565565 _ -> []
566566
567567
568+
569+-- STRINGS AND CHARACTERS
570+
571+
568572str :: IParser String
569573str =
570− expecting "a string" $
571− do s <- choice [ multiStr, singleStr ]
572− processAs T.stringLiteral . sandwich '\"' $ concat s
573− where
574− rawString quote insides =
575− quote >> manyTill insides quote
574+ expecting "a string like \"hello\"" $
575+ do charSeq <- choice [ multiStr, singleStr ]
576+ either (fail . show) return $
577+ processAs T.stringLiteral ('"' : charSeq ++ "\"")
578+
579+
580+delimitedSequence :: IParser a -> IParser String -> IParser String
581+delimitedSequence quote insides =
582+ do quote
583+ concat <$> manyTill insides quote
584+
585+
586+multiStr :: IParser String
587+multiStr =
588+ delimitedSequence (try (string "\"\"\"")) multilineStringChar
589+
590+
591+singleStr :: IParser String
592+singleStr =
593+ delimitedSequence (char '"') (charWithin '"')
594+
595+
596+chr :: IParser Char
597+chr =
598+ expecting "a character like 'x'" $
599+ do char '\''
600+ charSeq <- concat <$> many1 (charWithin '\'') <?> "a character"
601+ case processAs T.charLiteral ("'" ++ charSeq ++ "'") of
602+ Right character ->
603+ do char '\''
604+ return character
605+
606+ Left _ ->
607+ failure $
608+ "Elm uses double quotes for strings. Switch\
609+ \ the ' to \" on both ends of the string and\
610+ \ you should be all set!"
611+
612+
576613
577− multiStr = rawString (try (string "\"\"\"")) multilineStringChar
578− singleStr = rawString (char '"') stringChar
614+-- CHARACTER HELPERS
579615
580− stringChar :: IParser String
581− stringChar = choice [ newlineChar, escaped '\"', (:[]) <$> satisfy (/= '\"') ]
582616
583− multilineStringChar :: IParser String
584− multilineStringChar =
585− do noEnd
586− choice [ newlineChar, escaped '\"', expandQuote <$> anyChar ]
587− where
588− noEnd = notFollowedBy (string "\"\"\"")
589− expandQuote c = if c == '\"' then "\\\"" else [c]
617+charWithin :: Char -> IParser String
618+charWithin delim =
619+ choice
620+ [ escaped delim
621+ , (:[]) <$> satisfy (/= delim)
622+ ]
623+
590624
591− newlineChar :: IParser String
592− newlineChar =
593− choice [ char '\n' >> return "\\n"
594− , char '\r' >> return "\\r" ]
625+multilineStringChar :: IParser String
626+multilineStringChar =
627+ do notFollowedBy (string "\"\"\"")
628+ choice
629+ [ newlineChar
630+ , escaped '\"'
631+ , escapeQuotes <$> anyChar
632+ ]
595633
596634
597−sandwich :: Char -> String -> String
598−sandwich delim s =
599− delim : s ++ [delim]
635+escapeQuotes :: Char -> String
636+escapeQuotes c =
637+ if c == '\"' then "\\\"" else [c]
638+
639+
640+newlineChar :: IParser String
641+newlineChar =
642+ choice
643+ [ char '\n' >> return "\\n"
644+ , char '\r' >> return "\\r"
645+ ]
600646
601647
602648escaped :: Char -> IParser String
@@ -607,32 +653,16 @@ escaped delim =
607653 return ['\\', c]
608654
609655
610−chr :: IParser Char
611−chr =
612− betwixt '\'' '\'' character <?> "a character"
613− where
614− nonQuote = satisfy (/='\'')
615−
616− character =
617− do c <- choice
618− [ escaped '\''
619− , (:) <$> char '\\' <*> many1 nonQuote
620− , (:[]) <$> nonQuote
621− ]
622−
623− processAs T.charLiteral $ sandwich '\'' c
624−
625−
626−processAs :: (T.GenTokenParser String u SourceM -> IParser a) -> String -> IParser a
627−processAs processor s =
628− calloutParser s (processor lexer)
656+processAs
657+ :: (T.GenTokenParser String u SourceM -> IParser a)
658+ -> String
659+ -> Either ParseError a
660+processAs processor string =
661+ iParse (processor lexer) string
629662 where
630− calloutParser :: String -> IParser a -> IParser a
631− calloutParser inp p =
632− either (fail . show) return (iParse p inp)
633−
634663 lexer :: T.GenTokenParser String u SourceM
635− lexer = T.makeTokenParser elmDef
664+ lexer =
665+ T.makeTokenParser elmDef
636666
637667 -- I don't know how many of these are necessary for charLiteral/stringLiteral
638668 elmDef :: T.GenLanguageDef String u SourceM