Fix Trac #3403: interaction of CPR and pattern-match failure
[ghc-hetmet.git] / compiler / parser / Parser.y.pp
index 6712f4e..9f3dd27 100644 (file)
@@ -399,8 +399,8 @@ missing_module_keyword :: { () }
        : {- empty -}                           {% pushCurrentContext }
 
 maybemodwarning :: { Maybe WarningTxt }
-    : '{-# DEPRECATED' STRING '#-}' { Just (DeprecatedTxt (getSTRING $2)) }
-    | '{-# WARNING' STRING '#-}'    { Just (WarningTxt (getSTRING $2)) }
+    : '{-# DEPRECATED' strings '#-}' { Just (DeprecatedTxt $ unLoc $2) }
+    | '{-# WARNING' strings '#-}'    { Just (WarningTxt $ unLoc $2) }
     |  {- empty -}                  { Nothing }
 
 body   :: { ([LImportDecl RdrName], [LHsDecl RdrName]) }
@@ -707,7 +707,7 @@ tycl_hdr :: { Located (LHsContext RdrName, LHsType RdrName) }
 
 -- Glasgow extension: stand-alone deriving declarations
 stand_alone_deriving :: { LDerivDecl RdrName }
-       : 'deriving' 'instance' inst_type {% checkDerivDecl (LL (DerivDecl $3)) }
+       : 'deriving' 'instance' inst_type { LL (DerivDecl $3) }
 
 -----------------------------------------------------------------------------
 -- Nested declarations
@@ -839,8 +839,8 @@ warnings :: { OrdList (LHsDecl RdrName) }
 
 -- SUP: TEMPORARY HACK, not checking for `module Foo'
 warning :: { OrdList (LHsDecl RdrName) }
-       : namelist STRING
-               { toOL [ LL $ WarningD (Warning n (WarningTxt (getSTRING $2)))
+       : namelist strings
+               { toOL [ LL $ WarningD (Warning n (WarningTxt $ unLoc $2))
                       | n <- unLoc $1 ] }
 
 deprecations :: { OrdList (LHsDecl RdrName) }
@@ -851,10 +851,18 @@ deprecations :: { OrdList (LHsDecl RdrName) }
 
 -- SUP: TEMPORARY HACK, not checking for `module Foo'
 deprecation :: { OrdList (LHsDecl RdrName) }
-       : namelist STRING
-               { toOL [ LL $ WarningD (Warning n (DeprecatedTxt (getSTRING $2)))
+       : namelist strings
+               { toOL [ LL $ WarningD (Warning n (DeprecatedTxt $ unLoc $2))
                       | n <- unLoc $1 ] }
 
+strings :: { Located [FastString] }
+    : STRING { L1 [getSTRING $1] }
+    | '[' stringlist ']' { LL $ fromOL (unLoc $2) }
+
+stringlist :: { Located (OrdList FastString) }
+    : stringlist ',' STRING { LL (unLoc $1 `snocOL` getSTRING $3) }
+    | STRING                { LL (unitOL (getSTRING $1)) }
+
 -----------------------------------------------------------------------------
 -- Annotations
 annotation :: { LHsDecl RdrName }
@@ -1488,8 +1496,18 @@ transformquals1 :: { Located [LStmt RdrName] }
 
 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) }
+    -- <<<
+    -- These two productions deliberately have a shift-reduce conflict. I have made 'group' into a special_id,
+    -- which means you can enable TransformListComp while still using Data.List.group. However, this makes the two
+    -- productions ambiguous. I've set things up so that Happy chooses to resolve the conflict in that case by
+    -- choosing the "group by" variant, which is what we want.
+    --
+    -- This is rather dubious: the user might be confused as to how to parse this statement. However, it is a good
+    -- practical choice. NB: Data.List.group :: [a] -> [[a]], so using the first production would not even type check
+    -- if /that/ is the group function we conflict with.
     | 'then' 'group' 'using' exp           { LL $ \leftStmts -> (mkGroupUsingStmt (reverse leftStmts) $4) }
     | 'then' 'group' 'by' exp 'using' exp  { LL $ \leftStmts -> (mkGroupByUsingStmt (reverse leftStmts) $4 $6) }
 
@@ -1621,7 +1639,7 @@ fbinds1   :: { ([HsRecField RdrName (LHsExpr RdrName)], Bool) }
   
 fbind  :: { HsRecField RdrName (LHsExpr RdrName) }
        : qvar '=' exp  { HsRecField $1 $3 False }
-       | qvar          { HsRecField $1 (L (getLoc $1) (HsVar (unLoc $1))) True }
+        | qvar          { HsRecField $1 (L (getLoc $1) placeHolderPunRhs) 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
@@ -1841,6 +1859,7 @@ special_id
        | 'stdcall'             { L1 (fsLit "stdcall") }
        | 'ccall'               { L1 (fsLit "ccall") }
        | 'prim'                { L1 (fsLit "prim") }
+       | 'group'               { L1 (fsLit "group") }
 
 special_sym :: { Located FastString }
 special_sym : '!'      { L1 (fsLit "!") }