-- ---------------------------------------------------------------------------
{
+{-# 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
+
+{-# OPTIONS_GHC -O0 -fno-ignore-interface-pragmas #-}
+{-
+Careful optimisation of the parser: we don't want to throw everything
+at it, because that takes too long and doesn't buy much, but we do want
+to inline certain key external functions, so we instruct GHC not to
+throw away inlinings as it would normally do in -O0 mode.
+-}
+
module Parser ( parseModule, parseStmt, parseIdentifier, parseType,
parseHeader ) where
-#define INCLUDE #include
-INCLUDE "HsVersions.h"
-
import HsSyn
import RdrHsSyn
-import HscTypes ( IsBootInterface, DeprecTxt )
+import HscTypes ( IsBootInterface, WarningTxt(..) )
import Lexer
import RdrName
import TysWiredIn ( unitTyCon, unitDataCon, tupleTyCon, tupleCon, nilDataCon,
+ unboxedSingletonTyCon, unboxedSingletonDataCon,
listTyCon_RDR, parrTyCon_RDR, consDataCon_RDR )
import Type ( funTyCon )
import ForeignCall ( Safety(..), CExportSpec(..), CLabelString,
SrcSpan, combineLocs, srcLocFile,
mkSrcLoc, mkSrcSpan )
import Module
-import StaticFlags ( opt_SccProfilingOn )
+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 )
+import HaddockUtils
import FastString
import Maybes ( orElse )
import Outputable
-import GLAEXTS
+
+import Control.Monad ( unless )
+import GHC.Exts
+import Data.Char
+import Control.Monad ( mplus )
}
{-
-----------------------------------------------------------------------------
+24 Februar 2006
+
+Conflicts: 33 shift/reduce
+ 1 reduce/reduce
+
+The reduce/reduce conflict is weird. It's between tyconsym and consym, and I
+would think the two should never occur in the same context.
+
+ -=chak
+
+-----------------------------------------------------------------------------
+31 December 2006
+
+Conflicts: 34 shift/reduce
+ 1 reduce/reduce
+
+The reduce/reduce conflict is weird. It's between tyconsym and consym, and I
+would think the two should never occur in the same context.
+
+ -=chak
+
+-----------------------------------------------------------------------------
+6 December 2006
+
+Conflicts: 32 shift/reduce
+ 1 reduce/reduce
+
+The reduce/reduce conflict is weird. It's between tyconsym and consym, and I
+would think the two should never occur in the same context.
+
+ -=chak
+
+-----------------------------------------------------------------------------
26 July 2006
Conflicts: 37 shift/reduce
-=chak
-----------------------------------------------------------------------------
-Conflicts: 36 shift/reduce (1.25)
+Conflicts: 38 shift/reduce (1.25)
10 for abiguity in 'if x then y else z + 1' [State 178]
(shift parses as 'if x then y else (z + 1)', as per longest-parse rule)
This saves explicitly defining a grammar for the rule lhs that
doesn't include 'forall'.
+1 for ambiguity when the source file starts with "-- | doc". We need another
+ token of lookahead to determine if a top declaration or the 'module' keyword
+ follows. Shift parses as if the 'module' keyword follows.
+
-- ---------------------------------------------------------------------------
-- Adding location info
'threadsafe' { L _ ITthreadsafe }
'unsafe' { L _ ITunsafe }
'mdo' { L _ ITmdo }
- 'iso' { L _ ITiso }
+ 'family' { L _ ITfamily }
'stdcall' { L _ ITstdcallconv }
'ccall' { L _ ITccallconv }
'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 }
'{-# RULES' { L _ ITrules_prag }
'{-# CORE' { L _ ITcore_prag } -- hdaume: annotated core
'{-# SCC' { L _ ITscc_prag }
+ '{-# GENERATED' { L _ ITgenerated_prag }
'{-# DEPRECATED' { L _ ITdeprecated_prag }
+ '{-# WARNING' { L _ ITwarning_prag }
'{-# UNPACK' { L _ ITunpack_prag }
'#-}' { L _ ITclose_prag }
QCONSYM { L _ (ITqconsym _) }
IPDUPVARID { L _ (ITdupipvarid _) } -- GHC extension
- IPSPLITVARID { L _ (ITsplitipvarid _) } -- GHC extension
CHAR { L _ (ITchar _) }
STRING { L _ (ITstring _) }
PRIMCHAR { L _ (ITprimchar _) }
PRIMSTRING { L _ (ITprimstring _) }
PRIMINTEGER { L _ (ITprimint _) }
+ PRIMWORD { L _ (ITprimword _) }
PRIMFLOAT { L _ (ITprimfloat _) }
PRIMDOUBLE { L _ (ITprimdouble _) }
-
+
+ DOCNEXT { L _ (ITdocCommentNext _) }
+ DOCPREV { L _ (ITdocCommentPrev _) }
+ DOCNAMED { L _ (ITdocCommentNamed _) }
+ DOCSECTION { L _ (ITdocSection _ _) }
+
-- Template Haskell
'[|' { L _ ITopenExpQuote }
'[p|' { L _ ITopenPatQuote }
'$(' { L _ ITparenEscape } -- $( exp )
TH_VAR_QUOTE { L _ ITvarQuote } -- 'x
TH_TY_QUOTE { L _ ITtyQuote } -- ''T
+TH_QUASIQUOTE { L _ (ITquasiQuote _) }
%monad { P } { >>= } { return }
%lexer { lexer } { L _ ITeof }
| qcon { $1 }
| qvarop { $1 }
| qconop { $1 }
+ | '(' '->' ')' { LL $ getRdrName funTyCon }
-----------------------------------------------------------------------------
-- Module Header
-- know what they are doing. :-)
module :: { Located (HsModule RdrName) }
- : 'module' modid maybemoddeprec maybeexports 'where' body
+ : maybedocheader 'module' modid maybemodwarning 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 (Just $2) $4 (fst $6) (snd $6) $3)) }
- | missing_module_keyword top close
- {% fileSrcSpan >>= \ loc ->
- return (L loc (HsModule Nothing Nothing
- (fst $2) (snd $2) Nothing)) }
+ return (L loc (HsModule Nothing Nothing
+ (fst $1) (snd $1) Nothing emptyHaddockModInfo
+ Nothing)) }
+
+maybedocheader :: { (HaddockModInfo RdrName, Maybe (HsDoc RdrName)) }
+ : moduleheader { $1 }
+ | {- empty -} { (emptyHaddockModInfo, Nothing) }
missing_module_keyword :: { () }
: {- empty -} {% pushCurrentContext }
-maybemoddeprec :: { Maybe DeprecTxt }
- : '{-# DEPRECATED' STRING '#-}' { Just (getSTRING $2) }
- | {- empty -} { Nothing }
+maybemodwarning :: { Maybe WarningTxt }
+ : '{-# DEPRECATED' STRING '#-}' { Just (DeprecatedTxt (getSTRING $2)) }
+ | '{-# WARNING' STRING '#-}' { Just (WarningTxt (getSTRING $2)) }
+ | {- empty -} { Nothing }
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) }
-- Module declaration & imports only
header :: { Located (HsModule RdrName) }
- : 'module' modid maybemoddeprec maybeexports 'where' header_body
- {% fileSrcSpan >>= \ loc ->
- return (L loc (HsModule (Just $2) $4 $6 [] $3)) }
+ : maybedocheader 'module' modid maybemodwarning 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)) }
+ return (L loc (HsModule Nothing Nothing $2 [] Nothing
+ emptyHaddockModInfo Nothing)) }
header_body :: { [LImportDecl RdrName] }
: '{' importdecls { $2 }
: '(' exportlist ')' { Just $2 }
| {- empty -} { Nothing }
-exportlist :: { [LIE RdrName] }
- : ',' { [] }
+exportlist :: { [LIE RdrName] }
+ : expdoclist ',' expdoclist { $1 ++ $3 }
| exportlist1 { $1 }
exportlist1 :: { [LIE RdrName] }
- : export { [$1] }
- | export ',' exportlist { $1 : $3 }
- | {- empty -} { [] }
-
+ : expdoclist export expdoclist ',' exportlist { $1 ++ ($2 : $3) ++ $5 }
+ | expdoclist export expdoclist { $1 ++ ($2 : $3) }
+ | expdoclist { $1 }
+
+expdoclist :: { [LIE RdrName] }
+ : exp_doc expdoclist { $1 : $2 }
+ | {- empty -} { [] }
+
+exp_doc :: { LIE RdrName }
+ : docsection { L1 (case (unLoc $1) of (n, doc) -> IEGroup n doc) }
+ | docnamed { L1 (IEDocNamed ((fst . unLoc) $1)) }
+ | docnext { L1 (IEDoc (unLoc $1)) }
+
-- No longer allow things like [] and (,,,) to be exported
-- They are built in syntax, always available
export :: { LIE RdrName }
| 'module' modid { LL (IEModuleContents (unLoc $2)) }
qcnames :: { [RdrName] }
- : qcnames ',' qcname { unLoc $3 : $1 }
- | qcname { [unLoc $1] }
+ : qcnames ',' qcname_ext { unLoc $3 : $1 }
+ | qcname_ext { [unLoc $1] }
+
+qcname_ext :: { Located RdrName } -- Variable or data constructor
+ -- or tagged type constructor
+ : qcname { $1 }
+ | 'type' qcon { sL (comb2 $1 $2)
+ (setRdrNameSpace (unLoc $2)
+ tcClsName) }
+-- Cannot pull into qcname_ext, as qcname is also used in expression.
qcname :: { Located RdrName } -- Variable or data constructor
- : qvar { $1 }
- | qcon { $1 }
+ : qvar { $1 }
+ | qcon { $1 }
-----------------------------------------------------------------------------
-- Import Declarations
-- Top-Level Declarations
topdecls :: { OrdList (LHsDecl RdrName) }
- : topdecls ';' topdecl { $1 `appOL` $3 }
- | topdecls ';' { $1 }
- | topdecl { $1 }
+ : topdecls ';' topdecl { $1 `appOL` $3 }
+ | topdecls ';' { $1 }
+ | topdecl { $1 }
topdecl :: { OrdList (LHsDecl RdrName) }
: cl_decl { unitOL (L1 (TyClD (unLoc $1))) }
- | ty_decl {% checkTopTypeD $1 >>=
- return.unitOL.L1 }
- | 'instance' inst_type where
- { let (binds, sigs, ats) = cvBindsAndSigs (unLoc $3)
- in unitOL (L (comb3 $1 $2 $3)
- (InstD (InstDecl $2 binds sigs ats))) }
+ | ty_decl { unitOL (L1 (TyClD (unLoc $1))) }
+ | 'instance' inst_type where_inst
+ { let (binds, sigs, ats, _) = cvBindsAndSigs (unLoc $3)
+ in
+ unitOL (L (comb3 $1 $2 $3) (InstD (InstDecl $2 binds sigs ats)))}
+ | stand_alone_deriving { unitOL (LL (DerivD (unLoc $1))) }
| 'default' '(' comma_types0 ')' { unitOL (LL $ DefD (DefaultDecl $3)) }
| 'foreign' fdecl { unitOL (LL (unLoc $2)) }
- | '{-# DEPRECATED' deprecations '#-}' { $2 }
+ | '{-# DEPRECATED' deprecations '#-}' { $2 }
+ | '{-# WARNING' warnings '#-}' { $2 }
| '{-# RULES' rules '#-}' { $2 }
| decl { unLoc $1 }
-- Type classes
--
cl_decl :: { LTyClDecl RdrName }
- : 'class' tycl_hdr fds where
- {% do { let { (binds, sigs, ats) =
+ : 'class' tycl_hdr fds where_cls
+ {% do { let { (binds, sigs, ats, docs) =
cvBindsAndSigs (unLoc $4)
; (ctxt, tc, tvs, tparms) = unLoc $2}
- ; checkTyVars tparms False -- only type vars allowed
+ ; checkTyVars tparms -- only type vars allowed
; checkKindSigs ats
; return $ L (comb4 $1 $2 $3 $4)
(mkClassDecl (ctxt, tc, tvs)
- (unLoc $3) sigs binds ats) } }
+ (unLoc $3) sigs binds ats docs) } }
--- Type declarations
+-- Type declarations (toplevel)
--
ty_decl :: { LTyClDecl RdrName }
- -- type function signature and equations (w/ type synonyms as special
- -- case); we need to handle all this in one rule to avoid a large
- -- number of shift/reduce conflicts
- : 'type' opt_iso type kind_or_ctype
+ -- ordinary type synonyms
+ : 'type' type '=' ctype
+ -- Note ctype, not sigtype, on the right of '='
+ -- We allow an explicit for-all but we don't insert one
+ -- in type Foo a = (b,b)
+ -- Instead we just say b is out of scope
--
-- Note the use of type for the head; this allows
- -- infix type constructors to be declared and type
- -- patterns for type function equations
- --
- -- We have that `typats :: Maybe [LHsType name]' is `Nothing'
- -- (in the second case alternative) when all arguments are
- -- variables (and we thus have a vanilla type synonym
- -- declaration); otherwise, it contains all arguments as type
- -- patterns.
+ -- infix type constructors to be declared
+ {% do { (tc, tvs, _) <- checkSynHdr $2 False
+ ; return (L (comb2 $1 $4)
+ (TySynonym tc tvs Nothing $4))
+ } }
+
+ -- type family declarations
+ | 'type' 'family' type opt_kind_sig
+ -- Note the use of type for the head; this allows
+ -- infix type constructors to be declared
--
- {% case $4 of
- Left kind ->
- do { (tc, tvs, _) <- checkSynHdr $3 False
- ; return (L (comb3 $1 $3 kind)
- (TyFunction tc tvs $2 (unLoc kind)))
- }
- Right ty | not $2 ->
- do { (tc, tvs, typats) <- checkSynHdr $3 True
- ; return (L (comb2 $1 ty)
- (TySynonym tc tvs typats ty)) }
- Right ty | otherwise ->
- parseError (comb2 $1 ty)
- "iso tag is only allowed in kind signatures"
- }
+ {% do { (tc, tvs, _) <- checkSynHdr $3 False
+ ; return (L (comb3 $1 $3 $4)
+ (TyFamily TypeFamily tc tvs (unLoc $4)))
+ } }
+
+ -- type instance declarations
+ | 'type' 'instance' type '=' ctype
+ -- Note the use of type for the head; this allows
+ -- infix type constructors and type patterns
+ --
+ {% do { (tc, tvs, typats) <- checkSynHdr $3 True
+ ; return (L (comb2 $1 $5)
+ (TySynonym tc tvs (Just typats) $5))
+ } }
+
+ -- ordinary data type or newtype declaration
+ | data_or_newtype tycl_hdr constrs deriving
+ {% do { let {(ctxt, tc, tvs, tparms) = unLoc $2}
+ ; checkTyVars tparms -- no type pattern
+ ; return $!
+ sL (comb4 $1 $2 $3 $4)
+ -- We need the location on tycl_hdr in case
+ -- constrs and deriving are both empty
+ (mkTyData (unLoc $1) (ctxt, tc, tvs, Nothing)
+ Nothing (reverse (unLoc $3)) (unLoc $4)) } }
- -- kind signature of indexed type
- | data_or_newtype tycl_hdr '::' kind
+ -- ordinary GADT declaration
+ | data_or_newtype tycl_hdr opt_kind_sig
+ 'where' gadt_constrlist
+ deriving
{% do { let {(ctxt, tc, tvs, tparms) = unLoc $2}
- ; checkTyVars tparms False -- no type pattern
+ ; checkTyVars tparms -- can have type pats
+ ; return $!
+ sL (comb4 $1 $2 $4 $5)
+ (mkTyData (unLoc $1) (ctxt, tc, tvs, Nothing)
+ (unLoc $3) (reverse (unLoc $5)) (unLoc $6)) } }
+
+ -- data/newtype family
+ | '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
+ parseError (getLoc ctxt)
+ "A family declaration cannot have a context"
; return $
L (comb3 $1 $2 $4)
- (mkTyData (unLoc $1) (ctxt, tc, tvs, Nothing)
- (Just (unLoc $4)) [] Nothing) } }
+ (TyFamily DataFamily tc tvs (unLoc $4)) } }
+
+ -- data/newtype instance declaration
+ | data_or_newtype 'instance' tycl_hdr constrs deriving
+ {% do { let {(ctxt, tc, tvs, tparms) = unLoc $3}
+ -- can have type pats
+ ; return $
+ L (comb4 $1 $3 $4 $5)
+ -- We need the location on tycl_hdr in case
+ -- constrs and deriving are both empty
+ (mkTyData (unLoc $1) (ctxt, tc, tvs, Just tparms)
+ Nothing (reverse (unLoc $4)) (unLoc $5)) } }
+
+ -- GADT instance declaration
+ | data_or_newtype 'instance' tycl_hdr opt_kind_sig
+ 'where' gadt_constrlist
+ deriving
+ {% do { let {(ctxt, tc, tvs, tparms) = unLoc $3}
+ -- can have type pats
+ ; return $
+ L (comb4 $1 $3 $6 $7)
+ (mkTyData (unLoc $1) (ctxt, tc, tvs, Just tparms)
+ (unLoc $4) (reverse (unLoc $6)) (unLoc $7)) } }
+
+-- Associate type family declarations
+--
+-- * They have a different syntax than on the toplevel (no family special
+-- identifier).
+--
+-- * They also need to be separate from instances; otherwise, data family
+-- declarations without a kind signature cause parsing conflicts with empty
+-- data declarations.
+--
+at_decl_cls :: { LTyClDecl RdrName }
+ -- type family declarations
+ : 'type' type opt_kind_sig
+ -- Note the use of type for the head; this allows
+ -- infix type constructors to be declared
+ --
+ {% do { (tc, tvs, _) <- checkSynHdr $2 False
+ ; return (L (comb3 $1 $2 $3)
+ (TyFamily TypeFamily tc tvs (unLoc $3)))
+ } }
+
+ -- default type instance
+ | 'type' type '=' ctype
+ -- Note the use of type for the head; this allows
+ -- infix type constructors and type patterns
+ --
+ {% do { (tc, tvs, typats) <- checkSynHdr $2 True
+ ; return (L (comb2 $1 $4)
+ (TySynonym tc tvs (Just typats) $4))
+ } }
- -- data type or newtype declaration
+ -- data/newtype family declaration
+ | '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
+ parseError (getLoc ctxt)
+ "A family declaration cannot have a context"
+ ; return $
+ L (comb3 $1 $2 $3)
+ (TyFamily DataFamily tc tvs (unLoc $3))
+ } }
+
+-- Associate type instances
+--
+at_decl_inst :: { LTyClDecl RdrName }
+ -- type instance declarations
+ : 'type' type '=' ctype
+ -- Note the use of type for the head; this allows
+ -- infix type constructors and type patterns
+ --
+ {% do { (tc, tvs, typats) <- checkSynHdr $2 True
+ ; return (L (comb2 $1 $4)
+ (TySynonym tc tvs (Just typats) $4))
+ } }
+
+ -- data/newtype instance declaration
| data_or_newtype tycl_hdr constrs deriving
{% do { let {(ctxt, tc, tvs, tparms) = unLoc $2}
- ; tpats <- checkTyVars tparms True -- can have type pats
+ -- can have type pats
; return $
L (comb4 $1 $2 $3 $4)
-- We need the location on tycl_hdr in case
-- constrs and deriving are both empty
- (mkTyData (unLoc $1) (ctxt, tc, tvs, tpats)
- Nothing (reverse (unLoc $3)) (unLoc $4)) } }
+ (mkTyData (unLoc $1) (ctxt, tc, tvs, Just tparms)
+ Nothing (reverse (unLoc $3)) (unLoc $4)) } }
- -- GADT declaration
+ -- GADT instance declaration
| data_or_newtype tycl_hdr opt_kind_sig
'where' gadt_constrlist
deriving
{% do { let {(ctxt, tc, tvs, tparms) = unLoc $2}
- ; tpats <- checkTyVars tparms True -- can have type pats
+ -- can have type pats
; return $
- L (comb4 $1 $2 $4 $5)
- (mkTyData (unLoc $1) (ctxt, tc, tvs, tpats) $3
- (reverse (unLoc $5)) (unLoc $6)) } }
-
-opt_iso :: { Bool }
- : { False }
- | 'iso' { True }
-
-kind_or_ctype :: { Either (Located Kind) (LHsType RdrName) }
- : '::' kind { Left (LL (unLoc $2)) }
- | '=' ctype { Right (LL (unLoc $2)) }
- -- Note ctype, not sigtype, on the right of '='
- -- We allow an explicit for-all but we don't insert one
- -- in type Foo a = (b,b)
- -- Instead we just say b is out of scope
+ L (comb4 $1 $2 $5 $6)
+ (mkTyData (unLoc $1) (ctxt, tc, tvs, Just tparms)
+ (unLoc $3) (reverse (unLoc $5)) (unLoc $6)) } }
data_or_newtype :: { Located NewOrData }
: 'data' { L1 DataType }
| 'newtype' { L1 NewType }
-opt_kind_sig :: { Maybe Kind }
- : { Nothing }
- | '::' kind { Just (unLoc $2) }
+opt_kind_sig :: { Located (Maybe Kind) }
+ : { noLoc Nothing }
+ | '::' kind { LL (Just (unLoc $2)) }
-- tycl_hdr parses the header of a class or data type decl,
-- which takes the form
| type {% checkTyClHdr (noLoc []) $1 >>= return.L1 }
-----------------------------------------------------------------------------
+-- Stand-alone deriving
+
+-- Glasgow extension: stand-alone deriving declarations
+stand_alone_deriving :: { LDerivDecl RdrName }
+ : 'deriving' 'instance' inst_type {% checkDerivDecl (LL (DerivDecl $3)) }
+
+-----------------------------------------------------------------------------
-- Nested declarations
--- Type declaration or value declaration
+-- Declaration in class bodies
--
-tydecl :: { Located (OrdList (LHsDecl RdrName)) }
-tydecl : ty_decl { LL (unitOL (L1 (TyClD (unLoc $1)))) }
- | decl { $1 }
-
-tydecls :: { Located (OrdList (LHsDecl RdrName)) } -- Reversed
- : tydecls ';' tydecl { LL (unLoc $1 `appOL` unLoc $3) }
- | tydecls ';' { LL (unLoc $1) }
- | tydecl { $1 }
- | {- empty -} { noLoc nilOL }
+decl_cls :: { Located (OrdList (LHsDecl RdrName)) }
+decl_cls : at_decl_cls { LL (unitOL (L1 (TyClD (unLoc $1)))) }
+ | decl { $1 }
+
+decls_cls :: { Located (OrdList (LHsDecl RdrName)) } -- Reversed
+ : decls_cls ';' decl_cls { LL (unLoc $1 `appOL` unLoc $3) }
+ | decls_cls ';' { LL (unLoc $1) }
+ | decl_cls { $1 }
+ | {- empty -} { noLoc nilOL }
+
+
+decllist_cls
+ :: { Located (OrdList (LHsDecl RdrName)) } -- Reversed
+ : '{' decls_cls '}' { LL (unLoc $2) }
+ | vocurly decls_cls close { $2 }
+
+-- Class body
+--
+where_cls :: { Located (OrdList (LHsDecl RdrName)) } -- Reversed
+ -- No implicit parameters
+ -- May have type declarations
+ : 'where' decllist_cls { LL (unLoc $2) }
+ | {- empty -} { noLoc nilOL }
+
+-- Declarations in instance bodies
+--
+decl_inst :: { Located (OrdList (LHsDecl RdrName)) }
+decl_inst : at_decl_inst { LL (unitOL (L1 (TyClD (unLoc $1)))) }
+ | decl { $1 }
+decls_inst :: { Located (OrdList (LHsDecl RdrName)) } -- Reversed
+ : decls_inst ';' decl_inst { LL (unLoc $1 `appOL` unLoc $3) }
+ | decls_inst ';' { LL (unLoc $1) }
+ | decl_inst { $1 }
+ | {- empty -} { noLoc nilOL }
-tydecllist
+decllist_inst
:: { Located (OrdList (LHsDecl RdrName)) } -- Reversed
- : '{' tydecls '}' { LL (unLoc $2) }
- | vocurly tydecls close { $2 }
+ : '{' decls_inst '}' { LL (unLoc $2) }
+ | vocurly decls_inst close { $2 }
--- Form of the body of class and instance declarations
+-- Instance body
--
-where :: { Located (OrdList (LHsDecl RdrName)) } -- Reversed
+where_inst :: { Located (OrdList (LHsDecl RdrName)) } -- Reversed
-- No implicit parameters
-- May have type declarations
- : 'where' tydecllist { LL (unLoc $2) }
+ : 'where' decllist_inst { LL (unLoc $2) }
| {- empty -} { noLoc nilOL }
+-- Declarations in binding groups other than classes and instances
+--
decls :: { Located (OrdList (LHsDecl RdrName)) }
- : decls ';' decl { LL (unLoc $1 `appOL` unLoc $3) }
+ : decls ';' decl { let { this = unLoc $3;
+ rest = unLoc $1;
+ these = rest `appOL` this }
+ in rest `seq` this `seq` these `seq`
+ LL these }
| decls ';' { LL (unLoc $1) }
| decl { $1 }
| {- empty -} { noLoc nilOL }
-
decllist :: { Located (OrdList (LHsDecl RdrName)) }
: '{' decls '}' { LL (unLoc $2) }
| vocurly decls close { $2 }
| '(' varid '::' ctype ')' { RuleBndrSig $2 $4 }
-----------------------------------------------------------------------------
--- Deprecations (c.f. rules)
+-- Warnings and deprecations (c.f. rules)
+
+warnings :: { OrdList (LHsDecl RdrName) }
+ : warnings ';' warning { $1 `appOL` $3 }
+ | warnings ';' { $1 }
+ | warning { $1 }
+ | {- empty -} { nilOL }
+
+-- SUP: TEMPORARY HACK, not checking for `module Foo'
+warning :: { OrdList (LHsDecl RdrName) }
+ : namelist STRING
+ { toOL [ LL $ WarningD (Warning n (WarningTxt (getSTRING $2)))
+ | n <- unLoc $1 ] }
deprecations :: { OrdList (LHsDecl RdrName) }
: deprecations ';' deprecation { $1 `appOL` $3 }
-- SUP: TEMPORARY HACK, not checking for `module Foo'
deprecation :: { OrdList (LHsDecl RdrName) }
- : depreclist STRING
- { toOL [ LL $ DeprecD (Deprecation n (getSTRING $2))
+ : namelist STRING
+ { toOL [ LL $ WarningD (Warning n (DeprecatedTxt (getSTRING $2)))
| n <- unLoc $1 ] }
| 'threadsafe' { PlaySafe True }
fspec :: { Located (Located FastString, Located RdrName, LHsType RdrName) }
- : STRING var '::' sigtype { LL (L (getLoc $1) (getSTRING $1), $2, $4) }
- | var '::' sigtype { LL (noLoc nilFS, $1, $3) }
+ : STRING var '::' sigtypedoc { LL (L (getLoc $1) (getSTRING $1), $2, $4) }
+ | var '::' sigtypedoc { LL (noLoc nilFS, $1, $3) }
-- if the entity string is missing, it defaults to the empty string;
-- the meaning of an empty entity string depends on the calling
-- convention
: ctype { L1 (mkImplicitHsForAllTy (noLoc []) $1) }
-- Wrap an Implicit forall if there isn't one there already
+sigtypedoc :: { LHsType RdrName }
+ : ctypedoc { L1 (mkImplicitHsForAllTy (noLoc []) $1) }
+ -- Wrap an Implicit forall if there isn't one there already
+
sig_vars :: { Located [Located RdrName] }
: sig_vars ',' var { LL ($3 : unLoc $1) }
| var { L1 [$1] }
-----------------------------------------------------------------------------
-- Types
+infixtype :: { LHsType RdrName }
+ : btype qtyconop gentype { LL $ HsOpTy $1 $2 $3 }
+ | btype tyvarop gentype { LL $ HsOpTy $1 $2 $3 }
+
+infixtypedoc :: { LHsType RdrName }
+ : infixtype { $1 }
+ | infixtype docprev { LL $ HsDocTy $1 $2 }
+
+gentypedoc :: { LHsType RdrName }
+ : btype { $1 }
+ | btypedoc { $1 }
+ | infixtypedoc { $1 }
+ | btype '->' ctypedoc { LL $ HsFunTy $1 $3 }
+ | btypedoc '->' ctypedoc { LL $ HsFunTy $1 $3 }
+
+ctypedoc :: { LHsType RdrName }
+ : 'forall' tv_bndrs '.' ctypedoc { LL $ mkExplicitHsForAllTy $2 (noLoc []) $4 }
+ | context '=>' ctypedoc { LL $ mkImplicitHsForAllTy $1 $3 }
+ -- A type of form (context => type) is an *implicit* HsForAllTy
+ | gentypedoc { $1 }
+
strict_mark :: { Located HsBang }
: '!' { L1 HsStrict }
| '{-# UNPACK' '#-}' '!' { LL HsUnbox }
-- errors in ctype. The basic problem is that
-- (Eq a, Ord a)
-- looks so much like a tuple type. We can't tell until we find the =>
+--
+-- We have the t1 ~ t2 form here and in gentype, to permit an individual
+-- equational constraint without parenthesis.
context :: { LHsContext RdrName }
- : btype {% checkContext $1 }
+ : btype '~' btype {% checkContext
+ (LL $ HsPredTy (HsEqualP $1 $3)) }
+ | btype {% checkContext $1 }
type :: { LHsType RdrName }
: ipvar '::' gentype { LL (HsPredTy (HsIParam (unLoc $1) $3)) }
: btype { $1 }
| btype qtyconop gentype { LL $ HsOpTy $1 $2 $3 }
| btype tyvarop gentype { LL $ HsOpTy $1 $2 $3 }
- | btype '->' ctype { LL $ HsFunTy $1 $3 }
+ | btype '->' ctype { LL $ HsFunTy $1 $3 }
+ | btype '~' btype { LL $ HsPredTy (HsEqualP $1 $3) }
btype :: { LHsType RdrName }
: btype atype { LL $ HsAppTy $1 $2 }
| atype { $1 }
+btypedoc :: { LHsType RdrName }
+ : btype atype docprev { LL $ HsDocTy (L (comb2 $1 $2) (HsAppTy $1 $2)) $3 }
+ | atype docprev { LL $ HsDocTy $1 $2 }
+
atype :: { LHsType RdrName }
: gtycon { L1 (HsTyVar (unLoc $1)) }
| tyvar { L1 (HsTyVar (unLoc $1)) }
-- XXX revisit audreyt
| constr_stuff_record '::' sigtype
{ let (con,details) = unLoc $1 in
- LL (ConDecl con Implicit [] (noLoc []) details (ResTyGADT $3)) }
+ LL (ConDecl con Implicit [] (noLoc []) details (ResTyGADT $3) Nothing) }
{-
| forall context '=>' constr_stuff_record '::' sigtype
{ let (con,details) = unLoc $4 in
- LL (ConDecl con Implicit (unLoc $1) $2 details (ResTyGADT $6)) }
+ LL (ConDecl con Implicit (unLoc $1) $2 details (ResTyGADT $6) Nothing ) }
| forall constr_stuff_record '::' sigtype
{ let (con,details) = unLoc $2 in
- LL (ConDecl con Implicit (unLoc $1) (noLoc []) details (ResTyGADT $4)) }
+ LL (ConDecl con Implicit (unLoc $1) (noLoc []) details (ResTyGADT $4) Nothing) }
-}
constrs :: { Located [LConDecl RdrName] }
: {- empty; a GHC extension -} { noLoc [] }
- | '=' constrs1 { LL (unLoc $2) }
+ | maybe_docnext '=' constrs1 { L (comb2 $2 $3) (addConDocs (unLoc $3) $1) }
constrs1 :: { Located [LConDecl RdrName] }
- : constrs1 '|' constr { LL ($3 : unLoc $1) }
- | constr { L1 [$1] }
+ : constrs1 maybe_docnext '|' maybe_docprev constr { LL (addConDoc $5 $2 : addConDocFirst (unLoc $1) $4) }
+ | constr { L1 [$1] }
constr :: { LConDecl RdrName }
- : forall context '=>' constr_stuff
- { let (con,details) = unLoc $4 in
- LL (ConDecl con Explicit (unLoc $1) $2 details ResTyH98) }
- | forall constr_stuff
- { let (con,details) = unLoc $2 in
- LL (ConDecl con Explicit (unLoc $1) (noLoc []) details ResTyH98) }
+ : maybe_docnext forall context '=>' constr_stuff maybe_docprev
+ { let (con,details) = unLoc $5 in
+ L (comb4 $2 $3 $4 $5) (ConDecl con Explicit (unLoc $2) $3 details ResTyH98 ($1 `mplus` $6)) }
+ | maybe_docnext forall constr_stuff maybe_docprev
+ { let (con,details) = unLoc $3 in
+ L (comb2 $2 $3) (ConDecl con Explicit (unLoc $2) (noLoc []) details ResTyH98 ($1 `mplus` $4)) }
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
| 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 $>) }
-fielddecls :: { [([Located RdrName], LBangType RdrName)] }
- : fielddecl ',' fielddecls { unLoc $1 : $3 }
- | fielddecl { [unLoc $1] }
+fielddecls :: { [([Located RdrName], LBangType RdrName, Maybe (LHsDoc RdrName))] }
+ : fielddecl maybe_docnext ',' maybe_docprev fielddecls { addFieldDoc (unLoc $1) $4 : addFieldDocs $5 $2 }
+ | fielddecl { [unLoc $1] }
-fielddecl :: { Located ([Located RdrName], LBangType RdrName) }
- : sig_vars '::' ctype { LL (reverse (unLoc $1), $3) }
+fielddecl :: { Located ([Located RdrName], LBangType RdrName, Maybe (LHsDoc RdrName)) }
+ : maybe_docnext sig_vars '::' ctype maybe_docprev { L (comb3 $2 $3 $4) (reverse (unLoc $2), $4, $1 `mplus` $5) }
-- We allow the odd-looking 'inst_type' in a deriving clause, so that
-- we can do deriving( forall a. C [a] ) in a newtype (GHC extension).
We can't tell whether to reduce var to qvar until after we've read the signatures.
-}
+docdecl :: { LHsDecl RdrName }
+ : docdecld { L1 (DocD (unLoc $1)) }
+
+docdecld :: { LDocDecl RdrName }
+ : docnext { L1 (DocCommentNext (unLoc $1)) }
+ | docprev { L1 (DocCommentPrev (unLoc $1)) }
+ | docnamed { L1 (case (unLoc $1) of (n, doc) -> DocCommentNamed n doc) }
+ | docsection { L1 (case (unLoc $1) of (n, doc) -> DocGroup n doc) }
+
decl :: { Located (OrdList (LHsDecl RdrName)) }
: sigdecl { $1 }
- | '!' infixexp rhs {% do { pat <- checkPattern $2;
- return (LL $ unitOL $ LL $ ValD $
+ | '!' aexp rhs {% do { pat <- checkPattern $2;
+ return (LL $ unitOL $ LL $ ValD (
PatBind (LL $ BangPat pat) (unLoc $3)
- placeHolderType placeHolderNames) } }
- | infixexp opt_sig rhs {% do { r <- checkValDef $1 $2 $3;
- return (LL $ unitOL (LL $ ValD r)) } }
+ placeHolderType placeHolderNames)) } }
+ | infixexp opt_sig rhs {% do { r <- checkValDef $1 $2 $3;
+ let { l = comb2 $1 $> };
+ return $! (sL l (unitOL $! (sL l $ ValD r))) } }
+ | docdecl { LL $ unitOL $1 }
rhs :: { Located (GRHSs RdrName) }
- : '=' exp wherebinds { L (comb3 $1 $2 $3) $ GRHSs (unguardedRHS $2) (unLoc $3) }
+ : '=' exp wherebinds { sL (comb3 $1 $2 $3) $ GRHSs (unguardedRHS $2) (unLoc $3) }
| gdrhs wherebinds { LL $ GRHSs (reverse (unLoc $1)) (unLoc $2) }
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 '::' sigtype
+ : infixexp '::' sigtypedoc
{% do s <- checkValSig $1 $3;
return (LL $ unitOL (LL $ SigD s)) }
-- See the above notes for why we need infixexp here
- | var ',' sig_vars '::' sigtype
+ | var ',' sig_vars '::' sigtypedoc
{ LL $ toOL [ LL $ SigD (TypeSig n $5) | n <- $1 : unLoc $3 ] }
| infix prec ops { LL $ toOL [ LL $ SigD (FixSig (FixitySig n (Fixity $2 (unLoc $1))))
| n <- unLoc $3 ] }
| '{-# INLINE' activation qvar '#-}'
{ LL $ unitOL (LL $ SigD (InlineSig $3 (mkInlineSpec $2 (getINLINE $1)))) }
| '{-# SPECIALISE' qvar '::' sigtypes1 '#-}'
- { LL $ toOL [ LL $ SigD (SpecSig $2 t defaultInlineSpec)
+ { LL $ toOL [ LL $ SigD (SpecSig $2 t defaultInlineSpec)
| t <- $4] }
| '{-# SPECIALISE_INLINE' activation qvar '::' sigtypes1 '#-}'
{ LL $ toOL [ LL $ SigD (SpecSig $3 t (mkInlineSpec $2 (getSPEC_INLINE $1)))
| infixexp qop exp10 { LL (OpApp $1 $2 (panic "fixity") $3) }
exp10 :: { LHsExpr RdrName }
- : '\\' aexp aexps opt_asig '->' exp
- {% checkPatterns ($2 : reverse $3) >>= \ ps ->
- return (LL $ HsLam (mkMatchGroup [LL $ Match ps $4
- (GRHSs (unguardedRHS $6) emptyLocalBinds
- )])) }
+ : '\\' apat apats opt_asig '->' exp
+ { LL $ HsLam (mkMatchGroup [LL $ Match ($2:$3) $4
+ (unguardedGRHSs $6)
+ ]) }
| '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) ->
| scc_annot exp { LL $ if opt_SccProfilingOn
then HsSCC (unLoc $1) $2
else HsPar $2 }
+ | hpc_annot exp { LL $ if opt_Hpc
+ then HsTickPragma (unLoc $1) $2
+ else HsPar $2 }
| 'proc' aexp '->' exp
{% checkPattern $2 >>= \ p ->
| fexp { $1 }
scc_annot :: { Located FastString }
- : '_scc_' STRING { LL $ getSTRING $2 }
- | '{-# SCC' STRING '#-}' { LL $ getSTRING $2 }
+ : '_scc_' STRING {% (addWarning Opt_WarnWarningsDeprecations (getLoc $1) (text "_scc_ is deprecated; use an SCC pragma instead")) >>= \_ ->
+ ( do scc <- getSCC $2; return $ LL scc ) }
+ | '{-# SCC' STRING '#-}' {% do scc <- getSCC $2; return $ LL scc }
+
+hpc_annot :: { Located (FastString,(Int,Int),(Int,Int)) }
+ : '{-# GENERATED' STRING INTEGER ':' INTEGER '-' INTEGER ':' INTEGER '#-}'
+ { LL $ (getSTRING $2
+ ,( fromInteger $ getINTEGER $3
+ , fromInteger $ getINTEGER $5
+ )
+ ,( fromInteger $ getINTEGER $7
+ , fromInteger $ getINTEGER $9
+ )
+ )
+ }
fexp :: { LHsExpr RdrName }
: fexp aexp { LL $ HsApp $1 $2 }
| aexp { $1 }
-aexps :: { [LHsExpr RdrName] }
- : aexps aexp { $2 : $1 }
- | {- empty -} { [] }
-
aexp :: { LHsExpr RdrName }
: qvar '@' aexp { LL $ EAsPat $1 $3 }
| '~' aexp { LL $ ELazyPat $2 }
--- | '!' aexp { LL $ EBangPat $2 }
- | aexp1 { $1 }
+ | aexp1 { $1 }
aexp1 :: { LHsExpr RdrName }
- : aexp1 '{' fbinds '}' {% do { r <- mkRecConstrOrUpdate $1 (comb2 $2 $4)
- (reverse $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
: ipvar { L1 (HsIPVar $! unLoc $1) }
| qcname { L1 (HsVar $! unLoc $1) }
| literal { L1 (HsLit $! unLoc $1) }
- | INTEGER { L1 (HsOverLit $! mkHsIntegral (getINTEGER $1)) }
- | RATIONAL { L1 (HsOverLit $! mkHsFractional (getRATIONAL $1)) }
- | '(' exp ')' { LL (HsPar $2) }
+-- This will enable overloaded strings permanently. Normally the renamer turns HsString
+-- into HsOverLit when -foverloaded-strings is on.
+-- | 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
(getTH_ID_SPLICE $1)))) } -- $x
| '$(' exp ')' { LL $ HsSpliceE (mkHsSplice $2) } -- $( exp )
+ | TH_QUASIQUOTE { let { loc = getLoc $1
+ ; ITquasiQuote (quoter, quote, quoteSpan) = unLoc $1
+ ; quoterId = mkUnqual varName quoter
+ }
+ in sL loc $ HsQuasiQuoteE (mkHsQuasiQuote quoterId quoteSpan quote) }
| TH_VAR_QUOTE qvar { LL $ HsBracket (VarBr (unLoc $2)) }
| TH_VAR_QUOTE qcon { LL $ HsBracket (VarBr (unLoc $2)) }
| TH_TY_QUOTE tyvar { LL $ HsBracket (VarBr (unLoc $2)) }
| '[|' exp '|]' { LL $ HsBracket (ExpBr $2) }
| '[t|' ctype '|]' { LL $ HsBracket (TypBr $2) }
| '[p|' infixexp '|]' {% checkPattern $2 >>= \p ->
- return (LL $ HsBracket (PatBr p)) }
- | '[d|' cvtopbody '|]' { LL $ HsBracket (DecBr (mkGroup $2)) }
+ return (LL $ HsBracket (PatBr p)) }
+ | '[d|' cvtopbody '|]' {% checkDecBrGroup $2 >>= \g ->
+ return (LL $ HsBracket (DecBr g)) }
-- arrow notation extension
| '(|' aexp2 cmdargs '|)' { LL $ HsArrForm $2 Nothing (reverse $3) }
: {- 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 }
| 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) }
+ : lexps ',' texp { LL (((:) $! $3) $! unLoc $1) }
| texp ',' texp { LL [$3,$1] }
-----------------------------------------------------------------------------
-- 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) }
-quals :: { Located [LStmt RdrName] }
- : quals ',' qual { LL ($3 : unLoc $1) }
- | qual { L1 [$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] }
+
+
+-- 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
parr :: { LHsExpr RdrName }
: { noLoc (ExplicitPArr placeHolderType []) }
- | exp { L1 $ ExplicitPArr placeHolderType [$1] }
+ | texp { L1 $ ExplicitPArr placeHolderType [$1] }
| lexps { L1 $ ExplicitPArr placeHolderType
(reverse (unLoc $1)) }
- | exp '..' exp { LL $ PArrSeq noPostTcExpr (FromTo $1 $3) }
- | exp ',' exp '..' exp { LL $ PArrSeq noPostTcExpr (FromThenTo $1 $3 $5) }
- | exp pquals { sL (comb2 $1 $>) $ mkHsDo PArrComp (reverse (unLoc $2)) $1 }
+ | texp '..' exp { LL $ PArrSeq noPostTcExpr (FromTo $1 $3) }
+ | texp ',' exp '..' exp { LL $ PArrSeq noPostTcExpr (FromThenTo $1 $3 $5) }
+ | texp '|' flattenedpquals { LL $ mkHsDo PArrComp (unLoc $3) $1 }
+
+-- We are reusing `lexps' and `flattenedpquals' from the list case.
--- We are reusing `lexps' and `pquals' 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
| alt { L1 [$1] }
alt :: { LMatch RdrName }
- : infixexp opt_sig alt_rhs {% checkPattern $1 >>= \p ->
- return (LL (Match [p] $2 (unLoc $3))) }
- | '!' infixexp opt_sig alt_rhs {% checkPattern $2 >>= \p ->
- return (LL (Match [LL $ BangPat p] $3 (unLoc $4))) }
+ : pat opt_sig alt_rhs { LL (Match [$1] $2 (unLoc $3)) }
alt_rhs :: { Located (GRHSs RdrName) }
: ralt wherebinds { LL (GRHSs (unLoc $1) (unLoc $2)) }
| 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 : exp {% checkPattern $1 }
+ | '!' aexp {% checkPattern (LL (SectionR (L1 (HsVar bang_RDR)) $2)) }
+
+apat :: { LPat RdrName }
+apat : aexp {% checkPattern $1 }
+ | '!' aexp {% checkPattern (LL (SectionR (L1 (HsVar bang_RDR)) $2)) }
+
+apats :: { [LPat RdrName] }
+ : apat apats { $1 : $2 }
+ | {- empty -} { [] }
-----------------------------------------------------------------------------
-- Statement sequences
| {- nothing -} { Nothing }
stmt :: { LStmt RdrName }
- : qual { $1 }
- | infixexp '->' exp {% checkPattern $3 >>= \p ->
- return (LL $ mkBindStmt p $1) }
+ : qual { $1 }
| 'rec' stmtlist { LL $ mkRecStmt (unLoc $2) }
qual :: { LStmt RdrName }
- : exp '<-' exp {% checkPattern $1 >>= \p ->
- return (LL $ mkBindStmt p $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 }
+fbinds :: { ([HsRecField RdrName (LHsExpr RdrName)], Bool) }
: fbinds1 { $1 }
- | {- empty -} { [] }
+ | {- empty -} { ([], False) }
-fbinds1 :: { HsRecordBinds RdrName }
- : 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
dbinds :: { Located [LIPBind RdrName] }
- : dbinds ';' dbind { LL ($3 : unLoc $1) }
+ : dbinds ';' dbind { let { this = $3; rest = unLoc $1 }
+ in rest `seq` this `seq` LL (this : rest) }
| dbinds ';' { LL (unLoc $1) }
- | dbind { L1 [$1] }
+ | dbind { let this = $1 in this `seq` L1 [this] }
-- | {- empty -} { [] }
dbind :: { LIPBind RdrName }
dbind : ipvar '=' exp { LL (IPBind (unLoc $1) $3) }
ipvar :: { Located (IPName RdrName) }
- : IPDUPVARID { L1 (Dupable (mkUnqual varName (getIPDUPVARID $1))) }
- | IPSPLITVARID { L1 (Linear (mkUnqual varName (getIPSPLITVARID $1))) }
+ : IPDUPVARID { L1 (IPName (mkUnqual varName (getIPDUPVARID $1))) }
-----------------------------------------------------------------------------
--- Deprecations
+-- Warnings and deprecations
-depreclist :: { Located [RdrName] }
-depreclist : deprec_var { L1 [unLoc $1] }
- | deprec_var ',' depreclist { LL (unLoc $1 : unLoc $3) }
+namelist :: { Located [RdrName] }
+namelist : name_var { L1 [unLoc $1] }
+ | name_var ',' namelist { LL (unLoc $1 : unLoc $3) }
-deprec_var :: { Located RdrName }
-deprec_var : var { $1 }
- | con { $1 }
+name_var :: { Located RdrName }
+name_var : var { $1 }
+ | con { $1 }
-----------------------------------------
-- Data constructors
sysdcon :: { Located DataCon } -- Wired in data constructors
: '(' ')' { LL unitDataCon }
| '(' commas ')' { LL $ tupleCon Boxed $2 }
+ | '(#' '#)' { LL $ unboxedSingletonDataCon }
+ | '(#' commas '#)' { LL $ tupleCon Unboxed $2 }
| '[' ']' { LL nilDataCon }
conop :: { Located RdrName }
: oqtycon { $1 }
| '(' ')' { LL $ getRdrName unitTyCon }
| '(' commas ')' { LL $ getRdrName (tupleTyCon Boxed $2) }
+ | '(#' '#)' { LL $ getRdrName unboxedSingletonTyCon }
+ | '(#' commas '#)' { LL $ getRdrName (tupleTyCon Unboxed $2) }
| '(' '->' ')' { LL $ getRdrName funTyCon }
| '[' ']' { LL $ listTyCon_RDR }
| '[:' ':]' { LL $ parrTyCon_RDR }
tyvarid :: { Located RdrName }
: VARID { L1 $! mkUnqual tvName (getVARID $1) }
| special_id { L1 $! mkUnqual tvName (unLoc $1) }
- | 'unsafe' { L1 $! mkUnqual tvName FSLIT("unsafe") }
- | 'safe' { L1 $! mkUnqual tvName FSLIT("safe") }
- | 'threadsafe' { L1 $! mkUnqual tvName FSLIT("threadsafe") }
+ | 'unsafe' { L1 $! mkUnqual tvName (fsLit "unsafe") }
+ | 'safe' { L1 $! mkUnqual tvName (fsLit "safe") }
+ | 'threadsafe' { L1 $! mkUnqual tvName (fsLit "threadsafe") }
tyvarsym :: { Located RdrName }
-- Does not include "!", because that is used for strictness marks
varid :: { Located RdrName }
: varid_no_unsafe { $1 }
- | 'unsafe' { L1 $! mkUnqual varName FSLIT("unsafe") }
- | 'safe' { L1 $! mkUnqual varName FSLIT("safe") }
- | 'threadsafe' { L1 $! mkUnqual varName FSLIT("threadsafe") }
+ | 'unsafe' { L1 $! mkUnqual varName (fsLit "unsafe") }
+ | 'safe' { L1 $! mkUnqual varName (fsLit "safe") }
+ | 'threadsafe' { L1 $! mkUnqual varName (fsLit "threadsafe") }
varid_no_unsafe :: { Located RdrName }
: VARID { L1 $! mkUnqual varName (getVARID $1) }
| special_id { L1 $! mkUnqual varName (unLoc $1) }
- | 'forall' { L1 $! mkUnqual varName FSLIT("forall") }
+ | 'forall' { L1 $! mkUnqual varName (fsLit "forall") }
+ | 'family' { L1 $! mkUnqual varName (fsLit "family") }
qvarsym :: { Located RdrName }
: varsym { $1 }
varsym :: { Located RdrName }
: varsym_no_minus { $1 }
- | '-' { L1 $ mkUnqual varName FSLIT("-") }
+ | '-' { L1 $ mkUnqual varName (fsLit "-") }
varsym_no_minus :: { Located RdrName } -- varsym not including '-'
: VARSYM { L1 $ mkUnqual varName (getVARSYM $1) }
-- These special_ids are treated as keywords in various places,
-- but as ordinary ids elsewhere. 'special_id' collects all these
--- except 'unsafe' and 'forall' whose treatment differs depending on context
+-- except 'unsafe', 'forall', and 'family' whose treatment differs
+-- depending on context
special_id :: { Located FastString }
special_id
- : 'as' { L1 FSLIT("as") }
- | 'qualified' { L1 FSLIT("qualified") }
- | 'hiding' { L1 FSLIT("hiding") }
- | 'export' { L1 FSLIT("export") }
- | 'label' { L1 FSLIT("label") }
- | 'dynamic' { L1 FSLIT("dynamic") }
- | 'stdcall' { L1 FSLIT("stdcall") }
- | 'ccall' { L1 FSLIT("ccall") }
- | 'iso' { L1 FSLIT("iso") }
+ : 'as' { L1 (fsLit "as") }
+ | 'qualified' { L1 (fsLit "qualified") }
+ | 'hiding' { L1 (fsLit "hiding") }
+ | 'export' { L1 (fsLit "export") }
+ | 'label' { L1 (fsLit "label") }
+ | 'dynamic' { L1 (fsLit "dynamic") }
+ | 'stdcall' { L1 (fsLit "stdcall") }
+ | 'ccall' { L1 (fsLit "ccall") }
special_sym :: { Located FastString }
-special_sym : '!' { L1 FSLIT("!") }
- | '.' { L1 FSLIT(".") }
- | '*' { L1 FSLIT("*") }
+special_sym : '!' { L1 (fsLit "!") }
+ | '.' { L1 (fsLit ".") }
+ | '*' { L1 (fsLit "*") }
-----------------------------------------------------------------------------
-- Data constructors
literal :: { Located HsLit }
: CHAR { L1 $ HsChar $ getCHAR $1 }
- | STRING { L1 $ HsString $ getSTRING $1 }
+ | STRING { L1 $ HsString $ getSTRING $1 }
| PRIMINTEGER { L1 $ HsIntPrim $ getPRIMINTEGER $1 }
+ | PRIMWORD { L1 $ HsWordPrim $ getPRIMWORD $1 }
| PRIMCHAR { L1 $ HsCharPrim $ getPRIMCHAR $1 }
| PRIMSTRING { L1 $ HsStringPrim $ getPRIMSTRING $1 }
| PRIMFLOAT { L1 $ HsFloatPrim $ getPRIMFLOAT $1 }
| ',' { 2 }
-----------------------------------------------------------------------------
+-- Documentation comments
+
+docnext :: { LHsDoc RdrName }
+ : DOCNEXT {% case parseHaddockParagraphs (tokenise (getDOCNEXT $1)) of {
+ MyLeft err -> parseError (getLoc $1) err;
+ MyRight doc -> return (L1 doc) } }
+
+docprev :: { LHsDoc RdrName }
+ : DOCPREV {% case parseHaddockParagraphs (tokenise (getDOCPREV $1)) of {
+ 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 {
+ MyLeft err -> parseError (getLoc $1) err;
+ MyRight doc -> return (L1 (name, doc)) } }
+
+docsection :: { Located (Int, HsDoc RdrName) }
+ : DOCSECTION {% let (n, doc) = getDOCSECTION $1 in
+ case parseHaddockString (tokenise doc) of {
+ 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 {
+ MyLeft err -> parseError (getLoc $1) err;
+ MyRight doc -> return (info, Just doc);
+ };
+ Left err -> parseError (getLoc $1) err
+ } }
+
+maybe_docprev :: { Maybe (LHsDoc RdrName) }
+ : docprev { Just $1 }
+ | {- empty -} { Nothing }
+
+maybe_docnext :: { Maybe (LHsDoc RdrName) }
+ : docnext { Just $1 }
+ | {- empty -} { Nothing }
{
happyError :: P a
getQVARSYM (L _ (ITqvarsym x)) = x
getQCONSYM (L _ (ITqconsym x)) = x
getIPDUPVARID (L _ (ITdupipvarid x)) = x
-getIPSPLITVARID (L _ (ITsplitipvarid x)) = x
getCHAR (L _ (ITchar x)) = x
getSTRING (L _ (ITstring x)) = x
getINTEGER (L _ (ITinteger x)) = x
getPRIMCHAR (L _ (ITprimchar x)) = x
getPRIMSTRING (L _ (ITprimstring x)) = x
getPRIMINTEGER (L _ (ITprimint x)) = x
+getPRIMWORD (L _ (ITprimword x)) = x
getPRIMFLOAT (L _ (ITprimfloat x)) = x
getPRIMDOUBLE (L _ (ITprimdouble x)) = x
getTH_ID_SPLICE (L _ (ITidEscape x)) = x
getINLINE (L _ (ITinline_prag b)) = b
getSPEC_INLINE (L _ (ITspec_inline_prag b)) = b
+getDOCNEXT (L _ (ITdocCommentNext x)) = x
+getDOCPREV (L _ (ITdocCommentPrev x)) = x
+getDOCNAMED (L _ (ITdocCommentNamed x)) = x
+getDOCSECTION (L _ (ITdocSection n x)) = (n, x)
+
+getSCC :: Located Token -> P FastString
+getSCC lt = do let s = getSTRING lt
+ err = "Spaces are not allowed in SCCs"
+ -- We probably actually want to be more restrictive than this
+ if ' ' `elem` unpackFS s
+ then failSpanMsgP (getLoc lt) (text err)
+ else return s
+
-- Utilities for combining source spans
comb2 :: Located a -> Located b -> SrcSpan
-comb2 = combineLocs
+comb2 a b = a `seq` b `seq` combineLocs a b
comb3 :: Located a -> Located b -> Located c -> SrcSpan
-comb3 a b c = combineSrcSpans (getLoc a) (combineSrcSpans (getLoc b) (getLoc c))
+comb3 a b c = a `seq` b `seq` c `seq`
+ combineSrcSpans (getLoc a) (combineSrcSpans (getLoc b) (getLoc c))
comb4 :: Located a -> Located b -> Located c -> Located d -> SrcSpan
-comb4 a b c d = combineSrcSpans (getLoc a) $ combineSrcSpans (getLoc b) $
- combineSrcSpans (getLoc c) (getLoc d)
+comb4 a b c d = a `seq` b `seq` c `seq` d `seq`
+ (combineSrcSpans (getLoc a) $ combineSrcSpans (getLoc b) $
+ combineSrcSpans (getLoc c) (getLoc d))
-- strict constructor version:
{-# INLINE sL #-}
sL :: SrcSpan -> a -> Located a
-sL span a = span `seq` L span a
+sL span a = span `seq` a `seq` L span a
-- Make a source location for the file. We're a bit lazy here and just
-- make a point SrcSpan at line 1, column 0. Strictly speaking we should