跳转至

【译】【未完成】Megaparsec 教程

关于 haskell 库 megaparsec 的中文资料凤毛麟角,其中比较系统的只有对 Megaparsec tutorial from IH book 的翻译 Megaparsec: Haskell 的语法分析组合子。无奈原教程对我这样的初学者来说水平过高,缺失细节,遇到错误也难以区分版本问题、环境问题或是自己的疏漏,故有了此注释版,希望也能帮到其他人。

注:原文提到这是一本未完成的书《Intermediate Haskell》中的一章,这本书已经夭折

前置知识

大佬跳过,新手留步 看这里

最小化的 demo


MonadParsec

先看下 MonadParsec 定义

-- Text/Megaparsec.hs
class (Stream s, MonadPlus m) => MonadParsec e s m | m -> e s where
  parseError :: ParseError s e -> m a
  label :: String -> m a -> m a

  hidden :: m a -> m a
  hidden = label ""

  try :: m a -> m a
  lookAhead :: m a -> m a
  notFollowedBy :: m a -> m ()
  withRecovery :: (ParseError s e -> m a) ->  m a -> m a
  observing :: m a -> m (Either (ParseError s e) a)
  eof :: m ()
  token :: (Token s -> Maybe a) -> Set (ErrorItem (Token s)) -> m a
  tokens :: (Tokens s -> Tokens s -> Bool) -> Tokens s -> m (Tokens s)
  takeWhileP :: Maybe String -> (Token s -> Bool) -> m (Tokens s)
  takeWhile1P :: Maybe String -> (Token s -> Bool) -> m (Tokens s)
  takeP :: Maybe String -> Int -> m (Tokens s)
  getParserState :: m (State s e)
  updateParserState :: (State s e -> State s e) -> m ()
  mkParsec :: (State s e -> Reply e s a) -> m a

Stream s

stream 是输入类型,不研究其细节了,使用 String, ByteString, Text, Lazy T 都可以。

MonadPlus m

MonadPlus 也是一个常见的类型类,用于处理两个同类型的 Monad,比如实现拼接、并发、选择等,其定义如下

class Monad m => MonadPlus m where
  mzero :: m a
  mplus :: m a -> m a -> m a

MonadParsec e s m

MonadParsec 接收 3 个类型参数 e s m,其中 e 表示错误的类型,s 和 m 之前已经介绍过了。

m -> e s

这是一个 functional dependency 描述,含义是当 m 确定后,可以确定唯一的 e 和 s。

有了这个约束,Haskell 就可以更容易的推理 MonadParsec 的类型了。