mrkkrp/megaparsec

Parsing hexadecimal floats

Opened this issue · 1 comments

It seems the parsing utilities in Text.Megaparsec.Char.Lexer do not support parsing hexadecimal floats out of the box:

0x0.1E
0xA23p-4
0X1.921FB54442D18P

Given how complex these are to parse efficiently and correctly, it seems like it would be a worthy addition to megaparsec.

Let me know if I am missing something obvious and there is an easy way to use the existing functions to parse these.

This is what I ended up going with using FloatingHex:

hexfloat = do
  zerox <- try $ char '0' >> char' 'x' <&> \x -> "0" ++ [x]
  whole <- hexdigits
  frac <- option "" $ liftA2 (:) (char '.') hexdigits
  exp <- option "p0" $ do
    p <- char' 'p'
    sign <- optional $ satisfy (\c -> c == '+' || c == '-')
    val <- digits
    return $ [p] ++ maybe "" (:[]) sign ++ val
  let literal = concat [zerox, whole, frac, exp]
  case readHFloat literal of
    Nothing -> unexpected $ Tokens $ fromList literal
    Just f -> return f
digits = T.unpack <$> takeWhile1P (Just "digit") isDigit
hexdigits = T.unpack <$> takeWhile1P (Just "hex digit") isHexDigit

Definitely not the cleanest/most performant, documenting for others who might need it or might be able to suggest improvements.