-{-
+{- -*-haskell-*-
-----------------------------------------------------------------------------
-$Id: Parser.y,v 1.75 2001/10/22 09:37:24 simonpj Exp $
+$Id: Parser.y,v 1.84 2002/02/11 08:20:44 chak Exp $
Haskell grammar.
import Lex
import ParseUtil
import RdrName
-import PrelNames ( mAIN_Name, unitTyCon_RDR, funTyCon_RDR, listTyCon_RDR,
- tupleTyCon_RDR, unitCon_RDR, nilCon_RDR, tupleCon_RDR
- )
+import PrelNames ( mAIN_Name, unitTyCon_RDR, funTyCon_RDR,
+ listTyCon_RDR, parrTyCon_RDR, tupleTyCon_RDR,
+ unitCon_RDR, nilCon_RDR, tupleCon_RDR )
import ForeignCall ( Safety(..), CExportSpec(..), CCallSpec(..),
CCallConv(..), CCallTarget(..), defaultCCallConv,
DNCallSpec(..) )
import SrcLoc ( SrcLoc )
import Module
import CmdLineOpts ( opt_SccProfilingOn )
-import BasicTypes ( Boxity(..), Fixity(..), FixityDirection(..),
+import BasicTypes ( Boxity(..), Fixity(..), FixityDirection(..), IPName(..),
NewOrData(..), StrictnessMark(..), Activation(..) )
import Panic
{-
-----------------------------------------------------------------------------
-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'
(shift parses as 'if x then y else (z + 1)', as per longest-parse rule)
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.
+
-----------------------------------------------------------------------------
-}
'export' { ITexport }
'label' { ITlabel }
'dynamic' { ITdynamic }
+ 'safe' { ITsafe }
'unsafe' { ITunsafe }
'with' { ITwith }
'stdcall' { ITstdcallconv }
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 $$ }
{ RdrHsDecl (TyClD (TySynonym (fst $3) (snd $3) $5 $1)) }
| srcloc 'data' ctype constrs deriving
- {% checkDataHeader $3 `thenP` \(cs,c,ts) ->
+ {% checkDataHeader "data" $3 `thenP` \(cs,c,ts) ->
returnP (RdrHsDecl (TyClD
(mkTyData DataType cs c ts (reverse $4) (length $4) $5 $1))) }
| srcloc 'newtype' ctype '=' newconstr deriving
- {% checkDataHeader $3 `thenP` \(cs,c,ts) ->
+ {% checkDataHeader "newtype" $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) ->
+ {% checkDataHeader "class" $3 `thenP` \(cs,c,ts) ->
let
(binds,sigs) = cvMonoBindsAndSigs cvClassOpSig (groupBindings $5)
in
in RdrHsDecl (InstD (InstDecl $3 binds sigs Nothing $1)) }
| srcloc 'default' '(' types0 ')' { RdrHsDecl (DefD (DefaultDecl $4 $1)) }
- | 'foreign' fordecl { RdrHsDecl $2 }
+ | 'foreign' fdecl { RdrHsDecl $2 }
| '{-# DEPRECATED' deprecations '#-}' { $2 }
| '{-# RULES' rules '#-}' { $2 }
| decl { $1 }
-fordecl :: { RdrNameHsDecl }
-fordecl : srcloc 'label' ext_name varid '::' sigtype
- { ForD (ForeignImport $4 $6 (LblImport ($3 `orElse` mkExtName $4)) $1) }
-
-
- ----------- ccall/stdcall decls ------------
- | srcloc 'import' ccallconv ext_name unsafe_flag varid_no_unsafe '::' sigtype
- { let
- call_spec = CCallSpec (StaticTarget ($4 `orElse` mkExtName $6)) $3 $5
- in
- ForD (ForeignImport $6 $8 (CImport call_spec) $1)
- }
-
- | srcloc 'import' ccallconv 'dynamic' unsafe_flag varid_no_unsafe '::' sigtype
- { let
- call_spec = CCallSpec DynamicTarget $3 $5
- in
- ForD (ForeignImport $6 $8 (CImport call_spec) $1)
- }
-
- | srcloc 'export' ccallconv ext_name varid '::' sigtype
- { ForD (ForeignExport $5 $7 (CExport (CExportStatic ($4 `orElse` mkExtName $5) $3)) $1) }
-
- | srcloc 'export' ccallconv 'dynamic' varid '::' sigtype
- { ForD (ForeignImport $5 $7 (CDynImport $3) $1) }
-
-
- ----------- .NET decls ------------
- | srcloc 'import' 'dotnet' ext_name varid '::' sigtype
- { ForD (ForeignImport $5 $7 (DNImport (DNCallSpec ($4 `orElse` mkExtName $5))) $1) }
-
- | srcloc 'import' 'dotnet' 'type' ext_name tycon
- { TyClD (ForeignType $6 $5 DNType $1) }
+-- 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 $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 _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 _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 _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
decls :: { [RdrBinding] }
: decls ';' decl { $3 : $1 }
rule :: { RdrBinding }
: STRING activation rule_forall infixexp '=' srcloc exp
- { RdrHsDecl (RuleD (HsRule $1 $2 [] $3 $4 $7 $6)) }
+ { RdrHsDecl (RuleD (HsRule $1 $2 $3 $4 $7 $6)) }
activation :: { Activation } -- Omitted means AlwaysActive
: {- empty -} { AlwaysActive }
- | '[' INTEGER ']' { ActiveAfter (fromInteger $2) }
+ | explicit_activation { $1 }
inverse_activation :: { Activation } -- Omitted means NeverActive
: {- empty -} { NeverActive }
- | '[' INTEGER ']' { ActiveAfter (fromInteger $2) }
+ | explicit_activation { $1 }
+
+explicit_activation :: { Activation } -- In brackets
+ : '[' INTEGER ']' { ActiveAfter (fromInteger $2) }
+ | '[' '~' INTEGER ']' { ActiveBefore (fromInteger $3) }
rule_forall :: { [RdrNameRuleBndr] }
: 'forall' rule_var_list '.' { $2 }
[ RdrHsDecl (DeprecD (Deprecation n $3 $1)) | n <- $2 ] }
-----------------------------------------------------------------------------
--- Foreign import/export
-
-ccallconv :: { CCallConv }
- : 'stdcall' { StdCallConv }
- | 'ccall' { CCallConv }
- | {- empty -} { defaultCCallConv }
-
-unsafe_flag :: { Safety }
- : 'unsafe' { PlayRisky }
- | {- empty -} { PlaySafe }
-
+-- Foreign declarations
+
+callconv :: { CallConv }
+ : 'stdcall' { CCall StdCallConv }
+ | 'ccall' { CCall CCallConv }
+ | 'dotnet' { DNCall }
+
+safety :: { Safety }
+ : 'unsafe' { PlayRisky }
+ | 'safe' { PlaySafe }
+ | {- empty -} { PlaySafe }
+
+safety1 :: { Safety }
+ : 'unsafe' { PlayRisky }
+ | 'safe' { PlaySafe }
+ -- 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
-- A ctype is a for-all type
ctype :: { RdrNameHsType }
: 'forall' tyvars '.' ctype { mkHsForAllTy (Just $2) [] $4 }
- | context type { mkHsForAllTy Nothing $1 $2 }
+ | context '=>' type { mkHsForAllTy Nothing $1 $3 }
-- A type of form (context => type) is an *implicit* HsForAllTy
| type { $1 }
| '(' type ',' types ')' { HsTupleTy (mkHsTupCon tcName Boxed ($2:$4)) ($2 : reverse $4) }
| '(#' types '#)' { HsTupleTy (mkHsTupCon tcName Unboxed $2) (reverse $2) }
| '[' type ']' { HsListTy $2 }
+ | '[:' type ':]' { HsPArrTy $2 }
| '(' ctype ')' { $2 }
-- Generics
| INTEGER { HsNumTy $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 }
| {- empty -} { [] }
context :: { RdrNameContext }
- : btype '=>' {% checkContext $1 }
+ : btype {% checkContext $1 }
constr_stuff :: { (RdrName, RdrNameConDetails) }
: btype {% mkVanillaCon $1 [] }
| btype '!' atype satypes {% mkVanillaCon $1 (BangType MarkedUserStrict $3 : $4) }
+ | gtycon '{' '}' {% mkRecCon $1 [] }
| gtycon '{' fielddecls '}' {% mkRecCon $1 $3 }
| sbtype conop sbtype { ($2, InfixCon $1 $3) }
: 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
exp10 :: { RdrNameHsExpr }
: '\\' srcloc aexp aexps opt_asig '->' srcloc exp
{% checkPatterns $2 ($3 : reverse $4) `thenP` \ ps ->
- returnP (HsLam (Match [] ps $5
+ returnP (HsLam (Match ps $5
(GRHSs (unguardedRHS $8 $7)
EmptyBinds placeHolderType))) }
| 'let' declbinds 'in' exp { HsLet $2 $4 }
| '(' 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 }
| stmt { [$1] }
-----------------------------------------------------------------------------
+-- 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
altslist :: { [RdrNameMatch] }
alt :: { RdrNameMatch }
: srcloc infixexp opt_sig ralt wherebinds
{% (checkPattern $1 $2 `thenP` \p ->
- returnP (Match [] [p] $3
+ returnP (Match [p] $3
(GRHSs $4 $5 placeHolderType)) )}
ralt :: { [RdrNameGRHS] }
-----------------------------------------------------------------------------
-- 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) }
-----------------------------------------------------------------------------
| '(' ')' { unitTyCon_RDR }
| '(' '->' ')' { funTyCon_RDR }
| '[' ']' { listTyCon_RDR }
+ | '[:' ':]' { parrTyCon_RDR }
| '(' commas ')' { tupleTyCon_RDR $2 }
gcon :: { RdrName }
| '[' ']' { 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 varName (tailFS $1)) }
+ipvar :: { IPName RdrName }
+ : IPDUPVARID { Dupable (mkUnqual varName $1) }
+ | IPSPLITVARID { Linear (mkUnqual varName $1) }
qcon :: { RdrName }
: qconid { $1 }
: tyconop { $1 }
| QCONSYM { mkQual tcClsName $1 }
-qtycls :: { RdrName }
- : qtycon { $1 }
-
commas :: { Int }
: commas ',' { $1 + 1 }
| ',' { 2 }