HsParser fails on any of these 6 examples:
data Data = A { x :: Int } f1 x = let { s = x } in s f2 x = do { x } f3 x = case x of { _ -> 12 } f4 x = s where { s = 12 } f5 y = A { x = 45 } The problem seems to be the production (copied from HsParser.ly) > layout_off :: { () } : {% pushContext NoLayout } This production is supposed to make the parser enter a NoLayout context every time the lexer reaches an open brace '{'. It is used in other productions such as > decllist :: { [HsDecl] } > : '{' layout_off decls '}' { $3 } > | layout_on decls close { $2 } For some reason the use of layout_off only takes effect _after_ the lexer has produced the next token. When the lexer reaches the second x in f2 x = do { x } the NoLayout hasn't been pushed yet. Since x is indented to the same column as f2, the lexer therefore inserts a ';'. The '{' followed by a ';' causes the parser to fail. In code with a more normal indentation f2 x = do { x } the parser works fine, because the lexer in this case doesn't insert an extra ';' or '}'. One way of fixing this is to remove all uses of layout_off, and instead delegate the pushing of NoLayouts to the lexer. I have attached a patch of HsParser.ly and HsLexer.lhs to show what I had in mind. Anders
233c233 < '{' -> special LeftCurly --- > '{' -> \ctxt -> special LeftCurly (NoLayout : ctxt)
130c130 < > : '{' layout_off bodyaux '}' { $3 } --- > > : '{' bodyaux '}' { $2 } 286c286 < > : '{' layout_off decls '}' { $3 } --- > > : '{' decls '}' { $2 } 370,371c370,371 < > | srcloc con '{' layout_off fielddecls '}' < > { HsRecDecl $1 $2 (reverse $5) } --- > > | srcloc con '{' fielddecls '}' > > { HsRecDecl $1 $2 (reverse $4) } 417c417 < > : 'where' '{' layout_off cbody '}' { $4 } --- > > : 'where' '{' cbody '}' { $3 } 438c438 < > : 'where' '{' layout_off valdefs '}' { $4 } --- > > : 'where' '{' valdefs '}' { $3 } 506c506 < > : aexp '{' layout_off fbinds '}' {% mkRecConstrOrUpdate $1 (reverse $4) } --- > > : aexp '{' fbinds '}' {% mkRecConstrOrUpdate $1 (reverse $3) } 571c571 < > : '{' layout_off alts optsemi '}' { reverse $3 } --- > > : '{' alts optsemi '}' { reverse $2 } 601c601 < > : '{' layout_off stmts '}' { $3 } --- > > : '{' stmts '}' { $2 } 738d737 < > layout_off :: { () } : {% pushContext NoLayout }