summaryrefslogtreecommitdiff
path: root/src/runtime/haskell
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/haskell')
-rw-r--r--src/runtime/haskell/PGF/CId.hs49
1 files changed, 43 insertions, 6 deletions
diff --git a/src/runtime/haskell/PGF/CId.hs b/src/runtime/haskell/PGF/CId.hs
index 6a20cb4f3..0594d9fc1 100644
--- a/src/runtime/haskell/PGF/CId.hs
+++ b/src/runtime/haskell/PGF/CId.hs
@@ -7,6 +7,7 @@ module PGF.CId (CId(..),
import Control.Monad
import qualified Data.ByteString.Char8 as BS
+import qualified Data.ByteString.UTF8 as UTF8
import Data.Char
import qualified Text.ParserCombinators.ReadP as RP
import qualified Text.PrettyPrint as PP
@@ -21,7 +22,7 @@ wildCId = CId (BS.singleton '_')
-- | Creates a new identifier from 'String'
mkCId :: String -> CId
-mkCId s = CId (BS.pack s)
+mkCId s = CId (UTF8.fromString s)
bsCId = CId
@@ -33,7 +34,18 @@ readCId s = case [x | (x,cs) <- RP.readP_to_S pCId s, all isSpace cs] of
-- | Renders the identifier as 'String'
showCId :: CId -> String
-showCId (CId x) = BS.unpack x
+showCId (CId x) =
+ let raw = UTF8.toString x
+ in if isIdent raw
+ then raw
+ else "'" ++ concatMap escape raw ++ "'"
+ where
+ isIdent [] = False
+ isIdent (c:cs) = isIdentFirst c && all isIdentRest cs
+
+ escape '\'' = "\\\'"
+ escape '\\' = "\\\\"
+ escape c = [c]
instance Show CId where
showsPrec _ = showString . showCId
@@ -48,10 +60,35 @@ pCId = do s <- pIdent
else return (mkCId s)
pIdent :: RP.ReadP String
-pIdent = liftM2 (:) (RP.satisfy isIdentFirst) (RP.munch isIdentRest)
- where
- isIdentFirst c = c == '_' || isLetter c
- isIdentRest c = c == '_' || c == '\'' || isAlphaNum c
+pIdent =
+ liftM2 (:) (RP.satisfy isIdentFirst) (RP.munch isIdentRest)
+ `mplus`
+ do RP.char '\''
+ cs <- RP.many1 insideChar
+ RP.char '\''
+ return cs
+-- where
+insideChar = RP.readS_to_P $ \s ->
+ case s of
+ [] -> []
+ ('\\':'\\':cs) -> [('\\',cs)]
+ ('\\':'\'':cs) -> [('\'',cs)]
+ ('\\':cs) -> []
+ ('\'':cs) -> []
+ (c:cs) -> [(c,cs)]
+
+isIdentFirst c =
+ (c == '_') ||
+ (c >= 'a' && c <= 'z') ||
+ (c >= 'A' && c <= 'Z') ||
+ (c >= '\192' && c <= '\255' && c /= '\247' && c /= '\215')
+isIdentRest c =
+ (c == '_') ||
+ (c == '\'') ||
+ (c >= '0' && c <= '9') ||
+ (c >= 'a' && c <= 'z') ||
+ (c >= 'A' && c <= 'Z') ||
+ (c >= '\192' && c <= '\255' && c /= '\247' && c /= '\215')
ppCId :: CId -> PP.Doc
ppCId = PP.text . showCId