解析不以attoparsec中的某些字符结尾的标识符
我被困在写一个attoparsec解析器来解析什么Uniform Code for Units of Measure称为<ATOM-SYMBOL>
。它被定义为某个类中字符的最长序列(该类包含所有数字0-9),它不以数字结尾。解析不以attoparsec中的某些字符结尾的标识符
所以给我希望消费和返回foo
,为237bar26
我想消费并返回237bar
,为19
我想不消耗任何失败的输入foo27
。
我无法弄清楚如何建立该方案的takeWhile1
或takeTill
或scan
但我可能失去了一些东西明显。
更新: 我最好的尝试,到目前为止是我设法排除完全数字
atomSymbol :: Parser Text
atomSymbol = do
r <- core
if (P.all (inClass "0-9") . T.unpack $ r)
then fail "Expected an atom symbol but all characters were digits."
else return r
where
core = A.takeWhile1 $ inClass "!#-'*,0-<>-Z\\^-z|~"
我试图改变的是测试如果最后一个字符是数字,而不是如果他们都是序列,但它似乎并没有一次回溯一个角色。
更新2:
整个文件是在https://github.com/dmcclean/dimensional-attoparsec/blob/master/src/Numeric/Units/Dimensional/Parsing/Attoparsec.hs。这仅适用于的prefixes
分支。
您应该重新解决问题并分别处理数字(0-9
)和非数字字符(!#-'*,:-<>-Z\\^-z|~
)的跨度。感兴趣的语法元素可随后被描述为
- 一个可选数字广度,随后
- 非数字广度,随后
- 零个或多个{数字广度后跟一个非数字广度}。
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Control.Applicative ((<|>), many)
import Data.Char (isDigit)
import Data.Attoparsec.Combinator (option)
import Data.Attoparsec.Text (Parser)
import qualified Data.Attoparsec.Text as A
import Data.Text (Text)
import qualified Data.Text as T
atomSymbol :: Parser Text
atomSymbol = f <$> (option "" digitSpan)
<*> (nonDigitSpan <|> fail errorMsg)
<*> many (g <$> digitSpan <*> nonDigitSpan)
where
nonDigitSpan = A.takeWhile1 $ A.inClass "!#-'*,:-<>-Z\\^-z|~"
digitSpan = A.takeWhile1 isDigit
f x y xss = T.concat $ x : y : concat xss
g x y = [x,y]
errorMsg = "Expected an atom symbol but all characters (if any) were digits."
测试
[...]给出的输入
foo27
我想消费并返回FOO,为237bar26
我想消费并返回237bar
,为19
我想不失败消耗什么。
λ> A.parseOnly atomSymbol "foo26"
Right "foo"
λ> A.parseOnly atomSymbol "237bar26"
Right "237bar"
λ> A.parseOnly atomSymbol "19"
Left "Failed reading: Expected an atom symbol but all characters (if any) were digits."
这是一个非常好的答案,非常感谢。对于延迟提供反馈意见,我感到抱歉,我在办公室里绝对淹没了。 –
@DougMcClean没问题。 – Jubobs
这里有一个组合子,可以帮助你:'notFollowedBy P = >>失败“后面没有”' – arrowd
请你的问题自足,并添加import语句。在这里,人们仍然想知道(即使有人猜测)什么样的合格进口“A”,“P”和“T”对应。 – Jubobs
你可以把整个令牌,反向它,放下数字,反向回来,并检查是否有任何遗留物? – VlatkoB