on master help sign in
Switch over to a CPS-based parsing monad
df83380Bryan O'Sullivan
Data/Text/Lex.hs+26−20
@@ -1,4 +1,4 @@
1−{-# LANGUAGE OverloadedStrings #-}
1+{-# LANGUAGE OverloadedStrings, Rank2Types #-}
2
2
3-- |
3-- |
4-- Module : Data.Text.Lex
4-- Module : Data.Text.Lex
@@ -69,7 +69,7 @@ hexDigitToInt c
69-- to the result of applying the given reader.
69-- to the result of applying the given reader.
70signed :: Num a => Lexer a -> Lexer a
70signed :: Num a => Lexer a -> Lexer a
71{-# INLINE signed #-}
71{-# INLINE signed #-}
72−signed f = runP (signa (P f))
72+signed f = parse (signa (asP f))
73
73
74signa :: Num a => Parser a -> Parser a
74signa :: Num a => Parser a -> Parser a
75{-# SPECIALIZE signa :: Parser Int -> Parser Int #-}
75{-# SPECIALIZE signa :: Parser Int -> Parser Int #-}
@@ -79,39 +79,46 @@ signa p = do
79 if sign == '+' then p else negate `liftM` p
79 if sign == '+' then p else negate `liftM` p
80
80
81newtype Parser a = P {
81newtype Parser a = P {
82+ runP :: forall r.
82− runP :: Text -> Either String (a,Text)
83+ (String -> Either String (r,Text))
84+ -> (a -> Text -> Either String (r,Text))
85+ -> Text -> Either String (r,Text)
83 }
86 }
84
87
88+parse :: Parser a -> Text -> Either String (a,Text)
89+parse p t = runP p Left (\a t' -> Right (a,t')) t
90+
85instance Monad Parser where
91instance Monad Parser where
86− return a = P $ \t -> Right (a,t)
92+ return a = P $ \kf ks t -> ks a t
87 {-# INLINE return #-}
93 {-# 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
91 {-# INLINE (>>=) #-}
95 {-# INLINE (>>=) #-}
92− fail msg = P $ \_ -> Left msg
96+ fail msg = P $ \kf ks t -> kf msg
93
97
94perhaps :: a -> Parser a -> Parser a
98perhaps :: a -> Parser a -> Parser a
95−perhaps def m = P $ \t -> case runP m t of
99+perhaps def m = P $ \kf ks t -> runP m (\_ -> ks def t) ks t
96− Left _ -> Right (def,t)
97− r@(Right _) -> r
98
100
99char :: (Char -> Bool) -> Parser Char
101char :: (Char -> Bool) -> Parser Char
100−char p = P $ \t -> case T.uncons t of
102+char p = P $ \kf ks t -> case T.uncons t of
101− Just (c,t') | p c -> Right (c,t')
103+ Just (c,t') | p c -> ks c t'
102− _ -> Left "char"
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'
103
110
104-- | Read a rational number.
111-- | Read a rational number.
105rational :: RealFloat a => Lexer a
112rational :: RealFloat a => Lexer a
106{-# SPECIALIZE rational :: Lexer Double #-}
113{-# SPECIALIZE rational :: Lexer Double #-}
107−rational = runP $ do
114+rational = parse $ do
108− real <- signa (P decimal)
115+ real <- signa (asP decimal)
109 (fraction,fracDigits) <- perhaps (0,0) $ do
116 (fraction,fracDigits) <- perhaps (0,0) $ do
110 _ <- char (=='.')
117 _ <- char (=='.')
111− digits <- P $ \t -> Right (T.length $ T.takeWhile isDigit t, t)
118+ digits <- P $ \kf ks t -> ks (T.length $ T.takeWhile isDigit t) t
112− n <- P decimal
119+ n <- asP decimal
113 return (n, digits)
120 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)
115 return $! if fraction == 0
122 return $! if fraction == 0
116 then if power == 0
123 then if power == 0
117 then fromIntegral real
124 then fromIntegral real
@@ -119,4 +126,3 @@ rational = runP $ do
119 else fromRational $ if power == 0
126 else fromRational $ if power == 0
120 then real % 1 + fraction % (10 ^ fracDigits)
127 then real % 1 + fraction % (10 ^ fracDigits)
121 else (real % 1 + fraction % (10 ^ fracDigits)) * (10 ^^ power)
128 else (real % 1 + fraction % (10 ^ fracDigits)) * (10 ^^ power)
122−