2015-12-04 29 views
3

我被困在写一个attoparsec解析器来解析什么Uniform Code for Units of Measure称为<ATOM-SYMBOL>。它被定义为某个类中字符的最长序列(该类包含所有数字0-9),它不以数字结尾。解析不以attoparsec中的某些字符结尾的标识符

所以给我希望消费和返回foo,为237bar26我想消费并返回237bar,为19我想不消耗任何失败的输入foo27

我无法弄清楚如何建立该方案的takeWhile1takeTillscan但我可能失去了一些东西明显。

更新: 我最好的尝试,到目前为止是我设法排除完全数字

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分支。

+2

这里有一个组合子,可以帮助你:'notFollowedBy P = >>失败“后面没有”' – arrowd

+0

请你的问题自足,并添加import语句。在这里,人们仍然想知道(即使有人猜测)什么样的合格进口“A”,“P”和“T”对应。 – Jubobs

+1

你可以把整个令牌,反向它,放下数字,反向回来,并检查是否有任何遗留物? – VlatkoB

回答

1

您应该重新解决问题并分别处理数字(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." 
+0

这是一个非常好的答案,非常感谢。对于延迟提供反馈意见,我感到抱歉,我在办公室里绝对淹没了。 –

+0

@DougMcClean没问题。 – Jubobs

相关问题