├── BlockParser.hs └── README.md /BlockParser.hs: -------------------------------------------------------------------------------- 1 | module BlockParser where 2 | 3 | import Text.Parsec 4 | import Text.Parsec.String 5 | import Control.Applicative hiding (many, (<|>)) 6 | 7 | data Item = 8 | Text String 9 | | Block String [Item] 10 | deriving Show 11 | 12 | type CharParser st = Parsec [Char] st 13 | 14 | -- A item is either a block delimited 15 | -- by \begin{name} \end{name} 16 | -- or plain text 17 | item :: CharParser st Item 18 | item = 19 | do 20 | blockName <- begin 21 | Block blockName <$> blockBody <* end blockName 22 | <|> text 23 | 24 | -- series of items (including nested blocks) 25 | blockBody :: CharParser st [Item] 26 | blockBody = many item 27 | 28 | -- \begin{name} 29 | -- returns name or fails 30 | begin :: CharParser st String 31 | begin = try $ string "\\begin" *> braced 32 | 33 | -- tries \end{str} for a given string 34 | end :: String -> CharParser st String 35 | end str = try $ 36 | string "\\end" *> between (char '{') (char '}') (string str) 37 | 38 | -- string delimited by braces 39 | braced :: CharParser st String 40 | braced = between (char '{') (char '}') (many $ noneOf "}") 41 | 42 | -- a non-empty string of characters other than \ $ { } 43 | text :: CharParser st Item 44 | text = Text <$> many1 (noneOf "\\${}") 45 | 46 | test :: String 47 | test = 48 | let file = "\\begin{foo}abc\\begin{bar}def\\end{bar}\\begin{baz}ghi\\end{baz}\\end{foo}" 49 | in 50 | case parse item "Experiment" file of 51 | Left err -> "Error: " ++ show err 52 | Right doc -> show doc 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Parsing 2 | Using parsec 3 | --------------------------------------------------------------------------------