25.10.2015 Views

Write You a Haskell Stephen Diehl

1kEcQTb

1kEcQTb

SHOW MORE
SHOW LESS

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

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!