Haskell 如何用Parsec推广重复解析

Haskell 如何用Parsec推广重复解析,haskell,parsec,Haskell,Parsec,我正在学习通过解析文本文件中的行来使用Parsec。我所拥有的是: import Text.Parsec (ParseError, parse) import Text.Parsec.String (Parser) import Text.Parsec.Char (anyChar, digit, char, oneOf) import Control.Monad (void) import qualified Text.Parsec.Combinator as C data Action =

我正在学习通过解析文本文件中的行来使用Parsec。我所拥有的是:

import Text.Parsec (ParseError, parse)
import Text.Parsec.String (Parser)
import Text.Parsec.Char (anyChar, digit, char, oneOf)
import Control.Monad (void)
import qualified Text.Parsec.Combinator as C

data Action =
  ActionA Int Int
  | ActionB Int Int Int Int Int
  | ActionC Int Int Int
  deriving (Show)

parseWithEof :: Parser a -> String -> Either ParseError a
parseWithEof p = parse (p <* C.eof) ""

parseActionA :: Parser Action
parseActionA = do
  char 'A'
  void $ oneOf " "
  a <- C.many1 digit
  void $ oneOf " "
  b <- C.many1 digit
  return $ ActionA (read a) (read b)

parseActionB :: Parser Action
parseActionB = do
  char 'B'
  void $ oneOf " "
  a <- C.many1 digit
  void $ oneOf " "
  b <- C.many1 digit
  void $ oneOf " "
  c <- C.many1 digit
  void $ oneOf " "
  d <- C.many1 digit
  void $ oneOf " "
  e <- C.many1 digit
  return $ ActionB (read a) (read b) (read c) (read d) (read e)

parseActionC :: Parser Action
parseActionC = do
  char 'C'
  void $ oneOf " "
  a <- C.many1 digit
  void $ oneOf " "
  b <- C.many1 digit
  void $ oneOf " "
  c <- C.many1 digit
  return $ ActionC (read a) (read b) (read c)
import Text.Parsec(ParseError,parse)
导入Text.Parsec.String(解析器)
导入Text.Parsec.Char(anyChar、digital、Char、oneOf)
进口管制.单子(无效)
将限定的Text.Parsec.Combinator作为C导入
数据操作=
动作A整数
|动作b Int
|ActionC Int
派生(显示)
parseWithEof::解析器a->字符串->解析错误a

parseWithEof p=parse(p使用应用组合符,您可以编写:

num = do oneOf " "; fmap read (C.many1 digit)

parseActionA = ActionA <$> (char 'A' >> num) <*> num

parseActionB = ActionB <$> (char 'B' >> num) <*> num <*> num <*> num <*> num

注意-
try
在最后一个解析器上应该不需要,但拥有它并没有什么坏处。另外,如果你对解析器的工作方式了解得足够多,你可能可以省去一些
try
s。这在某种程度上简化了它,但我仍然需要编写n倍的
num
部分。有没有办法自动重复这个部分在?@OneEyeQuestion,看看你是否可以使用
replicItem
@ErikR你正在使用的
try parseaction a try parseaction b
,但是根据本文()我们应该尝试缩小
try
的范围。这是相同的情况还是不同的情况?
count::Stream sm=>Int->ParsecT s u m a->ParsecT s u m[a]
基本上,你可以在每一个解析器都安全之前做一些类似于
parseActionB=do char'B';([a,B,c,d,e])@OneEyeQuestion put
的事情。当你对Parsec的工作原理有了更多的了解后,你可以删除那些你不需要的,以提高效率。
num = do oneOf " "; fmap read (C.many1 digit)

parseActionA = ActionA <$> (char 'A' >> num) <*> num

parseActionB = ActionB <$> (char 'B' >> num) <*> num <*> num <*> num <*> num
parseAction = try parseActionA <|> try parseActionB <|> try parseActionC