如何使用 Parsec 仅在某个范围内解析一串整数?
How to parse a string of integers only in some range with Parsec?
我正在尝试通过解析 "YYYYMMDD" 格式的日期字符串来学习秒差距,例如“20161030”。我的解决方案是:
date :: Parser (String, String, String)
date = do
year <- replicateM 4 digit
month <- replicateM 2 digit
day <- replicateM 2 digit
return (year, month, day)
但问题是“20161356”也是我代码的有效日期。
如何验证 "MM" 在 1 到 12 之间; "DD" 介于 1 和 31 之间?
您可以按照 Thomas M. DuBuisson 的建议添加 guard
:
date :: Parser (String, String, String)
date = do
year <- replicateM 4 digit
month <- replicateM 2 digit
day <- replicateM 2 digit
guard $ read month > 0 && read month <= 12 && read day > 0 && read day <= 31
return (year, month, day)
但是,这会导致错误消息:
λ> parse date "" "20161356"
Left (line 1, column 9):unknown parse error
我们可以通过结合 guard
和 <?>
来解决这个问题,以提供更好的错误消息:
date :: Parser (String, String, String)
date = do
year <- replicateM 4 digit
month <- replicateM 2 digit
guard (read month > 0 && read month <= 12) <?> "valid month (1–12)"
day <- replicateM 2 digit
guard (read day > 0 && read day <= 31) <?> "valid day (1–31)"
return (year, month, day)
通过这种方法,您会得到更有用的错误消息:
λ> parse date "" "20161356"
Left (line 1, column 7):
expecting valid month (1–12)
作为旁注,我认为 在解析器中验证(或至少完整性检查)日期很有价值——它确保日期验证与其余部分相结合您的解析器和错误处理代码。您不能忘记稍后在您的代码中检查日期,并且错误已正确定位,如果您正在解析包含大量日期的文档,这将非常有用。
我正在尝试通过解析 "YYYYMMDD" 格式的日期字符串来学习秒差距,例如“20161030”。我的解决方案是:
date :: Parser (String, String, String)
date = do
year <- replicateM 4 digit
month <- replicateM 2 digit
day <- replicateM 2 digit
return (year, month, day)
但问题是“20161356”也是我代码的有效日期。
如何验证 "MM" 在 1 到 12 之间; "DD" 介于 1 和 31 之间?
您可以按照 Thomas M. DuBuisson 的建议添加 guard
:
date :: Parser (String, String, String)
date = do
year <- replicateM 4 digit
month <- replicateM 2 digit
day <- replicateM 2 digit
guard $ read month > 0 && read month <= 12 && read day > 0 && read day <= 31
return (year, month, day)
但是,这会导致错误消息:
λ> parse date "" "20161356"
Left (line 1, column 9):unknown parse error
我们可以通过结合 guard
和 <?>
来解决这个问题,以提供更好的错误消息:
date :: Parser (String, String, String)
date = do
year <- replicateM 4 digit
month <- replicateM 2 digit
guard (read month > 0 && read month <= 12) <?> "valid month (1–12)"
day <- replicateM 2 digit
guard (read day > 0 && read day <= 31) <?> "valid day (1–31)"
return (year, month, day)
通过这种方法,您会得到更有用的错误消息:
λ> parse date "" "20161356"
Left (line 1, column 7):
expecting valid month (1–12)
作为旁注,我认为 在解析器中验证(或至少完整性检查)日期很有价值——它确保日期验证与其余部分相结合您的解析器和错误处理代码。您不能忘记稍后在您的代码中检查日期,并且错误已正确定位,如果您正在解析包含大量日期的文档,这将非常有用。