如何使用Megaparsec解析带逗号的数字
解决Megaparsec解析带千分位逗号的数字问题
要让Megaparsec支持解析4,087.00这类带千分位逗号的数字,核心思路是先解析带逗号的数字字符串,去除逗号后再转换为Scientific类型。以下是具体实现步骤:
1. 导入必要模块
首先确保导入所需的Haskell模块:
import Text.Megaparsec import Text.Megaparsec.Char import qualified Text.Megaparsec.Lexer as L import Data.Text (Text) import qualified Data.Text as T import Data.Scientific (Scientific, readScientific) -- 定义Parser类型别名 type Parser = Parsec Void Text
2. 解析带千分位逗号的整数部分
先实现解析千分位格式整数的逻辑:
-- 解析1-3位数字组成的分组 pDigitGroup :: Parser Text pDigitGroup = T.pack <$> countMinMax 1 3 digitChar -- 解析带千分位逗号的整数部分(如4,087 或 123,456,789) pIntegerPart :: Parser Text pIntegerPart = do firstGroup <- pDigitGroup restGroups <- many (char ',' *> pDigitGroup) return $ T.concat (firstGroup : restGroups)
3. 解析可选的小数部分
处理小数点后的数字(可选,支持纯整数如4,087):
-- 解析小数部分(如.00,无小数则返回空字符串) pFractionalPart :: Parser Text pFractionalPart = option "" (char '.' *> (T.pack <$> some digitChar))
4. 组合解析逻辑并转换为Scientific
将整数、小数部分拼接,去除逗号后转换为Scientific,同时支持负数格式:
-- 支持带千分位逗号的Scientific解析器 pScientificWithCommas :: Parser Scientific pScientificWithCommas = lexeme $ do sign <- option "" (string "-") integerPart <- pIntegerPart fractionalPart <- pFractionalPart let numStr = sign ++ T.unpack (integerPart <> fractionalPart) case readScientific numStr of Right s -> return s Left err -> fail $ "无效数字: " ++ err
5. 兼容原有格式(可选)
如果需要同时支持4087.00和4,087.00两种格式,可将两个解析器组合:
pScientific :: Parser Scientific pScientific = pScientificWithCommas <|> lexeme L.scientific
说明
lexeme用于跳过数字后的空白,保持和原解析器一致的行为;readScientific负责将处理后的纯数字字符串转换为Scientific,自动处理整数、小数等合法格式;- 若解析后的字符串不合法(如
4,,087),会抛出错误提示。
内容的提问来源于stack exchange,提问作者Bads
相关产品推荐
相关产品推荐

