Implement generalised list comprehensions
[ghc-hetmet.git] / compiler / parser / Parser.y.pp
index abfc258..6de95f8 100644 (file)
@@ -8,6 +8,13 @@
 -- ---------------------------------------------------------------------------
 
 {
+{-# OPTIONS -w #-}
+-- The above warning supression flag is a temporary kludge.
+-- While working on this module you are encouraged to remove it and fix
+-- any warnings in the module. See
+--     http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings
+-- for details
+
 module Parser ( parseModule, parseStmt, parseIdentifier, parseType,
                parseHeader ) where
 
@@ -35,6 +42,7 @@ import StaticFlags    ( opt_SccProfilingOn, opt_Hpc )
 import Type            ( Kind, mkArrowKind, liftedTypeKind, unliftedTypeKind )
 import BasicTypes      ( Boxity(..), Fixity(..), FixityDirection(..), IPName(..),
                          Activation(..), defaultInlineSpec )
+import DynFlags
 import OrdList
 import HaddockParse
 import {-# SOURCE #-} HaddockLex hiding ( Token )
@@ -200,7 +208,6 @@ incorrect.
  'data'        { L _ ITdata } 
  'default'     { L _ ITdefault }
  'deriving'    { L _ ITderiving }
- 'derive'      { L _ ITderive }
  'do'          { L _ ITdo }
  'else'        { L _ ITelse }
  'hiding'      { L _ IThiding }
@@ -236,6 +243,9 @@ incorrect.
  'dotnet'       { L _ ITdotnet }
  'proc'                { L _ ITproc }          -- for arrow notation extension
  'rec'         { L _ ITrec }           -- for arrow notation extension
+ 'group'    { L _ ITgroup }     -- for list transform extension
+ 'by'       { L _ ITby }        -- for list transform extension
+ 'using'    { L _ ITusing }     -- for list transform extension
 
  '{-# INLINE'            { L _ (ITinline_prag _) }
  '{-# SPECIALISE'        { L _ ITspec_prag }
@@ -315,7 +325,6 @@ incorrect.
  DOCPREV       { L _ (ITdocCommentPrev _) }
  DOCNAMED      { L _ (ITdocCommentNamed _) }
  DOCSECTION    { L _ (ITdocSection _ _) }
- DOCOPTIONS    { L _ (ITdocOptions _) }
 
 -- Template Haskell 
 '[|'            { L _ ITopenExpQuote  }       
@@ -345,6 +354,7 @@ identifier :: { Located RdrName }
        | qcon                          { $1 }
        | qvarop                        { $1 }
        | qconop                        { $1 }
+    | '(' '->' ')'      { LL $ getRdrName funTyCon }
 
 -----------------------------------------------------------------------------
 -- Module Header
@@ -357,22 +367,19 @@ identifier :: { Located RdrName }
 -- know what they are doing. :-)
 
 module         :: { Located (HsModule RdrName) }
-       : optdoc 'module' modid maybemoddeprec maybeexports 'where' body 
-               {% fileSrcSpan >>= \ loc -> case $1 of { (opt, info, doc) -> 
-                  return (L loc (HsModule (Just $3) $5 (fst $7) (snd $7) $4 
-                          opt info doc) )}}
-       | missing_module_keyword top close
+       : maybedocheader 'module' modid maybemoddeprec maybeexports 'where' body
+               {% fileSrcSpan >>= \ loc -> case $1 of { (info, doc) ->
+                  return (L loc (HsModule (Just $3) $5 (fst $7) (snd $7) $4
+                          info doc) )}}
+        | body2
                {% fileSrcSpan >>= \ loc ->
-                  return (L loc (HsModule Nothing Nothing 
-                          (fst $2) (snd $2) Nothing Nothing emptyHaddockModInfo 
+                  return (L loc (HsModule Nothing Nothing
+                          (fst $1) (snd $1) Nothing emptyHaddockModInfo
                           Nothing)) }
 
-optdoc :: { (Maybe String, HaddockModInfo RdrName, Maybe (HsDoc RdrName)) }                             
-        : moduleheader            { (Nothing, fst $1, snd $1) }
-        | docoptions              { (Just $1, emptyHaddockModInfo, Nothing)} 
-        | docoptions moduleheader { (Just $1, fst $2, snd $2) } 
-        | moduleheader docoptions { (Just $2, fst $1, snd $1) } 
-        | {- empty -}             { (Nothing, emptyHaddockModInfo, Nothing) }  
+maybedocheader :: { (HaddockModInfo RdrName, Maybe (HsDoc RdrName)) }
+        : moduleheader            { (fst $1, snd $1) }
+        | {- empty -}             { (emptyHaddockModInfo, Nothing) }
 
 missing_module_keyword :: { () }
        : {- empty -}                           {% pushCurrentContext }
@@ -385,6 +392,10 @@ body       :: { ([LImportDecl RdrName], [LHsDecl RdrName]) }
        :  '{'            top '}'               { $2 }
        |      vocurly    top close             { $2 }
 
+body2  :: { ([LImportDecl RdrName], [LHsDecl RdrName]) }
+       :  '{' top '}'                          { $2 }
+       |  missing_module_keyword top close     { $2 }
+
 top    :: { ([LImportDecl RdrName], [LHsDecl RdrName]) }
        : importdecls                           { (reverse $1,[]) }
        | importdecls ';' cvtopdecls            { (reverse $1,$3) }
@@ -397,14 +408,14 @@ cvtopdecls :: { [LHsDecl RdrName] }
 -- Module declaration & imports only
 
 header         :: { Located (HsModule RdrName) }
-       : optdoc 'module' modid maybemoddeprec maybeexports 'where' header_body
-               {% fileSrcSpan >>= \ loc -> case $1 of { (opt, info, doc) -> 
-                  return (L loc (HsModule (Just $3) $5 $7 [] $4 
-                   opt info doc))}}
+       : maybedocheader 'module' modid maybemoddeprec maybeexports 'where' header_body
+               {% fileSrcSpan >>= \ loc -> case $1 of { (info, doc) ->
+                  return (L loc (HsModule (Just $3) $5 $7 [] $4
+                   info doc))}}
        | missing_module_keyword importdecls
                {% fileSrcSpan >>= \ loc ->
-                  return (L loc (HsModule Nothing Nothing $2 [] Nothing 
-                   Nothing emptyHaddockModInfo Nothing)) }
+                  return (L loc (HsModule Nothing Nothing $2 [] Nothing
+                   emptyHaddockModInfo Nothing)) }
 
 header_body :: { [LImportDecl RdrName] }
        :  '{'            importdecls           { $2 }
@@ -614,7 +625,7 @@ ty_decl :: { LTyClDecl RdrName }
                              (unLoc $3) (reverse (unLoc $5)) (unLoc $6)) } }
 
           -- data/newtype family
