on master help sign in
Switch over to a CPS-based parsing monad

Doesn't actually seem to make a difference to performance :-\ --HG-- extra : convert_revision : 1887119c5984456a177bbe260141bd5abfedb976

commitdf833803ed2926e7106765bf2b520ef109424a62 authorBryan O'Sullivan <bos@serpentine.com> dateFri 8 Oct 2010, 20:14 (16 years ago) parent6f8e914
1 file changed+26−20
Data/Text/Lex.hs+26−20
Data/Text/Lex.hs+26−20
@@ -1,4 +1,4 @@
1−{-# LANGUAGE OverloadedStrings #-}
1+{-# LANGUAGE OverloadedStrings, Rank2Types #-}
22
33-- |
44-- Module : Data.Text.Lex
@@ -69,7 +69,7 @@ hexDigitToInt c
6969-- to the result of applying the given reader.
7070signed :: Num a => Lexer a -> Lexer a
7171{-# INLINE signed #-}
72−signed f = runP (signa (P f))
72+signed f = parse (signa (asP f))
7373
7474signa :: Num a => Parser a -> Parser a
7575{-# SPECIALIZE signa :: Parser Int -> Parser Int #-}
@@ -79,39 +79,46 @@ signa p = do
7979 if sign == '+' then p else negate `liftM` p
8080
8181newtype Parser a = P {
82− runP :: Text -> Either String (a,Text)
82+ runP :: forall r.
83+ (String -> Either String (r,Text))
84+ -> (a -> Text -> Either String (r,Text))
85+ -> Text -> Either String (r,Text)
8386 }
8487
88+parse :: Parser a -> Text -> Either String (a,Text)
89+parse p t = runP p Left (\a t' -> Right (a,t')) t
90+
8591instance Monad Parser where
86− return a = P $ \t -> Right (a,t)
92+ return a = P $ \kf ks t -> ks a t
8793 {-# INLINE return #-}
88− m >>= k = P $ \t -> case runP m t of
89− Left err -> Left err
90− Right (a,t') -> runP (k a) t'
94+ m >>= k = P $ \kf ks t -> runP m kf (\a t' -> runP (k a) kf ks t') t
9195 {-# INLINE (>>=) #-}
92− fail msg = P $ \_ -> Left msg
96+ fail msg = P $ \kf ks t -> kf msg
9397
9498perhaps :: a -> Parser a -> Parser a
95−perhaps def m = P $ \t -> case runP m t of
96− Left _ -> Right (def,t)
97− r@(Right _) -> r
99+perhaps def m = P $ \kf ks t -> runP m (\_ -> ks def t) ks t
98100
99101char :: (Char -> Bool) -> Parser Char
100−char p = P $ \t -> case T.uncons t of
101− Just (c,t') | p c -> Right (c,t')
102− _ -> Left "char"
102+char p = P $ \kf ks t -> case T.uncons t of
103+ Just (c,t') | p c -> ks c t'
104+ _ -> kf "char"
105+
106+asP :: (Text -> Either String (a,Text)) -> Parser a
107+asP p = P $ \kf ks t -> case p t of
108+ Left err -> kf err
109+ Right (a,t') -> ks a t'
103110
104111-- | Read a rational number.
105112rational :: RealFloat a => Lexer a
106113{-# SPECIALIZE rational :: Lexer Double #-}
107−rational = runP $ do
108− real <- signa (P decimal)
114+rational = parse $ do
115+ real <- signa (asP decimal)
109116 (fraction,fracDigits) <- perhaps (0,0) $ do
110117 _ <- char (=='.')
111− digits <- P $ \t -> Right (T.length $ T.takeWhile isDigit t, t)
112− n <- P decimal
118+ digits <- P $ \kf ks t -> ks (T.length $ T.takeWhile isDigit t) t
119+ n <- asP decimal
113120 return (n, digits)
114− power <- perhaps 0 (char (`elem` "eE") >> signa (P decimal) :: Parser Int)
121+ power <- perhaps 0 (char (`elem` "eE") >> signa (asP decimal) :: Parser Int)
115122 return $! if fraction == 0
116123 then if power == 0
117124 then fromIntegral real
@@ -119,4 +126,3 @@ rational = runP $ do
119126 else fromRational $ if power == 0
120127 then real % 1 + fraction % (10 ^ fracDigits)
121128 else (real % 1 + fraction % (10 ^ fracDigits)) * (10 ^^ power)
122−