Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
Parsing<br />
Parser Combinators<br />
For parsing in <strong>Haskell</strong> it is quite common to use a family of libraries known as parser combinators which<br />
let us compose higher order functions to generate parsers. Parser combinators are a particularly expressive<br />
pattern that allows us to quickly prototype language grammars in an small embedded domain language<br />
inside of <strong>Haskell</strong> itself. Most notably we can embed custom <strong>Haskell</strong> logic inside of the parser.<br />
NanoParsec<br />
So now let’s build our own toy parser combinator library which we’ll call NanoParsec just to get the feel<br />
of how these things are built.<br />
{-# OPTIONS_GHC -fno-warn-unused-do-bind #-}<br />
module NanoParsec where<br />
import Data.Char<br />
import Control.Monad<br />
import Control.Applicative<br />
Structurally a parser is a function which takes an input stream of characters and yields a parse tree by<br />
applying the parser logic over sections of the character stream (called lexemes) to build up a composite<br />
data structure for the AST.<br />
newtype Parser a = Parser { parse :: String -> [(a,String)] }<br />
Running the function will result in traversing the stream of characters yielding a value of type a that<br />
usually represents the AST for the parsed expression, or failing with a parse error for malformed input,<br />
or failing by not consuming the entire stream of input. A more robust implementation would track the<br />
position information of failures for error reporting.<br />
runParser :: Parser a -> String -> a<br />
runParser m s =<br />
31