-        | data_or_newtype 'family' tycl_hdr opt_kind_sig
+        | 'data' 'family' tycl_hdr opt_kind_sig
                {% do { let {(ctxt, tc, tvs, tparms) = unLoc $3}
                       ; checkTyVars tparms            -- no type pattern
                      ; unless (null (unLoc ctxt)) $  -- and no context
@@ -622,8 +633,7 @@ ty_decl :: { LTyClDecl RdrName }
                            "A family declaration cannot have a context"
                      ; return $
                          L (comb3 $1 $2 $4)
-                           (TyFamily (DataFamily (unLoc $1)) tc tvs 
-                                     (unLoc $4)) } }
+                           (TyFamily DataFamily tc tvs (unLoc $4)) } }
 
           -- data/newtype instance declaration
        | data_or_newtype 'instance' tycl_hdr constrs deriving
@@ -678,7 +688,7 @@ at_decl_cls :: { LTyClDecl RdrName }
                       } }
 
           -- data/newtype family declaration
-        | data_or_newtype tycl_hdr opt_kind_sig
+        | 'data' tycl_hdr opt_kind_sig
                {% do { let {(ctxt, tc, tvs, tparms) = unLoc $2}
                       ; checkTyVars tparms            -- no type pattern
                      ; unless (null (unLoc ctxt)) $  -- and no context
@@ -686,8 +696,7 @@ at_decl_cls :: { LTyClDecl RdrName }
                            "A family declaration cannot have a context"
                      ; return $
                          L (comb3 $1 $2 $3)
-                           (TyFamily (DataFamily (unLoc $1)) tc tvs
-                                     (unLoc $3)) 
+                           (TyFamily DataFamily tc tvs (unLoc $3)) 
                       } }
 
 -- Associate type instances
