Be sure you put your name and e-mail in a comment at the beginning of the file. Without this you will not get any feedback.
In this homework you will write a parser for a subset of haskell. In order to do this you will need to write indentation sensitive parsers. Which keep track of the column that some sytactic entities start in. This is done with the parsec "layout" combinator. An example is given below that parses a "let" statement (given parsers for declarations (declP) and expressions ("expP")).
letParser declP expP = do { pos <- getPosition -- This gets the SourcePos ; keyworD "let" ; ds <- layout declP (keyworD "in") -- "in" ends the layout if it is found ; exp <- expP ; return(ds,exp)}When a parser "p" is "layed out" a "tab stop" is set at the next non-whitespace character. It the parses a sequence of "p" objects. Lines that begin after the "tab stop" are continuations of the "p" that started on earlier lines. Lines that begin at the "tab stop" are the beginning of the next "p". Lines that start before the "tab stop" end the layout rule. The second argument to "layout" (keyworD "in") is a parser the forces the layout to end regardless of the where the line begins. Some layout sensisitve language copnstructs (such as case, where, and do) do not have a terminating token, in which case the parser (return ()) will do.
One can turn off the laout rule by surrounding the sequence of "p" objects by "{" and "}" separating by ";". Thus the following pairs all parse the same.
case x of [] -> 0 (Cons x xs) -> x + 4 case x of { [] -> 0; (Cons x xs) -> x + 4} ----------------------------------- let x = 3 y = 5 in x + y let {x = 3; y = 5} in x+5 ----------------------------------- f x y = x+y+z where a = 5 z = a - 3 f x y = x+y+z where { a= 5; z = a-3}Luckily all this is handled by the layout parser combinator. In order to use the layout combinator one needs a modified version of the Parsec.Token module. He one we use is called "LayoutToken" and is included here. Just download this file, along with HW4Template.html. Rename "HW4Template.html" to "hw4.hs", and keep both files in the same directory.
The language we are interested in has the following abstract syntax. This is a subset of Haskell expressions.
type Var = (SourcePos,String) -- Starts lowercase type Con = (SourcePos,String) -- Starts with Upper case type Name = (SourcePos,String) -- Starts with either lower case or uppercase data Lit = Int Int | Char Char | Unit | Float Float data Pat = Plit Lit -- { 5 or 'c' } | Pvar Var -- { x } | Pprod [Pat] -- { (p1,p2,p3) } | Paspat Var Pat -- { x @ p } | Pwild -- { _ } | Pcon Con [Pat] -- C x y (z,a) data Exp = Var Name -- { x or Nil } | Lit Lit -- { 5 or 'c' or 5.6 } | Prod [Exp] -- { (e1,e2,e3) } | App Exp Exp -- { f x } | Lam [Pat] Exp -- { \ p1 p2 -> e } | Let [Dec] Exp -- { let { x=e1; y=e2 } in e3 } | Case Exp [Match Pat Exp Dec] -- { case e of { m1; m2 }} | Do [Stmt Pat Exp Dec] -- { do { p <- e1; e2 } } -- Let, Case, Do, all use layout type Match p e d = (SourcePos,p,Body e,[d]) -- case e of { p -> b where decs } data Body e = Guarded [(e,e)] -- f p { | e1 = e2 | e3 = e4 } where ds | Normal e -- f p = { e } where ds -- Where uses layout data Stmt p e d = BindSt SourcePos p e | LetSt SourcePos [d] | NoBindSt SourcePos e data Dec = Fun SourcePos Var [Match [Pat] Exp Dec] -- { f p1 p2 = b where decs } | Val SourcePos Pat (Body Exp) [Dec] -- { p = b where decs }Here is what I expect.