-{-
+{- -*-haskell-*-
-----------------------------------------------------------------------------
-$Id: Parser.y,v 1.48 2000/11/16 11:39:37 simonmar Exp $
+$Id: Parser.y,v 1.91 2002/03/03 03:59:03 sof Exp $
Haskell grammar.
-}
{
-module Parser ( ParseStuff(..), parse ) where
+module Parser ( parseModule, parseStmt, parseIdentifier ) where
import HsSyn
import HsTypes ( mkHsTupCon )
-import HsPat ( InPat(..) )
import RdrHsSyn
import Lex
import ParseUtil
import RdrName
-import PrelNames
-import OccName ( UserFS, varName, ipName, tcName, dataName, tcClsName, tvName )
+import PrelNames ( mAIN_Name, unitTyCon_RDR, funTyCon_RDR,
+ listTyCon_RDR, parrTyCon_RDR, tupleTyCon_RDR,
+ unitCon_RDR, nilCon_RDR, tupleCon_RDR )
+import ForeignCall ( Safety(..), CExportSpec(..),
+ CCallConv(..), CCallTarget(..), defaultCCallConv,
+ )
+import OccName ( UserFS, varName, tcName, dataName, tcClsName, tvName )
+import TyCon ( DataConDetails(..) )
import SrcLoc ( SrcLoc )
import Module
-import CallConv
import CmdLineOpts ( opt_SccProfilingOn )
-import BasicTypes ( Boxity(..), Fixity(..), FixityDirection(..), NewOrData(..) )
+import Type ( Kind, mkArrowKind, liftedTypeKind )
+import BasicTypes ( Boxity(..), Fixity(..), FixityDirection(..), IPName(..),
+ NewOrData(..), StrictnessMark(..), Activation(..) )
import Panic
import GlaExts
-import FastString ( tailFS )
+import CStrings ( CLabelString )
+import FastString
+import Maybes ( orElse )
import Outputable
#include "HsVersions.h"
{-
-----------------------------------------------------------------------------
-Conflicts: 14 shift/reduce
- (note: it's currently 21 -- JRL, 31/1/2000)
+Conflicts: 21 shift/reduce, -=chak[4Feb2]
-8 for abiguity in 'if x then y else z + 1'
+9 for abiguity in 'if x then y else z + 1'
(shift parses as 'if x then y else (z + 1)', as per longest-parse rule)
+ 8 because op might be: - ! * . `x` VARSYM CONSYM QVARSYM QCONSYM
1 for ambiguity in 'if x then y else z :: T'
(shift parses as 'if x then y else (z :: T)', as per longest-parse rule)
+1 for ambiguity in 'if x then y else z with ?x=3'
+ (shift parses as 'if x then y else (z with ?x=3)'
+
3 for ambiguity in 'case x of y :: a -> b'
(don't know whether to reduce 'a' as a btype or shift the '->'.
conclusion: bogus expression anyway, doesn't matter)
Only sensible parse is 'x @ (Rec{..})', which is what resolving
to shift gives us.
+6 for conflicts between `fdecl' and `fdeclDEPRECATED', which are resolved
+ correctly, and moreover, should go away when `fdeclDEPRECATED' is removed.
+
-----------------------------------------------------------------------------
-}
'then' { ITthen }
'type' { ITtype }
'where' { ITwhere }
- '_scc_' { ITscc }
+ '_scc_' { ITscc } -- ToDo: remove
'forall' { ITforall } -- GHC extension keywords
'foreign' { ITforeign }
'export' { ITexport }
'label' { ITlabel }
'dynamic' { ITdynamic }
+ 'safe' { ITsafe }
+ 'threadsafe' { ITthreadsafe }
'unsafe' { ITunsafe }
'with' { ITwith }
'stdcall' { ITstdcallconv }
'ccall' { ITccallconv }
- '_ccall_' { ITccall (False, False, False) }
- '_ccall_GC_' { ITccall (False, False, True) }
- '_casm_' { ITccall (False, True, False) }
- '_casm_GC_' { ITccall (False, True, True) }
+ 'dotnet' { ITdotnet }
+ '_ccall_' { ITccall (False, False, PlayRisky) }
+ '_ccall_GC_' { ITccall (False, False, PlaySafe False) }
+ '_casm_' { ITccall (False, True, PlayRisky) }
+ '_casm_GC_' { ITccall (False, True, PlaySafe False) }
'{-# SPECIALISE' { ITspecialise_prag }
'{-# SOURCE' { ITsource_prag }
'{-# INLINE' { ITinline_prag }
'{-# NOINLINE' { ITnoinline_prag }
'{-# RULES' { ITrules_prag }
+ '{-# SCC' { ITscc_prag }
'{-# DEPRECATED' { ITdeprecated_prag }
'#-}' { ITclose_prag }
- '__expr' { ITexpr }
-
{-
'__interface' { ITinterface } -- interface keywords
'__export' { IT__export }
'__A' { ITarity }
'__P' { ITspecialise }
'__C' { ITnocaf }
- '__U' { ITunfold $$ }
+ '__U' { ITunfold }
'__S' { ITstrict $$ }
'__M' { ITcprinfo $$ }
-}
'=>' { ITdarrow }
'-' { ITminus }
'!' { ITbang }
+ '*' { ITstar }
'.' { ITdot }
'{' { ITocurly } -- special symbols
vccurly { ITvccurly } -- virtual close curly (from layout)
'[' { ITobrack }
']' { ITcbrack }
+ '[:' { ITopabrack }
+ ':]' { ITcpabrack }
'(' { IToparen }
')' { ITcparen }
'(#' { IToubxparen }
QVARSYM { ITqvarsym $$ }
QCONSYM { ITqconsym $$ }
- IPVARID { ITipvarid $$ } -- GHC extension
+ IPDUPVARID { ITdupipvarid $$ } -- GHC extension
+ IPSPLITVARID { ITsplitipvarid $$ } -- GHC extension
CHAR { ITchar $$ }
STRING { ITstring $$ }
%monad { P } { thenP } { returnP }
%lexer { lexer } { ITeof }
-%name parse
+%name parseModule module
+%name parseStmt maybe_stmt
+%name parseIdentifier identifier
%tokentype { Token }
%%
-----------------------------------------------------------------------------
--- Entry points
-
-parse :: { ParseStuff }
- : module { PModule $1 }
- | '__expr' exp { PExpr $2 }
-
------------------------------------------------------------------------------
-- Module Header
-- The place for module deprecation is really too restrictive, but if it
| {- empty -} { [] }
importdecl :: { RdrNameImportDecl }
- : 'import' srcloc maybe_src optqualified CONID maybeas maybeimpspec
- { ImportDecl (mkModuleNameFS $5) $3 $4 $6 $7 $2 }
+ : 'import' srcloc maybe_src optqualified modid maybeas maybeimpspec
+ { ImportDecl $5 $3 $4 $6 $7 $2 }
maybe_src :: { WhereFrom }
: '{-# SOURCE' '#-}' { ImportByUserSource }
| topdecl { [$1] }
topdecl :: { RdrBinding }
- : srcloc 'type' simpletype '=' sigtype
- { RdrHsDecl (TyClD (TySynonym (fst $3) (snd $3) $5 $1)) }
-
- | srcloc 'data' ctype '=' constrs deriving
- {% checkDataHeader $3 `thenP` \(cs,c,ts) ->
- returnP (RdrHsDecl (TyClD
- (mkTyData DataType cs c ts (reverse $5) (length $5) $6 $1))) }
-
- | srcloc 'newtype' ctype '=' newconstr deriving
- {% checkDataHeader $3 `thenP` \(cs,c,ts) ->
- returnP (RdrHsDecl (TyClD
- (mkTyData NewType cs c ts [$5] 1 $6 $1))) }
-
- | srcloc 'class' ctype fds where
- {% checkDataHeader $3 `thenP` \(cs,c,ts) ->
- let
+ : srcloc 'type' tycon tv_bndrs '=' ctype
+ -- Note ctype, not sigtype.
+ -- 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
+ { RdrHsDecl (TyClD (TySynonym $3 $4 $6 $1)) }
+
+
+ | srcloc 'data' tycl_hdr constrs deriving
+ {% returnP (RdrHsDecl (TyClD
+ (mkTyData DataType $3 (DataCons (reverse $4)) $5 $1))) }
+
+ | srcloc 'newtype' tycl_hdr '=' newconstr deriving
+ {% returnP (RdrHsDecl (TyClD
+ (mkTyData NewType $3 (DataCons [$5]) $6 $1))) }
+
+ | srcloc 'class' tycl_hdr fds where
+ {% let
(binds,sigs) = cvMonoBindsAndSigs cvClassOpSig (groupBindings $5)
in
returnP (RdrHsDecl (TyClD
- (mkClassDecl cs c ts $4 sigs binds $1))) }
+ (mkClassDecl $3 $4 sigs (Just binds) $1))) }
| srcloc 'instance' inst_type where
{ let (binds,sigs)
(groupBindings $4)
in RdrHsDecl (InstD (InstDecl $3 binds sigs Nothing $1)) }
- | srcloc 'default' '(' types0 ')'
- { RdrHsDecl (DefD (DefaultDecl $4 $1)) }
-
- | srcloc 'foreign' 'import' callconv ext_name
- unsafe_flag varid_no_unsafe '::' sigtype
- { RdrHsDecl (ForD (ForeignDecl $7 (FoImport $6) $9 (mkExtName $5 $7) $4 $1)) }
-
- | srcloc 'foreign' 'export' callconv ext_name varid '::' sigtype
- { RdrHsDecl (ForD (ForeignDecl $6 FoExport $8 (mkExtName $5 $6) $4 $1)) }
-
- | srcloc 'foreign' 'label' ext_name varid '::' sigtype
- { RdrHsDecl (ForD (ForeignDecl $5 FoLabel $7 (mkExtName $4 $5)
- defaultCallConv $1)) }
-
+ | srcloc 'default' '(' comma_types0 ')' { RdrHsDecl (DefD (DefaultDecl $4 $1)) }
+ | 'foreign' fdecl { RdrHsDecl $2 }
| '{-# DEPRECATED' deprecations '#-}' { $2 }
| '{-# RULES' rules '#-}' { $2 }
| decl { $1 }
+-- tycl_hdr parses the header of a type or class decl,
+-- which takes the form
+-- T a b
+-- Eq a => T a
+-- (Eq a, Ord b) => T a b
+-- Rather a lot of inlining here, else we get reduce/reduce errors
+tycl_hdr :: { (RdrNameContext, RdrName, [RdrNameHsTyVar]) }
+ : '(' comma_types1 ')' '=>' gtycon tv_bndrs {% mapP checkPred $2 `thenP` \ cxt ->
+ returnP (cxt, $5, $6) }
+ -- qtycon for the class below name would lead to many s/r conflicts
+ -- FIXME: does the renamer pick up all wrong forms and raise an
+ -- error
+ | gtycon atypes1 '=>' gtycon atypes0 {% checkTyVars $5 `thenP` \ tvs ->
+ returnP ([HsClassP $1 $2], $4, tvs) }
+ | gtycon atypes0 {% checkTyVars $2 `thenP` \ tvs ->
+ returnP ([], $1, tvs) }
+ -- We have to have qtycon in this production to avoid s/r
+ -- conflicts with the previous one. The renamer will complain
+ -- if we use a qualified tycon.
+ --
+ -- Using a `gtycon' throughout. This enables special syntax,
+ -- such as "[]" for tycons as well as tycon ops in
+ -- parentheses. This is beyond H98, but used repeatedly in
+ -- the Prelude modules. (So, it would be a good idea to raise
+ -- an error in the renamer if some non-H98 form is used and
+ -- -fglasgow-exts is not given.) -=chak
+
decls :: { [RdrBinding] }
: decls ';' decl { $3 : $1 }
| decls ';' { $1 }
decl :: { RdrBinding }
: fixdecl { $1 }
| valdef { $1 }
- | '{-# INLINE' srcloc opt_phase qvar '#-}' { RdrSig (InlineSig $4 $3 $2) }
- | '{-# NOINLINE' srcloc opt_phase qvar '#-}' { RdrSig (NoInlineSig $4 $3 $2) }
+ | '{-# INLINE' srcloc activation qvar '#-}' { RdrSig (InlineSig True $4 $3 $2) }
+ | '{-# NOINLINE' srcloc inverse_activation qvar '#-}' { RdrSig (InlineSig False $4 $3 $2) }
| '{-# SPECIALISE' srcloc qvar '::' sigtypes '#-}'
{ foldr1 RdrAndBindings
(map (\t -> RdrSig (SpecSig $3 t $2)) $5) }
| '{-# SPECIALISE' srcloc 'instance' inst_type '#-}'
{ RdrSig (SpecInstSig $4 $2) }
-opt_phase :: { Maybe Int }
- : INTEGER { Just (fromInteger $1) }
- | {- empty -} { Nothing }
-
wherebinds :: { RdrNameHsBinds }
: where { cvBinds cvValSig (groupBindings $1) }
| {- empty -} { RdrNullBind }
rule :: { RdrBinding }
- : STRING rule_forall fexp '=' srcloc exp
- { RdrHsDecl (RuleD (HsRule $1 [] $2 $3 $6 $5)) }
+ : STRING activation rule_forall infixexp '=' srcloc exp
+ { RdrHsDecl (RuleD (HsRule $1 $2 $3 $4 $7 $6)) }
+
+activation :: { Activation } -- Omitted means AlwaysActive
+ : {- empty -} { AlwaysActive }
+ | explicit_activation { $1 }
+
+inverse_activation :: { Activation } -- Omitted means NeverActive
+ : {- empty -} { NeverActive }
+ | explicit_activation { $1 }
+
+explicit_activation :: { Activation } -- In brackets
+ : '[' INTEGER ']' { ActiveAfter (fromInteger $2) }
+ | '[' '~' INTEGER ']' { ActiveBefore (fromInteger $3) }
rule_forall :: { [RdrNameRuleBndr] }
: 'forall' rule_var_list '.' { $2 }
{ foldr RdrAndBindings RdrNullBind
[ RdrHsDecl (DeprecD (Deprecation n $3 $1)) | n <- $2 ] }
------------------------------------------------------------------------------
--- Foreign import/export
-callconv :: { Int }
- : 'stdcall' { stdCallConv }
- | 'ccall' { cCallConv }
- | {- empty -} { defaultCallConv }
-
-unsafe_flag :: { Bool }
- : 'unsafe' { True }
- | {- empty -} { False }
-
-ext_name :: { Maybe ExtName }
- : 'dynamic' { Just Dynamic }
- | STRING { Just (ExtName $1 Nothing) }
- | STRING STRING { Just (ExtName $2 (Just $1)) }
+-----------------------------------------------------------------------------
+-- Foreign import and export declarations
+
+-- for the time being, the following accepts foreign declarations conforming
+-- to the FFI Addendum, Version 1.0 as well as pre-standard declarations
+--
+-- * a flag indicates whether pre-standard declarations have been used and
+-- triggers a deprecation warning further down the road
+--
+-- NB: The first two rules could be combined into one by replacing `safety1'
+-- with `safety'. However, the combined rule conflicts with the
+-- DEPRECATED rules.
+--
+fdecl :: { RdrNameHsDecl }
+fdecl : srcloc 'import' callconv safety1 fspec {% mkImport $3 $4 $5 $1 }
+ | srcloc 'import' callconv fspec {% mkImport $3 (PlaySafe False) $4 $1 }
+ | srcloc 'export' callconv fspec {% mkExport $3 $4 $1 }
+ -- the following syntax is DEPRECATED
+ | srcloc fdecl1DEPRECATED { ForD ($2 True $1) }
+ | srcloc fdecl2DEPRECATED { $2 $1 }
+
+fdecl1DEPRECATED :: { Bool -> SrcLoc -> ForeignDecl RdrName }
+fdecl1DEPRECATED
+ ----------- DEPRECATED label decls ------------
+ : 'label' ext_name varid '::' sigtype
+ { ForeignImport $3 $5 (CImport defaultCCallConv (PlaySafe False) _NIL_ _NIL_
+ (CLabel ($2 `orElse` mkExtName $3))) }
+
+ ----------- DEPRECATED ccall/stdcall decls ------------
+ --
+ -- NB: This business with the case expression below may seem overly
+ -- complicated, but it is necessary to avoid some conflicts.
+
+ -- DEPRECATED variant #1: lack of a calling convention specification
+ -- (import)
+ | 'import' {-no callconv-} ext_name safety varid_no_unsafe '::' sigtype
+ { let
+ target = StaticTarget ($2 `orElse` mkExtName $4)
+ in
+ ForeignImport $4 $6 (CImport defaultCCallConv $3 _NIL_ _NIL_
+ (CFunction target)) }
+
+ -- DEPRECATED variant #2: external name consists of two separate strings
+ -- (module name and function name) (import)
+ | 'import' callconv STRING STRING safety varid_no_unsafe '::' sigtype
+ {% case $2 of
+ DNCall -> parseError "Illegal format of .NET foreign import"
+ CCall cconv -> returnP $
+ let
+ imp = CFunction (StaticTarget $4)
+ in
+ ForeignImport $6 $8 (CImport cconv $5 _NIL_ _NIL_ imp) }
+
+ -- DEPRECATED variant #3: `unsafe' after entity
+ | 'import' callconv STRING 'unsafe' varid_no_unsafe '::' sigtype
+ {% case $2 of
+ DNCall -> parseError "Illegal format of .NET foreign import"
+ CCall cconv -> returnP $
+ let
+ imp = CFunction (StaticTarget $3)
+ in
+ ForeignImport $5 $7 (CImport cconv PlayRisky _NIL_ _NIL_ imp) }
+
+ -- DEPRECATED variant #4: use of the special identifier `dynamic' without
+ -- an explicit calling convention (import)
+ | 'import' {-no callconv-} 'dynamic' safety varid_no_unsafe '::' sigtype
+ { ForeignImport $4 $6 (CImport defaultCCallConv $3 _NIL_ _NIL_
+ (CFunction DynamicTarget)) }
+
+ -- DEPRECATED variant #5: use of the special identifier `dynamic' (import)
+ | 'import' callconv 'dynamic' safety varid_no_unsafe '::' sigtype
+ {% case $2 of
+ DNCall -> parseError "Illegal format of .NET foreign import"
+ CCall cconv -> returnP $
+ ForeignImport $5 $7 (CImport cconv $4 _NIL_ _NIL_
+ (CFunction DynamicTarget)) }
+
+ -- DEPRECATED variant #6: lack of a calling convention specification
+ -- (export)
+ | 'export' {-no callconv-} ext_name varid '::' sigtype
+ { ForeignExport $3 $5 (CExport (CExportStatic ($2 `orElse` mkExtName $3)
+ defaultCCallConv)) }
+
+ -- DEPRECATED variant #7: external name consists of two separate strings
+ -- (module name and function name) (export)
+ | 'export' callconv STRING STRING varid '::' sigtype
+ {% case $2 of
+ DNCall -> parseError "Illegal format of .NET foreign import"
+ CCall cconv -> returnP $
+ ForeignExport $5 $7
+ (CExport (CExportStatic $4 cconv)) }
+
+ -- DEPRECATED variant #8: use of the special identifier `dynamic' without
+ -- an explicit calling convention (export)
+ | 'export' {-no callconv-} 'dynamic' varid '::' sigtype
+ { ForeignImport $3 $5 (CImport defaultCCallConv (PlaySafe False) _NIL_ _NIL_
+ CWrapper) }
+
+ -- DEPRECATED variant #9: use of the special identifier `dynamic' (export)
+ | 'export' callconv 'dynamic' varid '::' sigtype
+ {% case $2 of
+ DNCall -> parseError "Illegal format of .NET foreign import"
+ CCall cconv -> returnP $
+ ForeignImport $4 $6 (CImport cconv (PlaySafe False) _NIL_ _NIL_ CWrapper) }
+
+ ----------- DEPRECATED .NET decls ------------
+ -- NB: removed the .NET call declaration, as it is entirely subsumed
+ -- by the new standard FFI declarations
+
+fdecl2DEPRECATED :: { SrcLoc -> RdrNameHsDecl }
+fdecl2DEPRECATED
+ : 'import' 'dotnet' 'type' ext_name tycon
+ { \loc -> TyClD (ForeignType $5 $4 DNType loc) }
+ -- left this one unchanged for the moment as type imports are not
+ -- covered currently by the FFI standard -=chak
+
+
+callconv :: { CallConv }
+ : 'stdcall' { CCall StdCallConv }
+ | 'ccall' { CCall CCallConv }
+ | 'dotnet' { DNCall }
+
+safety :: { Safety }
+ : 'unsafe' { PlayRisky }
+ | 'safe' { PlaySafe False }
+ | 'threadsafe' { PlaySafe True }
+ | {- empty -} { PlaySafe False }
+
+safety1 :: { Safety }
+ : 'unsafe' { PlayRisky }
+ | 'safe' { PlaySafe False }
+ | 'threadsafe' { PlaySafe True }
+ -- only needed to avoid conflicts with the DEPRECATED rules
+
+fspec :: { (FAST_STRING, RdrName, RdrNameHsType) }
+ : STRING varid '::' sigtype { ($1 , $2, $4) }
+ | varid '::' sigtype { (SLIT(""), $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
+
+-- DEPRECATED syntax
+ext_name :: { Maybe CLabelString }
+ : STRING { Just $1 }
+ | STRING STRING { Just $2 } -- Ignore "module name" for now
| {- empty -} { Nothing }
| sigtypes ',' sigtype { $3 : $1 }
sigtype :: { RdrNameHsType }
- : ctype { (mkHsForAllTy Nothing [] $1) }
+ : ctype { mkHsForAllTy Nothing [] $1 }
sig_vars :: { [RdrName] }
: sig_vars ',' var { $3 : $1 }
-- A ctype is a for-all type
ctype :: { RdrNameHsType }
- : 'forall' tyvars '.' ctype { mkHsForAllTy (Just $2) [] $4 }
- | context type { mkHsForAllTy Nothing $1 $2 }
+ : 'forall' tv_bndrs '.' ctype { mkHsForAllTy (Just $2) [] $4 }
+ | context '=>' type { mkHsForAllTy Nothing $1 $3 }
-- A type of form (context => type) is an *implicit* HsForAllTy
| type { $1 }
+-- We parse a context as a btype so that we don't get reduce/reduce
+-- 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 =>
+context :: { RdrNameContext }
+ : btype {% checkContext $1 }
+
type :: { RdrNameHsType }
: gentype '->' type { HsFunTy $1 $3 }
| ipvar '::' type { mkHsIParamTy $1 $3 }
| atype tyconop atype { HsOpTy $1 $2 $3 }
btype :: { RdrNameHsType }
- : btype atype { (HsAppTy $1 $2) }
+ : btype atype { HsAppTy $1 $2 }
| atype { $1 }
atype :: { RdrNameHsType }
: gtycon { HsTyVar $1 }
| tyvar { HsTyVar $1 }
- | '(' type ',' types ')' { HsTupleTy (mkHsTupCon tcName Boxed ($2:$4)) ($2 : reverse $4) }
- | '(#' types '#)' { HsTupleTy (mkHsTupCon tcName Unboxed $2) (reverse $2) }
+ | '(' type ',' comma_types1 ')' { HsTupleTy (mkHsTupCon tcName Boxed ($2:$4)) ($2:$4) }
+ | '(#' comma_types1 '#)' { HsTupleTy (mkHsTupCon tcName Unboxed $2) $2 }
| '[' type ']' { HsListTy $2 }
+ | '[:' type ':]' { HsPArrTy $2 }
| '(' ctype ')' { $2 }
+ | '(' ctype '::' kind ')' { HsKindSig $2 $4 }
-- Generics
| INTEGER { HsNumTy $1 }
inst_type :: { RdrNameHsType }
: ctype {% checkInstType $1 }
-types0 :: { [RdrNameHsType] }
- : types { $1 }
+comma_types0 :: { [RdrNameHsType] }
+ : comma_types1 { $1 }
| {- empty -} { [] }
-types :: { [RdrNameHsType] }
+comma_types1 :: { [RdrNameHsType] }
: type { [$1] }
- | types ',' type { $3 : $1 }
-
-simpletype :: { (RdrName, [RdrNameHsTyVar]) }
- : tycon tyvars { ($1, reverse $2) }
+ | type ',' comma_types1 { $1 : $3 }
-tyvars :: { [RdrNameHsTyVar] }
- : tyvars tyvar { UserTyVar $2 : $1 }
+atypes0 :: { [RdrNameHsType] }
+ : atypes1 { $1 }
| {- empty -} { [] }
+atypes1 :: { [RdrNameHsType] }
+ : atype { [$1] }
+ | atype atypes1 { $1 : $2 }
+
+tv_bndrs :: { [RdrNameHsTyVar] }
+ : tv_bndr tv_bndrs { $1 : $2 }
+ | {- empty -} { [] }
+
+tv_bndr :: { RdrNameHsTyVar }
+ : tyvar { UserTyVar $1 }
+ | '(' tyvar '::' kind ')' { IfaceTyVar $2 $4 }
+
fds :: { [([RdrName], [RdrName])] }
: {- empty -} { [] }
| '|' fds1 { reverse $2 }
| varids0 tyvar { $2 : $1 }
-----------------------------------------------------------------------------
+-- Kinds
+
+kind :: { Kind }
+ : akind { $1 }
+ | akind '->' kind { mkArrowKind $1 $3 }
+
+akind :: { Kind }
+ : '*' { liftedTypeKind }
+ | '(' kind ')' { $2 }
+
+
+-----------------------------------------------------------------------------
-- Datatype declarations
newconstr :: { RdrNameConDecl }
- : srcloc conid atype { mkConDecl $2 [] [] (VanillaCon [Unbanged $3]) $1 }
- | srcloc conid '{' var '::' type '}'
- { mkConDecl $2 [] [] (RecCon [([$4], Unbanged $6)]) $1 }
+ : srcloc conid atype { mkConDecl $2 [] [] (VanillaCon [unbangedType $3]) $1 }
+ | srcloc conid '{' var '::' ctype '}'
+ { mkConDecl $2 [] [] (RecCon [([$4], unbangedType $6)]) $1 }
constrs :: { [RdrNameConDecl] }
- : constrs '|' constr { $3 : $1 }
+ : {- empty; a GHC extension -} { [] }
+ | '=' constrs1 { $2 }
+
+constrs1 :: { [RdrNameConDecl] }
+ : constrs1 '|' constr { $3 : $1 }
| constr { [$1] }
constr :: { RdrNameConDecl }
- : srcloc forall context constr_stuff
- { mkConDecl (fst $4) $2 $3 (snd $4) $1 }
+ : srcloc forall context '=>' constr_stuff
+ { mkConDecl (fst $5) $2 $3 (snd $5) $1 }
| srcloc forall constr_stuff
{ mkConDecl (fst $3) $2 [] (snd $3) $1 }
forall :: { [RdrNameHsTyVar] }
- : 'forall' tyvars '.' { $2 }
+ : 'forall' tv_bndrs '.' { $2 }
| {- empty -} { [] }
-context :: { RdrNameContext }
- : btype '=>' {% checkContext $1 }
-
constr_stuff :: { (RdrName, RdrNameConDetails) }
: btype {% mkVanillaCon $1 [] }
- | btype '!' atype satypes {% mkVanillaCon $1 (Banged $3 : $4) }
+ | btype '!' atype satypes {% mkVanillaCon $1 (BangType MarkedUserStrict $3 : $4) }
+ | gtycon '{' '}' {% mkRecCon $1 [] }
| gtycon '{' fielddecls '}' {% mkRecCon $1 $3 }
| sbtype conop sbtype { ($2, InfixCon $1 $3) }
satypes :: { [RdrNameBangType] }
- : atype satypes { Unbanged $1 : $2 }
- | '!' atype satypes { Banged $2 : $3 }
+ : atype satypes { unbangedType $1 : $2 }
+ | '!' atype satypes { BangType MarkedUserStrict $2 : $3 }
| {- empty -} { [] }
sbtype :: { RdrNameBangType }
- : btype { Unbanged $1 }
- | '!' atype { Banged $2 }
+ : btype { unbangedType $1 }
+ | '!' atype { BangType MarkedUserStrict $2 }
fielddecls :: { [([RdrName],RdrNameBangType)] }
: fielddecl ',' fielddecls { $1 : $3 }
: sig_vars '::' stype { (reverse $1, $3) }
stype :: { RdrNameBangType }
- : ctype { Unbanged $1 }
- | '!' atype { Banged $2 }
+ : ctype { unbangedType $1 }
+ | '!' atype { BangType MarkedUserStrict $2 }
-deriving :: { Maybe [RdrName] }
+deriving :: { Maybe RdrNameContext }
: {- empty -} { Nothing }
- | 'deriving' qtycls { Just [$2] }
- | 'deriving' '(' ')' { Just [] }
- | 'deriving' '(' dclasses ')' { Just (reverse $3) }
-
-dclasses :: { [RdrName] }
- : dclasses ',' qtycls { $3 : $1 }
- | qtycls { [$1] }
+ | 'deriving' context { Just $2 }
+ -- Glasgow extension: allow partial
+ -- applications in derivings
-----------------------------------------------------------------------------
-- Value definitions
rhs :: { RdrNameGRHSs }
- : '=' srcloc exp wherebinds { (GRHSs (unguardedRHS $3 $2)
- $4 Nothing)}
- | gdrhs wherebinds { GRHSs (reverse $1) $2 Nothing }
+ : '=' srcloc exp wherebinds { (GRHSs (unguardedRHS $3 $2) $4 placeHolderType)}
+ | gdrhs wherebinds { GRHSs (reverse $1) $2 placeHolderType }
gdrhs :: { [RdrNameGRHS] }
: gdrhs gdrh { $2 : $1 }
| gdrh { [$1] }
gdrh :: { RdrNameGRHS }
- : '|' srcloc quals '=' exp { GRHS (reverse (ExprStmt $5 $2 : $3)) $2 }
+ : '|' srcloc quals '=' exp { GRHS (reverse (ResultStmt $5 $2 : $3)) $2 }
-----------------------------------------------------------------------------
-- Expressions
(panic "fixity") $3 )}
exp10 :: { RdrNameHsExpr }
- : '\\' aexp aexps opt_asig '->' srcloc exp
- {% checkPatterns ($2 : reverse $3) `thenP` \ ps ->
- returnP (HsLam (Match [] ps $4
- (GRHSs (unguardedRHS $7 $6)
- EmptyBinds Nothing))) }
+ : '\\' srcloc aexp aexps opt_asig '->' srcloc exp
+ {% checkPatterns $2 ($3 : reverse $4) `thenP` \ ps ->
+ returnP (HsLam (Match ps $5
+ (GRHSs (unguardedRHS $8 $7)
+ EmptyBinds placeHolderType))) }
| 'let' declbinds 'in' exp { HsLet $2 $4 }
| 'if' srcloc exp 'then' exp 'else' exp { HsIf $3 $5 $7 $2 }
| 'case' srcloc exp 'of' altslist { HsCase $3 $5 $2 }
| '-' fexp { mkHsNegApp $2 }
- | srcloc 'do' stmtlist { HsDo DoStmt $3 $1 }
+ | srcloc 'do' stmtlist {% checkDo $3 `thenP` \ stmts ->
+ returnP (HsDo DoExpr stmts $1) }
- | '_ccall_' ccallid aexps0 { HsCCall $2 $3 False False cbot }
- | '_ccall_GC_' ccallid aexps0 { HsCCall $2 $3 True False cbot }
- | '_casm_' CLITLIT aexps0 { HsCCall $2 $3 False True cbot }
- | '_casm_GC_' CLITLIT aexps0 { HsCCall $2 $3 True True cbot }
+ | '_ccall_' ccallid aexps0 { HsCCall $2 $3 PlayRisky False placeHolderType }
+ | '_ccall_GC_' ccallid aexps0 { HsCCall $2 $3 (PlaySafe False) False placeHolderType }
+ | '_casm_' CLITLIT aexps0 { HsCCall $2 $3 PlayRisky True placeHolderType }
+ | '_casm_GC_' CLITLIT aexps0 { HsCCall $2 $3 (PlaySafe False) True placeHolderType }
- | '_scc_' STRING exp { if opt_SccProfilingOn
- then HsSCC $2 $3
- else HsPar $3 }
+ | scc_annot exp { if opt_SccProfilingOn
+ then HsSCC $1 $2
+ else HsPar $2 }
| fexp { $1 }
+scc_annot :: { FAST_STRING }
+ : '_scc_' STRING { $2 }
+ | '{-# SCC' STRING '#-}' { $2 }
+
ccallid :: { FAST_STRING }
: VARID { $1 }
| CONID { $1 }
| aexp { $1 }
aexps0 :: { [RdrNameHsExpr] }
- : aexps { (reverse $1) }
+ : aexps { reverse $1 }
aexps :: { [RdrNameHsExpr] }
: aexps aexp { $2 : $1 }
: ipvar { HsIPVar $1 }
| var_or_con { $1 }
| literal { HsLit $1 }
- | INTEGER { HsOverLit (HsIntegral $1 fromInteger_RDR) }
- | RATIONAL { HsOverLit (HsFractional $1 fromRational_RDR) }
+ | INTEGER { HsOverLit (mkHsIntegral $1) }
+ | RATIONAL { HsOverLit (mkHsFractional $1) }
| '(' exp ')' { HsPar $2 }
| '(' exp ',' texps ')' { ExplicitTuple ($2 : reverse $4) Boxed}
| '(#' texps '#)' { ExplicitTuple (reverse $2) Unboxed }
| '[' list ']' { $2 }
+ | '[:' parr ':]' { $2 }
| '(' infixexp qop ')' { (SectionL $2 (HsVar $3)) }
| '(' qopm infixexp ')' { (SectionR $2 $3) }
| qvar '@' aexp { EAsPat $1 $3 }
-- avoiding another shift/reduce-conflict.
list :: { RdrNameHsExpr }
- : exp { ExplicitList [$1] }
- | lexps { ExplicitList (reverse $1) }
+ : exp { ExplicitList placeHolderType [$1] }
+ | lexps { ExplicitList placeHolderType (reverse $1) }
| exp '..' { ArithSeqIn (From $1) }
| exp ',' exp '..' { ArithSeqIn (FromThen $1 $3) }
| exp '..' exp { ArithSeqIn (FromTo $1 $3) }
body qss = [ParStmt (map reverse qss)] }
in
returnP ( HsDo ListComp
- (reverse (ReturnStmt $1 : body $3))
+ (reverse (ResultStmt $1 $2 : body $3))
$2
)
}
| '|' quals { [$2] }
quals :: { [RdrNameStmt] }
- : quals ',' qual { $3 : $1 }
- | qual { [$1] }
+ : quals ',' stmt { $3 : $1 }
+ | stmt { [$1] }
-qual :: { RdrNameStmt }
- : srcloc infixexp '<-' exp {% checkPattern $2 `thenP` \p ->
- returnP (BindStmt p $4 $1) }
- | srcloc exp { GuardStmt $2 $1 }
- | srcloc 'let' declbinds { LetStmt $3 }
+-----------------------------------------------------------------------------
+-- Parallel array expressions
+
+-- The rules below are little bit contorted; see the list case for details.
+-- Note that, in contrast to lists, we only have finite arithmetic sequences.
+-- Moreover, we allow explicit arrays with no element (represented by the nil
+-- constructor in the list case).
+
+parr :: { RdrNameHsExpr }
+ : { ExplicitPArr placeHolderType [] }
+ | exp { ExplicitPArr placeHolderType [$1] }
+ | lexps { ExplicitPArr placeHolderType
+ (reverse $1) }
+ | exp '..' exp { PArrSeqIn (FromTo $1 $3) }
+ | exp ',' exp '..' exp { PArrSeqIn (FromThenTo $1 $3 $5) }
+ | exp srcloc pquals {% let {
+ body [qs] = qs;
+ body qss = [ParStmt
+ (map reverse qss)]}
+ in
+ returnP $
+ HsDo PArrComp
+ (reverse (ResultStmt $1 $2
+ : body $3))
+ $2
+ }
+
+-- We are reusing `lexps' and `pquals' from the list case.
-----------------------------------------------------------------------------
-- Case alternatives
| alt { [$1] }
alt :: { RdrNameMatch }
- : infixexp opt_sig ralt wherebinds
- {% (checkPattern $1 `thenP` \p ->
- returnP (Match [] [p] $2
- (GRHSs $3 $4 Nothing)) )}
+ : srcloc infixexp opt_sig ralt wherebinds
+ {% (checkPattern $1 $2 `thenP` \p ->
+ returnP (Match [p] $3
+ (GRHSs $4 $5 placeHolderType)) )}
ralt :: { [RdrNameGRHS] }
- : '->' srcloc exp { [GRHS [ExprStmt $3 $2] $2] }
- | gdpats { (reverse $1) }
+ : '->' srcloc exp { [GRHS [ResultStmt $3 $2] $2] }
+ | gdpats { reverse $1 }
gdpats :: { [RdrNameGRHS] }
: gdpats gdpat { $2 : $1 }
| gdpat { [$1] }
gdpat :: { RdrNameGRHS }
- : srcloc '|' quals '->' exp { GRHS (reverse (ExprStmt $5 $1:$3)) $1}
+ : srcloc '|' quals '->' exp { GRHS (reverse (ResultStmt $5 $1:$3)) $1}
-----------------------------------------------------------------------------
-- Statement sequences
stmtlist :: { [RdrNameStmt] }
- : '{' stmts '}' { reverse $2 }
- | layout_on_for_do stmts close { reverse $2 }
-
--- Stmt list should really end in an expression, but it's not
--- convenient to enforce this here, so we throw out erroneous
--- statement sequences in the renamer instead.
-
+ : '{' stmts '}' { $2 }
+ | layout_on_for_do stmts close { $2 }
+
+-- do { ;; s ; s ; ; s ;; }
+-- The last Stmt should be a ResultStmt, but that's hard to enforce
+-- here, because we need too much lookahead if we see do { e ; }
+-- So we use ExprStmts throughout, and switch the last one over
+-- in ParseUtils.checkDo instead
stmts :: { [RdrNameStmt] }
- : ';' stmts1 { $2 }
- | stmts1 { $1 }
+ : stmt stmts_help { $1 : $2 }
+ | ';' stmts { $2 }
+ | {- empty -} { [] }
+
+stmts_help :: { [RdrNameStmt] }
+ : ';' stmts { $2 }
+ | {- empty -} { [] }
-stmts1 :: { [RdrNameStmt] }
- : stmts1 ';' stmt { $3 : $1 }
- | stmts1 ';' { $1 }
- | stmt { [$1] }
+-- For typing stmts at the GHCi prompt, where
+-- the input may consist of just comments.
+maybe_stmt :: { Maybe RdrNameStmt }
+ : stmt { Just $1 }
+ | {- nothing -} { Nothing }
stmt :: { RdrNameStmt }
- : srcloc infixexp '<-' exp {% checkPattern $2 `thenP` \p ->
+ : srcloc infixexp '<-' exp {% checkPattern $1 $2 `thenP` \p ->
returnP (BindStmt p $4 $1) }
- | srcloc exp { ExprStmt $2 $1 }
+ | srcloc exp { ExprStmt $2 placeHolderType $1 }
| srcloc 'let' declbinds { LetStmt $3 }
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- Implicit Parameter Bindings
-dbinding :: { [(RdrName, RdrNameHsExpr)] }
+dbinding :: { [(IPName RdrName, RdrNameHsExpr)] }
: '{' dbinds '}' { $2 }
| layout_on dbinds close { $2 }
-dbinds :: { [(RdrName, RdrNameHsExpr)] }
+dbinds :: { [(IPName RdrName, RdrNameHsExpr)] }
: dbinds ';' dbind { $3 : $1 }
| dbinds ';' { $1 }
| dbind { [$1] }
| {- empty -} { [] }
-dbind :: { (RdrName, RdrNameHsExpr) }
+dbind :: { (IPName RdrName, RdrNameHsExpr) }
dbind : ipvar '=' exp { ($1, $3) }
-----------------------------------------------------------------------------
-- Variables, Constructors and Operators.
+identifier :: { RdrName }
+ : qvar { $1 }
+ | gcon { $1 }
+ | qop { $1 }
+
depreclist :: { [RdrName] }
depreclist : deprec_var { [$1] }
| deprec_var ',' depreclist { $1 : $3 }
| '(' ')' { unitTyCon_RDR }
| '(' '->' ')' { funTyCon_RDR }
| '[' ']' { listTyCon_RDR }
+ | '[:' ':]' { parrTyCon_RDR }
| '(' commas ')' { tupleTyCon_RDR $2 }
-gcon :: { RdrName }
+gcon :: { RdrName } -- Data constructor namespace
: '(' ')' { unitCon_RDR }
| '[' ']' { nilCon_RDR }
| '(' commas ')' { tupleCon_RDR $2 }
| qcon { $1 }
+-- the case of '[:' ':]' is part of the production `parr'
var :: { RdrName }
: varid { $1 }
-- whether it's a qvar or a var can be postponed until
-- *after* we see the close paren.
-ipvar :: { RdrName }
- : IPVARID { (mkUnqual ipName (tailFS $1)) }
+ipvar :: { IPName RdrName }
+ : IPDUPVARID { Dupable (mkUnqual varName $1) }
+ | IPSPLITVARID { Linear (mkUnqual varName $1) }
qcon :: { RdrName }
: qconid { $1 }
varid :: { RdrName }
: varid_no_unsafe { $1 }
| 'unsafe' { mkUnqual varName SLIT("unsafe") }
+ | 'safe' { mkUnqual varName SLIT("safe") }
+ | 'threadsafe' { mkUnqual varName SLIT("threadsafe") }
varid_no_unsafe :: { RdrName }
: VARID { mkUnqual varName $1 }
: VARID { mkUnqual tvName $1 }
| special_id { mkUnqual tvName $1 }
| 'unsafe' { mkUnqual tvName SLIT("unsafe") }
+ | 'safe' { mkUnqual tvName SLIT("safe") }
+ | 'threadsafe' { mkUnqual tvName SLIT("threadsafe") }
-- These special_ids are treated as keywords in various places,
--- but as ordinary ids elsewhere. A special_id collects all thsee
+-- but as ordinary ids elsewhere. 'special_id' collects all these
-- except 'unsafe' and 'forall' whose treatment differs depending on context
special_id :: { UserFS }
special_id
-----------------------------------------------------------------------------
-- ConIds
-qconid :: { RdrName }
+qconid :: { RdrName } -- Qualified or unqualifiedb
: conid { $1 }
| QCONID { mkQual dataName $1 }
-----------------------------------------------------------------------------
-- ConSyms
-qconsym :: { RdrName }
+qconsym :: { RdrName } -- Qualified or unqualifiedb
: consym { $1 }
| QCONSYM { mkQual dataName $1 }
special_sym :: { UserFS }
special_sym : '!' { SLIT("!") }
| '.' { SLIT(".") }
+ | '*' { SLIT("*") }
-----------------------------------------------------------------------------
-- Literals
| PRIMSTRING { HsStringPrim $1 }
| PRIMFLOAT { HsFloatPrim $1 }
| PRIMDOUBLE { HsDoublePrim $1 }
- | CLITLIT { HsLitLit $1 (error "Parser.y: CLITLIT") }
+ | CLITLIT { HsLitLit $1 placeHolderType }
srcloc :: { SrcLoc } : {% getSrcLocP }
modid :: { ModuleName }
: CONID { mkModuleNameFS $1 }
+ | QCONID { mkModuleNameFS
+ (mkFastString
+ (unpackFS (fst $1) ++
+ '.':unpackFS (snd $1)))
+ }
tycon :: { RdrName }
: CONID { mkUnqual tcClsName $1 }
tyconop :: { RdrName }
: CONSYM { mkUnqual tcClsName $1 }
-qtycon :: { RdrName }
- : tycon { $1 }
- | QCONID { mkQual tcClsName $1 }
-
-qtyconop :: { RdrName }
- : tyconop { $1 }
- | QCONSYM { mkQual tcClsName $1 }
+qtycon :: { RdrName } -- Qualified or unqualified
+ : QCONID { mkQual tcClsName $1 }
+ | tycon { $1 }
-qtycls :: { RdrName }
- : qtycon { $1 }
+qtyconop :: { RdrName } -- Qualified or unqualified
+ : QCONSYM { mkQual tcClsName $1 }
+ | tyconop { $1 }
commas :: { Int }
: commas ',' { $1 + 1 }
-----------------------------------------------------------------------------
{
-data ParseStuff = PModule RdrNameHsModule | PExpr RdrNameHsExpr
-
happyError :: P a
happyError buf PState{ loc = loc } = PFailed (srcParseErr buf loc)
}