CmdLineParser4.hs

Plain text version of CmdLineParser4.hs

Command-Line Parsing Combinators

module CmdLineParser4(
  -- Parser type:
  P,
  -- Parser constructors:
  token,cmd,(!),(<@),(#@),chk,nil,many,arg,kw,opt,flag,(--:),
  -- Parser destructors:
  run,usage,parseAll
  ) where
import Pretty
import Monad(msum,join,liftM,MonadPlus(..),ap)
import Maybe(isJust)
import System(getArgs)
import PM
import Grammar

infixl 3 <@,`chk`,#@
infix 2 --:
infixr 1 !

The Parser Data Type

data P res = P Grammar (PM res)

instance Functor P where fmap f (P g p) = P g (fmap f p)

Parsing combinators

nil x = P Empty (return x)
P g1 f <@ P g2 a = P (Seq g1 g2) (f `ap` a)
named nt (P g p) = P (Nonterminal nt g) p
P g p --: descr = P (g :--- descr) p
token f s = P (Terminal s) (tokenP f s)
P g1 p1 ! P g2 p2 = P (Alt g1 g2) (p1 `mplus` p2)
many (P g p) = P (Many g) (manyP p)
opt (P g p) = P (Opt g) (fmap Just p `mplus` return Nothing)

chk p p' = const `fmap` p <@ p'
cmd s p = nil p `chk` kw s

f #@ p = fmap f p

arg = token Just
kw s = token check s
  where check a = if a==s then Just () else Nothing

flag s = isJust `fmap` opt (kw s)

Extracting the documentation from a grammar

usage prefix p = render (usageDoc prefix p)
usageDoc prefix (P g _) =
    (text "Usage:" $$
        nest 2 (nest 2 (text prefix<+>main) $$
                if null aux then empty else text "where" $$ vcat aux))
  where
    (main,aux) = ppGrammar g

Running a parser

run p = parseAll p =<< getArgs

parseAll (P g p) = runPM p

Valid HTML?