\$\begingroup\$
\$\endgroup\$
I am trying to parse escape sequences as well as plain characters. Can this be made more succinct?
import Control.Applicative
import Data.Char
import Numeric
import Text.Parsec hiding ((<|>))
echar :: Parsec String () Char
echar = (char '\\' >>
((char 'b' >> return '\b')
<|> (char 'f' >> return '\f')
<|> (char 'n' >> return '\n')
<|> (char 'r' >> return '\r')
<|> (char 't' >> return '\t')
<|> (char 'u' >> count 4 hexDigit >>= return . chr . fst . head . readHex)
<|> (char 'v' >> return '\v')
<|> (noneOf "u")))
<|> noneOf "\\"
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Jul 10, 2015 at 14:19
1 Answer 1
\$\begingroup\$
\$\endgroup\$
2
You could cut down on the repetitive elements with a local function binding.
echar =
let
yield :: Char -> Char -> Parsec String () Char
yield c d = char c >> return d
in
(char '\\' >>
( yield 'b' '\b'
<|> yield 'f' '\f'
-- ...
Then perhaps cut out the repeated applications with a fold.
import Data.Foldable
-- ...
in
(char '\\' >>
( (asum . map (uncurry yield) $ [('b', '\b'), ('f', '\f') -- ...
<|> (char 'u' -- ...
I'm not sure you need the Numeric
import either, I would write that line as—
char 'u' >> count 4 hexDigit >>= return . chr . read . ("0x" ++)
And then to tie it all together with a bow.
import Control.Applicative ((<|>))
import Data.Char (chr)
import Data.Foldable (asum)
import Text.Parsec hiding ((<|>))
echar :: Parsec String () Char
echar =
let
escapeCharacters = [('b', '\b'), ('f', '\f'), ('r', '\r'), ('t', '\t'), ('v', '\v')]
yield :: Char -> Char -> Parsec String () Char
yield c d = char c >> return d
in
(char '\\' >>
( (asum . map (uncurry yield) $ escapeCharacters)
<|> (char 'u' >> count 4 hexDigit >>= return . chr . read . ("0x" ++))
<|> (noneOf "u")
)
) <|> noneOf "\\"
-
\$\begingroup\$ thanks. Why do you
uncurry
youryield
rather than making it accept a pair right away? \$\endgroup\$akonsu– akonsu2015年07月13日 13:35:27 +00:00Commented Jul 13, 2015 at 13:35 -
\$\begingroup\$ 1) Curried functions are the default. 2) You might raise
yield
to the top-level and use it elsewhere, where the uncurried version doesn't make sense. 3) It just feels right. \$\endgroup\$R B– R B2015年07月13日 17:12:30 +00:00Commented Jul 13, 2015 at 17:12
lang-hs