@@ -752,7 +761,7 @@ tycl_hdr :: { Located (LHsContext RdrName,
 
 -- Glasgow extension: stand-alone deriving declarations
 stand_alone_deriving :: { LDerivDecl RdrName }
-       : 'derive' 'instance' inst_type {% checkDerivDecl (LL (DerivDecl $3)) }
+       : 'deriving' 'instance' inst_type {% checkDerivDecl (LL (DerivDecl $3)) }
 
 -----------------------------------------------------------------------------
 -- Nested declarations
@@ -961,7 +970,7 @@ gentypedoc :: { LHsType RdrName }
 
 ctypedoc  :: { LHsType RdrName }
         : 'forall' tv_bndrs '.' ctypedoc { LL $ mkExplicitHsForAllTy $2 (noLoc []) $4 }
-        | context '=>' gentypedoc        { LL $ mkImplicitHsForAllTy   $1 $3 }
+        | context '=>' ctypedoc          { LL $ mkImplicitHsForAllTy   $1 $3 }
        -- A type of form (context => type) is an *implicit* HsForAllTy
        | gentypedoc                     { $1 }
        
@@ -1134,7 +1143,7 @@ forall :: { Located [LHsTyVarBndr RdrName] }
        : 'forall' tv_bndrs '.'         { LL $2 }
        | {- empty -}                   { noLoc [] }
 
-constr_stuff :: { Located (Located RdrName, HsConDetails RdrName (LBangType RdrName)) }
+constr_stuff :: { Located (Located RdrName, HsConDeclDetails RdrName) }
 -- We parse the constructor declaration 
 --     C t1 t2
 -- as a btype (treating C as a type constructor) and then convert C to be
@@ -1147,7 +1156,7 @@ constr_stuff :: { Located (Located RdrName, HsConDetails RdrName (LBangType RdrN
        | oqtycon '{' fielddecls '}'    {% mkRecCon $1 $3 >>= return.LL }
        | btype conop btype             { LL ($2, InfixCon $1 $3) }
 
-constr_stuff_record :: { Located (Located RdrName, HsConDetails RdrName (LBangType RdrName)) }
+constr_stuff_record :: { Located (Located RdrName, HsConDeclDetails RdrName) }
        : oqtycon '{' '}'               {% mkRecCon $1 [] >>= return.sL (comb2 $1 $>) }
        | oqtycon '{' fielddecls '}'    {% mkRecCon $1 $3 >>= return.sL (comb2 $1 $>) }
 
@@ -1223,7 +1232,7 @@ gdrhs :: { Located [LGRHS RdrName] }
        | gdrh                  { L1 [$1] }
 
 gdrh :: { LGRHS RdrName }
-       : '|' quals '=' exp     { sL (comb2 $1 $>) $ GRHS (reverse (unLoc $2)) $4 }
+       : '|' guardquals '=' exp        { sL (comb2 $1 $>) $ GRHS (unLoc $2) $4 }
 
 sigdecl :: { Located (OrdList (LHsDecl RdrName)) }
        : infixexp '::' sigtypedoc
@@ -1268,7 +1277,7 @@ exp10 :: { LHsExpr RdrName }
        | 'let' binds 'in' exp                  { LL $ HsLet (unLoc $2) $4 }
        | 'if' exp 'then' exp 'else' exp        { LL $ HsIf $2 $4 $6 }
        | 'case' exp 'of' altslist              { LL $ HsCase $2 (mkMatchGroup (unLoc $4)) }
-       | '-' fexp                              { LL $ mkHsNegApp $2 }
+       | '-' fexp                              { LL $ NegApp $2 noSyntaxExpr }
 
        | 'do' stmtlist                 {% let loc = comb2 $1 $2 in
                                           checkDo loc (unLoc $2)  >>= \ (stmts,body) ->
@@ -1294,7 +1303,8 @@ exp10 :: { LHsExpr RdrName }
        | fexp                                  { $1 }
 
 scc_annot :: { Located FastString }
-       : '_scc_' STRING                        { LL $ getSTRING $2 }
+       : '_scc_' STRING                        {% (addWarning Opt_WarnDeprecations (getLoc $1) (text "_scc_ is deprecated; use an SCC pragma instead")) >>= \_ ->
+                                   (return $ LL $ getSTRING $2) }
        | '{-# SCC' STRING '#-}'                { LL $ getSTRING $2 }
 
 hpc_annot :: { Located (FastString,(Int,Int),(Int,Int)) }
@@ -1316,12 +1326,11 @@ fexp    :: { LHsExpr RdrName }
 aexp   :: { LHsExpr RdrName }
        : qvar '@' aexp                 { LL $ EAsPat $1 $3 }
        | '~' aexp                      { LL $ ELazyPat $2 }
-       | aexp1                         { $1 }
+       | aexp1                 { $1 }
 
 aexp1  :: { LHsExpr RdrName }
-        : aexp1 '{' fbinds '}'         {% do { r <- mkRecConstrOrUpdate $1 (comb2 $2 $4) 
-                                                       $3;
-                                       return (LL r) }}
+        : aexp1 '{' fbinds '}'         {% do { r <- mkRecConstrOrUpdate $1 (comb2 $2 $4) $3
+                                     ; return (LL r) }}
        | aexp2                 { $1 }
 
 -- Here was the syntax for type applications that I was planning
@@ -1338,16 +1347,18 @@ aexp2   :: { LHsExpr RdrName }
        | literal                       { L1 (HsLit   $! unLoc $1) }
 -- This will enable overloaded strings permanently.  Normally the renamer turns HsString
 -- into HsOverLit when -foverloaded-strings is on.
---     | STRING                        { L1 (HsOverLit $! mkHsIsString (getSTRING $1)) }
-       | INTEGER                       { L1 (HsOverLit $! mkHsIntegral (getINTEGER $1)) }
-       | RATIONAL                      { L1 (HsOverLit $! mkHsFractional (getRATIONAL $1)) }
-       | '(' exp ')'                   { LL (HsPar $2) }
+--     | STRING                        { sL (getLoc $1) (HsOverLit $! mkHsIsString (getSTRING $1) placeHolderType) }
+       | INTEGER                       { sL (getLoc $1) (HsOverLit $! mkHsIntegral (getINTEGER $1) placeHolderType) }
+       | RATIONAL                      { sL (getLoc $1) (HsOverLit $! mkHsFractional (getRATIONAL $1) placeHolderType) }
+        -- N.B.: sections get parsed by these next two productions.
+        -- This allows you to write, e.g., '(+ 3, 4 -)', which isn't correct Haskell98
+        -- (you'd have to write '((+ 3), (4 -))')
+        -- but the less cluttered version fell out of having texps.
+       | '(' texp ')'                  { LL (HsPar $2) }
        | '(' texp ',' texps ')'        { LL $ ExplicitTuple ($2 : reverse $4) Boxed }
        | '(#' texps '#)'               { LL $ ExplicitTuple (reverse $2)      Unboxed }
        | '[' list ']'                  { LL (unLoc $2) }
        | '[:' parr ':]'                { LL (unLoc $2) }
-       | '(' infixexp qop ')'          { LL $ SectionL $2 $3 }
-       | '(' qopm infixexp ')'         { LL $ SectionR $2 $3 }
        | '_'                           { L1 EWildPat }
        
        -- Template Haskell Extension
@@ -1385,11 +1396,17 @@ cvtopdecls0 :: { [LHsDecl RdrName] }
        : {- empty -}           { [] }
        | cvtopdecls            { $1 }
 
+-- tuple expressions: things that can appear unparenthesized as long as they're
+-- inside parens or delimitted by commas
 texp :: { LHsExpr RdrName }
        : exp                           { $1 }
-       | qopm infixexp                 { LL $ SectionR $1 $2 }
-       -- The second production is really here only for bang patterns
-       -- but 
+       -- Technically, this should only be used for bang patterns,
+       -- but we can be a little more liberal here and avoid parens
+       -- inside tuples
+       | infixexp qop  { LL $ SectionL $1 $2 }
+       | qopm infixexp       { LL $ SectionR $1 $2 }
+       -- view patterns get parenthesized above
+       | exp '->' exp   { LL $ EViewPat $1 $3 }
 
 texps :: { [LHsExpr RdrName] }
        : texps ',' texp                { $3 : $1 }
@@ -1409,7 +1426,7 @@ list :: { LHsExpr RdrName }
        | texp ',' exp '..'     { LL $ ArithSeq noPostTcExpr (FromThen $1 $3) }
        | texp '..' exp         { LL $ ArithSeq noPostTcExpr (FromTo $1 $3) }
        | texp ',' exp '..' exp { LL $ ArithSeq noPostTcExpr (FromThenTo $1 $3 $5) }
-       | texp pquals           { sL (comb2 $1 $>) $ mkHsDo ListComp (reverse (unLoc $2)) $1 }
+       | texp '|' flattenedpquals      { sL (comb2 $1 $>) $ mkHsDo ListComp (unLoc $3) $1 }
 
 lexps :: { Located [LHsExpr RdrName] }
        : lexps ',' texp                { LL ($3 : unLoc $1) }
@@ -1418,23 +1435,50 @@ lexps :: { Located [LHsExpr RdrName] }
 -----------------------------------------------------------------------------
 -- List Comprehensions
 
-pquals :: { Located [LStmt RdrName] }  -- Either a singleton ParStmt, 
-                                       -- or a reversed list of Stmts
-       : pquals1                       { case unLoc $1 of
-                                           [qs] -> L1 qs
-                                           qss  -> L1 [L1 (ParStmt stmtss)]
-                                                where
-                                                   stmtss = [ (reverse qs, undefined) 
-                                                            | qs <- qss ]
-                                       }
-                       
+flattenedpquals :: { Located [LStmt RdrName] }
+    : pquals   { case (unLoc $1) of
+                    ParStmt [(qs, _)] -> L1 qs
+                    -- We just had one thing in our "parallel" list so 
+                    -- we simply return that thing directly
+                    
+                    _ -> L1 [$1]
+                    -- We actually found some actual parallel lists so
+                    -- we leave them into as a ParStmt
+                }
+
+pquals :: { LStmt RdrName }
+    : pquals1   { L1 (ParStmt [(qs, undefined) | qs <- (reverse (unLoc $1))]) }
+
 pquals1 :: { Located [[LStmt RdrName]] }
-       : pquals1 '|' quals             { LL (unLoc $3 : unLoc $1) }
-       | '|' quals                     { L (getLoc $2) [unLoc $2] }
+    : pquals1 '|' squals    { LL (unLoc $3 : unLoc $1) }
+    | squals                { L (getLoc $1) [unLoc $1] }
+
+squals :: { Located [LStmt RdrName] }
+    : squals1               { L (getLoc $1) (reverse (unLoc $1)) }
+
+squals1 :: { Located [LStmt RdrName] }
+    : transformquals1       { LL (unLoc $1) }
+
+transformquals1 :: { Located [LStmt RdrName] }
+    : transformquals1 ',' transformqual         { LL $ [LL ((unLoc $3) (unLoc $1))] }
+    | transformquals1 ',' qual                  { LL ($3 : unLoc $1) }
+--  | transformquals1 ',' '{|' pquals '|}'      { LL ($4 : unLoc $1) }
+    | transformqual                             { LL $ [LL ((unLoc $1) [])] }
+    | qual                                      { L1 [$1] }
+--  | '{|' pquals '|}'                          { L1 [$2] }
 
-quals :: { Located [LStmt RdrName] }
-       : quals ',' qual                { LL ($3 : unLoc $1) }
-       | qual                          { L1 [$1] }
+
+-- It is possible to enable bracketing (associating) qualifier lists by uncommenting the lines with {| |}
+-- above. Due to a lack of consensus on the syntax, this feature is not being used until we get user
+-- demand. Note that the {| |} symbols are reused from -XGenerics and hence if you want to compile
+-- a program that makes use of this temporary syntax you must supply that flag to GHC
+
+transformqual :: { Located ([LStmt RdrName] -> Stmt RdrName) }
+    : 'then' exp                { LL $ \leftStmts -> (mkTransformStmt (reverse leftStmts) $2) }
+    | 'then' exp 'by' exp       { LL $ \leftStmts -> (mkTransformByStmt (reverse leftStmts) $2 $4) }
+    | 'then' 'group' 'by' exp              { LL $ \leftStmts -> (mkGroupByStmt (reverse leftStmts) $4) }
+    | 'then' 'group' 'using' exp           { LL $ \leftStmts -> (mkGroupUsingStmt (reverse leftStmts) $4) }
+    | 'then' 'group' 'by' exp 'using' exp  { LL $ \leftStmts -> (mkGroupByUsingStmt (reverse leftStmts) $4 $6) }
 
 -----------------------------------------------------------------------------
 -- Parallel array expressions
@@ -1451,9 +1495,19 @@ parr :: { LHsExpr RdrName }
                                                       (reverse (unLoc $1)) }
        | texp '..' exp                 { LL $ PArrSeq noPostTcExpr (FromTo $1 $3) }
        | texp ',' exp '..' exp         { LL $ PArrSeq noPostTcExpr (FromThenTo $1 $3 $5) }
-       | texp pquals                   { sL (comb2 $1 $>) $ mkHsDo PArrComp (reverse (unLoc $2)) $1 }
+       | texp '|' flattenedpquals      { LL $ mkHsDo PArrComp (unLoc $3) $1 }
 
--- We are reusing `lexps' and `pquals' from the list case.
+-- We are reusing `lexps' and `flattenedpquals' from the list case.
+
+-----------------------------------------------------------------------------
+-- Guards
+
+guardquals :: { Located [LStmt RdrName] }
+    : guardquals1           { L (getLoc $1) (reverse (unLoc $1)) }
+
+guardquals1 :: { Located [LStmt RdrName] }
+    : guardquals1 ',' qual  { LL ($3 : unLoc $1) }
+    | qual                  { L1 [$1] }
 
 -----------------------------------------------------------------------------
 -- Case alternatives
@@ -1486,14 +1540,14 @@ gdpats :: { Located [LGRHS RdrName] }
        | gdpat                         { L1 [$1] }
 
 gdpat  :: { LGRHS RdrName }
-       : '|' quals '->' exp            { sL (comb2 $1 $>) $ GRHS (reverse (unLoc $2)) $4 }
+       : '|' guardquals '->' exp               { sL (comb2 $1 $>) $ GRHS (unLoc $2) $4 }
 
 -- 'pat' recognises a pattern, including one with a bang at the top
 --     e.g.  "!x" or "!(x,y)" or "C a b" etc
 -- Bangs inside are parsed as infix operator applications, so that
 -- we parse them right when bang-patterns are off
 pat     :: { LPat RdrName }
-pat    : infixexp              {% checkPattern $1 }
+pat    :  exp                  {% checkPattern $1 }
        | '!' aexp              {% checkPattern (LL (SectionR (L1 (HsVar bang_RDR)) $2)) }
 
 apat   :: { LPat RdrName }     
@@ -1532,30 +1586,32 @@ maybe_stmt :: { Maybe (LStmt RdrName) }
        | {- nothing -}                 { Nothing }
 
 stmt  :: { LStmt RdrName }
-       : qual                          { $1 }
--- What is this next production doing?  I have no clue!  SLPJ Dec06
-       | infixexp '->' exp             {% checkPattern $3 >>= \p ->
-                                          return (LL $ mkBindStmt p $1) }
+       : qual                              { $1 }
        | 'rec' stmtlist                { LL $ mkRecStmt (unLoc $2) }
 
 qual  :: { LStmt RdrName }
-       : pat '<-' exp                  { LL $ mkBindStmt $1 $3 }
-       | exp                           { L1 $ mkExprStmt $1 }
-       | 'let' binds                   { LL $ LetStmt (unLoc $2) }
+    : pat '<-' exp                     { LL $ mkBindStmt $1 $3 }
+    | exp                                  { L1 $ mkExprStmt $1 }
+    | 'let' binds                      { LL $ LetStmt (unLoc $2) }
 
 -----------------------------------------------------------------------------
 -- Record Field Update/Construction
 
-fbinds         :: { HsRecordBinds RdrName }
-       : fbinds1                       { HsRecordBinds (reverse $1) }
-       | {- empty -}                   { HsRecordBinds [] }
+fbinds         :: { ([HsRecField RdrName (LHsExpr RdrName)], Bool) }
+       : fbinds1                       { $1 }
+       | {- empty -}                   { ([], False) }
 
-fbinds1        :: { [(Located id, LHsExpr id)] }
-       : fbinds1 ',' fbind             { $3 : $1 }
-       | fbind                         { [$1] }
+fbinds1        :: { ([HsRecField RdrName (LHsExpr RdrName)], Bool) }
+       : fbind ',' fbinds1             { case $3 of (flds, dd) -> ($1 : flds, dd) } 
+       | fbind                         { ([$1], False) }
+       | '..'                          { ([],   True) }
   
-fbind  :: { (Located RdrName, LHsExpr RdrName) }
-       : qvar '=' exp                  { ($1,$3) }
+fbind  :: { HsRecField RdrName (LHsExpr RdrName) }
+       : qvar '=' exp  { HsRecField $1 $3 False }
+       | qvar          { HsRecField $1 (L (getLoc $1) (HsVar (unLoc $1))) True }
+                       -- Here's where we say that plain 'x'
+                       -- means exactly 'x = x'.  The pun-flag boolean is
+                       -- there so we can still print it right
 
 -----------------------------------------------------------------------------
 -- Implicit Parameter Bindings
@@ -1753,7 +1809,6 @@ special_id
        : 'as'                  { L1 FSLIT("as") }
        | 'qualified'           { L1 FSLIT("qualified") }
        | 'hiding'              { L1 FSLIT("hiding") }
-       | 'derive'              { L1 FSLIT("derive") }
        | 'export'              { L1 FSLIT("export") }
        | 'label'               { L1 FSLIT("label")  }
        | 'dynamic'             { L1 FSLIT("dynamic") }
@@ -1825,38 +1880,35 @@ commas :: { Int }
 
 docnext :: { LHsDoc RdrName }
   : DOCNEXT {% case parseHaddockParagraphs (tokenise (getDOCNEXT $1)) of {
-      Left  err -> parseError (getLoc $1) err;
-      Right doc -> return (L1 doc) } }
+      MyLeft  err -> parseError (getLoc $1) err;
+      MyRight doc -> return (L1 doc) } }
 
 docprev :: { LHsDoc RdrName }
   : DOCPREV {% case parseHaddockParagraphs (tokenise (getDOCPREV $1)) of {
-      Left  err -> parseError (getLoc $1) err;
-      Right doc -> return (L1 doc) } }
+      MyLeft  err -> parseError (getLoc $1) err;
+      MyRight doc -> return (L1 doc) } }
 
 docnamed :: { Located (String, (HsDoc RdrName)) }
   : DOCNAMED {%
       let string = getDOCNAMED $1 
           (name, rest) = break isSpace string
       in case parseHaddockParagraphs (tokenise rest) of {
-        Left  err -> parseError (getLoc $1) err;
-        Right doc -> return (L1 (name, doc)) } }
+        MyLeft  err -> parseError (getLoc $1) err;
+        MyRight doc -> return (L1 (name, doc)) } }
 
 docsection :: { Located (n, HsDoc RdrName) }
   : DOCSECTION {% let (n, doc) = getDOCSECTION $1 in
         case parseHaddockString (tokenise doc) of {
-      Left  err -> parseError (getLoc $1) err;
-      Right doc -> return (L1 (n, doc)) } }
-
-docoptions :: { String }
-  : DOCOPTIONS { getDOCOPTIONS $1 }
+      MyLeft  err -> parseError (getLoc $1) err;
+      MyRight doc -> return (L1 (n, doc)) } }
 
 moduleheader :: { (HaddockModInfo RdrName, Maybe (HsDoc RdrName)) }                                    
         : DOCNEXT {% let string = getDOCNEXT $1 in
                case parseModuleHeader string of {                       
                  Right (str, info) ->                                  
                    case parseHaddockParagraphs (tokenise str) of {               
-                     Left err -> parseError (getLoc $1) err;                    
-                     Right doc -> return (info, Just doc);          
+                     MyLeft err -> parseError (getLoc $1) err;                    
+                     MyRight doc -> return (info, Just doc);          
                    };                                             
                  Left err -> parseError (getLoc $1) err
             }  }                                                  
@@ -1899,7 +1951,6 @@ getDOCNEXT (L _ (ITdocCommentNext x)) = x
 getDOCPREV (L _ (ITdocCommentPrev x)) = x
 getDOCNAMED (L _ (ITdocCommentNamed x)) = x
 getDOCSECTION (L _ (ITdocSection n x)) = (n, x)
-getDOCOPTIONS (L _ (ITdocOptions x)) = x
 
 -- Utilities for combining source spans
 comb2 :: Located a -> Located b -> SrcSpan