diff options
Diffstat (limited to 'compiler/parser/Parser.y.pp')
-rw-r--r-- | compiler/parser/Parser.y.pp | 1607 |
1 files changed, 1607 insertions, 0 deletions
diff --git a/compiler/parser/Parser.y.pp b/compiler/parser/Parser.y.pp new file mode 100644 index 0000000000..3066a0f876 --- /dev/null +++ b/compiler/parser/Parser.y.pp @@ -0,0 +1,1607 @@ +-- -*-haskell-*- +-- --------------------------------------------------------------------------- +-- (c) The University of Glasgow 1997-2003 +--- +-- The GHC grammar. +-- +-- Author(s): Simon Marlow, Sven Panne 1997, 1998, 1999 +-- --------------------------------------------------------------------------- + +{ +module Parser ( parseModule, parseStmt, parseIdentifier, parseType, + parseHeader ) where + +#define INCLUDE #include +INCLUDE "HsVersions.h" + +import HsSyn +import RdrHsSyn +import HscTypes ( IsBootInterface, DeprecTxt ) +import Lexer +import RdrName +import TysWiredIn ( unitTyCon, unitDataCon, tupleTyCon, tupleCon, nilDataCon, + listTyCon_RDR, parrTyCon_RDR, consDataCon_RDR ) +import Type ( funTyCon ) +import ForeignCall ( Safety(..), CExportSpec(..), CLabelString, + CCallConv(..), CCallTarget(..), defaultCCallConv + ) +import OccName ( varName, dataName, tcClsName, tvName ) +import DataCon ( DataCon, dataConName ) +import SrcLoc ( Located(..), unLoc, getLoc, noLoc, combineSrcSpans, + SrcSpan, combineLocs, srcLocFile, + mkSrcLoc, mkSrcSpan ) +import Module +import StaticFlags ( opt_SccProfilingOn ) +import Type ( Kind, mkArrowKind, liftedTypeKind ) +import BasicTypes ( Boxity(..), Fixity(..), FixityDirection(..), IPName(..), + Activation(..), defaultInlineSpec ) +import OrdList + +import FastString +import Maybes ( orElse ) +import Outputable +import GLAEXTS +} + +{- +----------------------------------------------------------------------------- +Conflicts: 36 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) + 10 because op might be: : - ! * . `x` VARSYM CONSYM QVARSYM QCONSYM + +1 for ambiguity in 'if x then y else z :: T' [State 178] + (shift parses as 'if x then y else (z :: T)', as per longest-parse rule) + +4 for ambiguity in 'if x then y else z -< e' [State 178] + (shift parses as 'if x then y else (z -< T)', as per longest-parse rule) + There are four such operators: -<, >-, -<<, >>- + + +2 for ambiguity in 'case v of { x :: T -> T ... } ' [States 11, 253] + Which of these two is intended? + case v of + (x::T) -> T -- Rhs is T + or + case v of + (x::T -> T) -> .. -- Rhs is ... + +10 for ambiguity in 'e :: a `b` c'. Does this mean [States 11, 253] + (e::a) `b` c, or + (e :: (a `b` c)) + As well as `b` we can have !, VARSYM, QCONSYM, and CONSYM, hence 5 cases + Same duplication between states 11 and 253 as the previous case + +1 for ambiguity in 'let ?x ...' [State 329] + the parser can't tell whether the ?x is the lhs of a normal binding or + an implicit binding. Fortunately resolving as shift gives it the only + sensible meaning, namely the lhs of an implicit binding. + +1 for ambiguity in '{-# RULES "name" [ ... #-} [State 382] + we don't know whether the '[' starts the activation or not: it + might be the start of the declaration with the activation being + empty. --SDM 1/4/2002 + +6 for conflicts between `fdecl' and `fdeclDEPRECATED', [States 393,394] + which are resolved correctly, and moreover, + should go away when `fdeclDEPRECATED' is removed. + +1 for ambiguity in '{-# RULES "name" forall = ... #-}' [State 474] + since 'forall' is a valid variable name, we don't know whether + to treat a forall on the input as the beginning of a quantifier + or the beginning of the rule itself. Resolving to shift means + it's always treated as a quantifier, hence the above is disallowed. + This saves explicitly defining a grammar for the rule lhs that + doesn't include 'forall'. + +-- --------------------------------------------------------------------------- +-- Adding location info + +This is done in a stylised way using the three macros below, L0, L1 +and LL. Each of these macros can be thought of as having type + + L0, L1, LL :: a -> Located a + +They each add a SrcSpan to their argument. + + L0 adds 'noSrcSpan', used for empty productions + + L1 for a production with a single token on the lhs. Grabs the SrcSpan + from that token. + + LL for a production with >1 token on the lhs. Makes up a SrcSpan from + the first and last tokens. + +These suffice for the majority of cases. However, we must be +especially careful with empty productions: LL won't work if the first +or last token on the lhs can represent an empty span. In these cases, +we have to calculate the span using more of the tokens from the lhs, eg. + + | 'newtype' tycl_hdr '=' newconstr deriving + { L (comb3 $1 $4 $5) + (mkTyData NewType (unLoc $2) [$4] (unLoc $5)) } + +We provide comb3 and comb4 functions which are useful in such cases. + +Be careful: there's no checking that you actually got this right, the +only symptom will be that the SrcSpans of your syntax will be +incorrect. + +/* + * We must expand these macros *before* running Happy, which is why this file is + * Parser.y.pp rather than just Parser.y - we run the C pre-processor first. + */ +#define L0 L noSrcSpan +#define L1 sL (getLoc $1) +#define LL sL (comb2 $1 $>) + +-- ----------------------------------------------------------------------------- + +-} + +%token + '_' { L _ ITunderscore } -- Haskell keywords + 'as' { L _ ITas } + 'case' { L _ ITcase } + 'class' { L _ ITclass } + 'data' { L _ ITdata } + 'default' { L _ ITdefault } + 'deriving' { L _ ITderiving } + 'do' { L _ ITdo } + 'else' { L _ ITelse } + 'hiding' { L _ IThiding } + 'if' { L _ ITif } + 'import' { L _ ITimport } + 'in' { L _ ITin } + 'infix' { L _ ITinfix } + 'infixl' { L _ ITinfixl } + 'infixr' { L _ ITinfixr } + 'instance' { L _ ITinstance } + 'let' { L _ ITlet } + 'module' { L _ ITmodule } + 'newtype' { L _ ITnewtype } + 'of' { L _ ITof } + 'qualified' { L _ ITqualified } + 'then' { L _ ITthen } + 'type' { L _ ITtype } + 'where' { L _ ITwhere } + '_scc_' { L _ ITscc } -- ToDo: remove + + 'forall' { L _ ITforall } -- GHC extension keywords + 'foreign' { L _ ITforeign } + 'export' { L _ ITexport } + 'label' { L _ ITlabel } + 'dynamic' { L _ ITdynamic } + 'safe' { L _ ITsafe } + 'threadsafe' { L _ ITthreadsafe } + 'unsafe' { L _ ITunsafe } + 'mdo' { L _ ITmdo } + 'stdcall' { L _ ITstdcallconv } + 'ccall' { L _ ITccallconv } + 'dotnet' { L _ ITdotnet } + 'proc' { L _ ITproc } -- for arrow notation extension + 'rec' { L _ ITrec } -- for arrow notation extension + + '{-# INLINE' { L _ (ITinline_prag _) } + '{-# SPECIALISE' { L _ ITspec_prag } + '{-# SPECIALISE_INLINE' { L _ (ITspec_inline_prag _) } + '{-# SOURCE' { L _ ITsource_prag } + '{-# RULES' { L _ ITrules_prag } + '{-# CORE' { L _ ITcore_prag } -- hdaume: annotated core + '{-# SCC' { L _ ITscc_prag } + '{-# DEPRECATED' { L _ ITdeprecated_prag } + '{-# UNPACK' { L _ ITunpack_prag } + '#-}' { L _ ITclose_prag } + + '..' { L _ ITdotdot } -- reserved symbols + ':' { L _ ITcolon } + '::' { L _ ITdcolon } + '=' { L _ ITequal } + '\\' { L _ ITlam } + '|' { L _ ITvbar } + '<-' { L _ ITlarrow } + '->' { L _ ITrarrow } + '@' { L _ ITat } + '~' { L _ ITtilde } + '=>' { L _ ITdarrow } + '-' { L _ ITminus } + '!' { L _ ITbang } + '*' { L _ ITstar } + '-<' { L _ ITlarrowtail } -- for arrow notation + '>-' { L _ ITrarrowtail } -- for arrow notation + '-<<' { L _ ITLarrowtail } -- for arrow notation + '>>-' { L _ ITRarrowtail } -- for arrow notation + '.' { L _ ITdot } + + '{' { L _ ITocurly } -- special symbols + '}' { L _ ITccurly } + '{|' { L _ ITocurlybar } + '|}' { L _ ITccurlybar } + vocurly { L _ ITvocurly } -- virtual open curly (from layout) + vccurly { L _ ITvccurly } -- virtual close curly (from layout) + '[' { L _ ITobrack } + ']' { L _ ITcbrack } + '[:' { L _ ITopabrack } + ':]' { L _ ITcpabrack } + '(' { L _ IToparen } + ')' { L _ ITcparen } + '(#' { L _ IToubxparen } + '#)' { L _ ITcubxparen } + '(|' { L _ IToparenbar } + '|)' { L _ ITcparenbar } + ';' { L _ ITsemi } + ',' { L _ ITcomma } + '`' { L _ ITbackquote } + + VARID { L _ (ITvarid _) } -- identifiers + CONID { L _ (ITconid _) } + VARSYM { L _ (ITvarsym _) } + CONSYM { L _ (ITconsym _) } + QVARID { L _ (ITqvarid _) } + QCONID { L _ (ITqconid _) } + QVARSYM { L _ (ITqvarsym _) } + QCONSYM { L _ (ITqconsym _) } + + IPDUPVARID { L _ (ITdupipvarid _) } -- GHC extension + IPSPLITVARID { L _ (ITsplitipvarid _) } -- GHC extension + + CHAR { L _ (ITchar _) } + STRING { L _ (ITstring _) } + INTEGER { L _ (ITinteger _) } + RATIONAL { L _ (ITrational _) } + + PRIMCHAR { L _ (ITprimchar _) } + PRIMSTRING { L _ (ITprimstring _) } + PRIMINTEGER { L _ (ITprimint _) } + PRIMFLOAT { L _ (ITprimfloat _) } + PRIMDOUBLE { L _ (ITprimdouble _) } + +-- Template Haskell +'[|' { L _ ITopenExpQuote } +'[p|' { L _ ITopenPatQuote } +'[t|' { L _ ITopenTypQuote } +'[d|' { L _ ITopenDecQuote } +'|]' { L _ ITcloseQuote } +TH_ID_SPLICE { L _ (ITidEscape _) } -- $x +'$(' { L _ ITparenEscape } -- $( exp ) +TH_VAR_QUOTE { L _ ITvarQuote } -- 'x +TH_TY_QUOTE { L _ ITtyQuote } -- ''T + +%monad { P } { >>= } { return } +%lexer { lexer } { L _ ITeof } +%name parseModule module +%name parseStmt maybe_stmt +%name parseIdentifier identifier +%name parseType ctype +%partial parseHeader header +%tokentype { (Located Token) } +%% + +----------------------------------------------------------------------------- +-- Identifiers; one of the entry points +identifier :: { Located RdrName } + : qvar { $1 } + | qcon { $1 } + | qvarop { $1 } + | qconop { $1 } + +----------------------------------------------------------------------------- +-- Module Header + +-- The place for module deprecation is really too restrictive, but if it +-- was allowed at its natural place just before 'module', we get an ugly +-- s/r conflict with the second alternative. Another solution would be the +-- introduction of a new pragma DEPRECATED_MODULE, but this is not very nice, +-- either, and DEPRECATED is only expected to be used by people who really +-- know what they are doing. :-) + +module :: { Located (HsModule RdrName) } + : 'module' modid maybemoddeprec maybeexports 'where' body + {% 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)) } + +missing_module_keyword :: { () } + : {- empty -} {% pushCurrentContext } + +maybemoddeprec :: { Maybe DeprecTxt } + : '{-# DEPRECATED' STRING '#-}' { Just (getSTRING $2) } + | {- empty -} { Nothing } + +body :: { ([LImportDecl RdrName], [LHsDecl RdrName]) } + : '{' top '}' { $2 } + | vocurly top close { $2 } + +top :: { ([LImportDecl RdrName], [LHsDecl RdrName]) } + : importdecls { (reverse $1,[]) } + | importdecls ';' cvtopdecls { (reverse $1,$3) } + | cvtopdecls { ([],$1) } + +cvtopdecls :: { [LHsDecl RdrName] } + : topdecls { cvTopDecls $1 } + +----------------------------------------------------------------------------- +-- 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)) } + | missing_module_keyword importdecls + {% fileSrcSpan >>= \ loc -> + return (L loc (HsModule Nothing Nothing $2 [] Nothing)) } + +header_body :: { [LImportDecl RdrName] } + : '{' importdecls { $2 } + | vocurly importdecls { $2 } + +----------------------------------------------------------------------------- +-- The Export List + +maybeexports :: { Maybe [LIE RdrName] } + : '(' exportlist ')' { Just $2 } + | {- empty -} { Nothing } + +exportlist :: { [LIE RdrName] } + : exportlist ',' export { $3 : $1 } + | exportlist ',' { $1 } + | export { [$1] } + | {- empty -} { [] } + + -- No longer allow things like [] and (,,,) to be exported + -- They are built in syntax, always available +export :: { LIE RdrName } + : qvar { L1 (IEVar (unLoc $1)) } + | oqtycon { L1 (IEThingAbs (unLoc $1)) } + | oqtycon '(' '..' ')' { LL (IEThingAll (unLoc $1)) } + | oqtycon '(' ')' { LL (IEThingWith (unLoc $1) []) } + | oqtycon '(' qcnames ')' { LL (IEThingWith (unLoc $1) (reverse $3)) } + | 'module' modid { LL (IEModuleContents (unLoc $2)) } + +qcnames :: { [RdrName] } + : qcnames ',' qcname { unLoc $3 : $1 } + | qcname { [unLoc $1] } + +qcname :: { Located RdrName } -- Variable or data constructor + : qvar { $1 } + | qcon { $1 } + +----------------------------------------------------------------------------- +-- Import Declarations + +-- import decls can be *empty*, or even just a string of semicolons +-- whereas topdecls must contain at least one topdecl. + +importdecls :: { [LImportDecl RdrName] } + : importdecls ';' importdecl { $3 : $1 } + | importdecls ';' { $1 } + | importdecl { [ $1 ] } + | {- empty -} { [] } + +importdecl :: { LImportDecl RdrName } + : 'import' maybe_src optqualified modid maybeas maybeimpspec + { L (comb4 $1 $4 $5 $6) (ImportDecl $4 $2 $3 (unLoc $5) (unLoc $6)) } + +maybe_src :: { IsBootInterface } + : '{-# SOURCE' '#-}' { True } + | {- empty -} { False } + +optqualified :: { Bool } + : 'qualified' { True } + | {- empty -} { False } + +maybeas :: { Located (Maybe Module) } + : 'as' modid { LL (Just (unLoc $2)) } + | {- empty -} { noLoc Nothing } + +maybeimpspec :: { Located (Maybe (Bool, [LIE RdrName])) } + : impspec { L1 (Just (unLoc $1)) } + | {- empty -} { noLoc Nothing } + +impspec :: { Located (Bool, [LIE RdrName]) } + : '(' exportlist ')' { LL (False, reverse $2) } + | 'hiding' '(' exportlist ')' { LL (True, reverse $3) } + +----------------------------------------------------------------------------- +-- Fixity Declarations + +prec :: { Int } + : {- empty -} { 9 } + | INTEGER {% checkPrecP (L1 (fromInteger (getINTEGER $1))) } + +infix :: { Located FixityDirection } + : 'infix' { L1 InfixN } + | 'infixl' { L1 InfixL } + | 'infixr' { L1 InfixR } + +ops :: { Located [Located RdrName] } + : ops ',' op { LL ($3 : unLoc $1) } + | op { L1 [$1] } + +----------------------------------------------------------------------------- +-- Top-Level Declarations + +topdecls :: { OrdList (LHsDecl RdrName) } -- Reversed + : topdecls ';' topdecl { $1 `appOL` $3 } + | topdecls ';' { $1 } + | topdecl { $1 } + +topdecl :: { OrdList (LHsDecl RdrName) } + : tycl_decl { unitOL (L1 (TyClD (unLoc $1))) } + | 'instance' inst_type where + { let (binds,sigs) = cvBindsAndSigs (unLoc $3) + in unitOL (L (comb3 $1 $2 $3) (InstD (InstDecl $2 binds sigs))) } + | 'default' '(' comma_types0 ')' { unitOL (LL $ DefD (DefaultDecl $3)) } + | 'foreign' fdecl { unitOL (LL (unLoc $2)) } + | '{-# DEPRECATED' deprecations '#-}' { $2 } + | '{-# RULES' rules '#-}' { $2 } + | '$(' exp ')' { unitOL (LL $ SpliceD (SpliceDecl $2)) } + | decl { unLoc $1 } + +tycl_decl :: { LTyClDecl RdrName } + : 'type' type '=' ctype + -- Note type on the left of the '='; this allows + -- infix type constructors to be declared + -- + -- Note ctype, not sigtype, on the right + -- 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 + {% do { (tc,tvs) <- checkSynHdr $2 + ; return (LL (TySynonym tc tvs $4)) } } + + | data_or_newtype tycl_hdr constrs deriving + { L (comb4 $1 $2 $3 $4) -- We need the location on tycl_hdr + -- in case constrs and deriving are both empty + (mkTyData (unLoc $1) (unLoc $2) Nothing (reverse (unLoc $3)) (unLoc $4)) } + + | data_or_newtype tycl_hdr opt_kind_sig + 'where' gadt_constrlist + deriving + { L (comb4 $1 $2 $4 $5) + (mkTyData (unLoc $1) (unLoc $2) $3 (reverse (unLoc $5)) (unLoc $6)) } + + | 'class' tycl_hdr fds where + { let + (binds,sigs) = cvBindsAndSigs (unLoc $4) + in + L (comb4 $1 $2 $3 $4) (mkClassDecl (unLoc $2) (unLoc $3) sigs + binds) } + +data_or_newtype :: { Located NewOrData } + : 'data' { L1 DataType } + | 'newtype' { L1 NewType } + +opt_kind_sig :: { Maybe Kind } + : { Nothing } + | '::' kind { Just $2 } + +-- 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 :: { Located (LHsContext RdrName, Located RdrName, [LHsTyVarBndr RdrName]) } + : context '=>' type {% checkTyClHdr $1 $3 >>= return.LL } + | type {% checkTyClHdr (noLoc []) $1 >>= return.L1 } + +----------------------------------------------------------------------------- +-- Nested declarations + +decls :: { Located (OrdList (LHsDecl RdrName)) } -- Reversed + : decls ';' decl { LL (unLoc $1 `appOL` unLoc $3) } + | decls ';' { LL (unLoc $1) } + | decl { $1 } + | {- empty -} { noLoc nilOL } + + +decllist :: { Located (OrdList (LHsDecl RdrName)) } -- Reversed + : '{' decls '}' { LL (unLoc $2) } + | vocurly decls close { $2 } + +where :: { Located (OrdList (LHsDecl RdrName)) } -- Reversed + -- No implicit parameters + : 'where' decllist { LL (unLoc $2) } + | {- empty -} { noLoc nilOL } + +binds :: { Located (HsLocalBinds RdrName) } -- May have implicit parameters + : decllist { L1 (HsValBinds (cvBindGroup (unLoc $1))) } + | '{' dbinds '}' { LL (HsIPBinds (IPBinds (unLoc $2) emptyLHsBinds)) } + | vocurly dbinds close { L (getLoc $2) (HsIPBinds (IPBinds (unLoc $2) emptyLHsBinds)) } + +wherebinds :: { Located (HsLocalBinds RdrName) } -- May have implicit parameters + : 'where' binds { LL (unLoc $2) } + | {- empty -} { noLoc emptyLocalBinds } + + +----------------------------------------------------------------------------- +-- Transformation Rules + +rules :: { OrdList (LHsDecl RdrName) } -- Reversed + : rules ';' rule { $1 `snocOL` $3 } + | rules ';' { $1 } + | rule { unitOL $1 } + | {- empty -} { nilOL } + +rule :: { LHsDecl RdrName } + : STRING activation rule_forall infixexp '=' exp + { LL $ RuleD (HsRule (getSTRING $1) + ($2 `orElse` AlwaysActive) + $3 $4 placeHolderNames $6 placeHolderNames) } + +activation :: { Maybe Activation } + : {- empty -} { Nothing } + | explicit_activation { Just $1 } + +explicit_activation :: { Activation } -- In brackets + : '[' INTEGER ']' { ActiveAfter (fromInteger (getINTEGER $2)) } + | '[' '~' INTEGER ']' { ActiveBefore (fromInteger (getINTEGER $3)) } + +rule_forall :: { [RuleBndr RdrName] } + : 'forall' rule_var_list '.' { $2 } + | {- empty -} { [] } + +rule_var_list :: { [RuleBndr RdrName] } + : rule_var { [$1] } + | rule_var rule_var_list { $1 : $2 } + +rule_var :: { RuleBndr RdrName } + : varid { RuleBndr $1 } + | '(' varid '::' ctype ')' { RuleBndrSig $2 $4 } + +----------------------------------------------------------------------------- +-- Deprecations (c.f. rules) + +deprecations :: { OrdList (LHsDecl RdrName) } -- Reversed + : deprecations ';' deprecation { $1 `appOL` $3 } + | deprecations ';' { $1 } + | deprecation { $1 } + | {- empty -} { nilOL } + +-- SUP: TEMPORARY HACK, not checking for `module Foo' +deprecation :: { OrdList (LHsDecl RdrName) } + : depreclist STRING + { toOL [ LL $ DeprecD (Deprecation n (getSTRING $2)) + | n <- unLoc $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 :: { LHsDecl RdrName } +fdecl : 'import' callconv safety1 fspec + {% mkImport $2 $3 (unLoc $4) >>= return.LL } + | 'import' callconv fspec + {% do { d <- mkImport $2 (PlaySafe False) (unLoc $3); + return (LL d) } } + | 'export' callconv fspec + {% mkExport $2 (unLoc $3) >>= return.LL } + -- the following syntax is DEPRECATED + | fdecl1DEPRECATED { L1 (ForD (unLoc $1)) } + | fdecl2DEPRECATED { L1 (unLoc $1) } + +fdecl1DEPRECATED :: { LForeignDecl RdrName } +fdecl1DEPRECATED + ----------- DEPRECATED label decls ------------ + : 'label' ext_name varid '::' sigtype + { LL $ ForeignImport $3 $5 (CImport defaultCCallConv (PlaySafe False) nilFS nilFS + (CLabel ($2 `orElse` mkExtName (unLoc $3)))) True } + + ----------- 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 (unLoc $4)) + in + LL $ ForeignImport $4 $6 (CImport defaultCCallConv $3 nilFS nilFS + (CFunction target)) True } + + -- 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 (comb2 $1 $>) "Illegal format of .NET foreign import" + CCall cconv -> return $ + let + imp = CFunction (StaticTarget (getSTRING $4)) + in + LL $ ForeignImport $6 $8 (CImport cconv $5 nilFS nilFS imp) True } + + -- DEPRECATED variant #3: `unsafe' after entity + | 'import' callconv STRING 'unsafe' varid_no_unsafe '::' sigtype + {% case $2 of + DNCall -> parseError (comb2 $1 $>) "Illegal format of .NET foreign import" + CCall cconv -> return $ + let + imp = CFunction (StaticTarget (getSTRING $3)) + in + LL $ ForeignImport $5 $7 (CImport cconv PlayRisky nilFS nilFS imp) True } + + -- DEPRECATED variant #4: use of the special identifier `dynamic' without + -- an explicit calling convention (import) + | 'import' {-no callconv-} 'dynamic' safety varid_no_unsafe '::' sigtype + { LL $ ForeignImport $4 $6 (CImport defaultCCallConv $3 nilFS nilFS + (CFunction DynamicTarget)) True } + + -- DEPRECATED variant #5: use of the special identifier `dynamic' (import) + | 'import' callconv 'dynamic' safety varid_no_unsafe '::' sigtype + {% case $2 of + DNCall -> parseError (comb2 $1 $>) "Illegal format of .NET foreign import" + CCall cconv -> return $ + LL $ ForeignImport $5 $7 (CImport cconv $4 nilFS nilFS + (CFunction DynamicTarget)) True } + + -- DEPRECATED variant #6: lack of a calling convention specification + -- (export) + | 'export' {-no callconv-} ext_name varid '::' sigtype + { LL $ ForeignExport $3 $5 (CExport (CExportStatic ($2 `orElse` mkExtName (unLoc $3)) + defaultCCallConv)) True } + + -- 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 (comb2 $1 $>) "Illegal format of .NET foreign import" + CCall cconv -> return $ + LL $ ForeignExport $5 $7 + (CExport (CExportStatic (getSTRING $4) cconv)) True } + + -- DEPRECATED variant #8: use of the special identifier `dynamic' without + -- an explicit calling convention (export) + | 'export' {-no callconv-} 'dynamic' varid '::' sigtype + { LL $ ForeignImport $3 $5 (CImport defaultCCallConv (PlaySafe False) nilFS nilFS + CWrapper) True } + + -- DEPRECATED variant #9: use of the special identifier `dynamic' (export) + | 'export' callconv 'dynamic' varid '::' sigtype + {% case $2 of + DNCall -> parseError (comb2 $1 $>) "Illegal format of .NET foreign import" + CCall cconv -> return $ + LL $ ForeignImport $4 $6 + (CImport cconv (PlaySafe False) nilFS nilFS CWrapper) True } + + ----------- DEPRECATED .NET decls ------------ + -- NB: removed the .NET call declaration, as it is entirely subsumed + -- by the new standard FFI declarations + +fdecl2DEPRECATED :: { LHsDecl RdrName } +fdecl2DEPRECATED + : 'import' 'dotnet' 'type' ext_name tycon { LL $ TyClD (ForeignType $5 $4 DNType) } + -- 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 :: { 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) } + -- 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 (getSTRING $1) } + | STRING STRING { Just (getSTRING $2) } -- Ignore "module name" for now + | {- empty -} { Nothing } + + +----------------------------------------------------------------------------- +-- Type signatures + +opt_sig :: { Maybe (LHsType RdrName) } + : {- empty -} { Nothing } + | '::' sigtype { Just $2 } + +opt_asig :: { Maybe (LHsType RdrName) } + : {- empty -} { Nothing } + | '::' atype { Just $2 } + +sigtypes1 :: { [LHsType RdrName] } + : sigtype { [ $1 ] } + | sigtype ',' sigtypes1 { $1 : $3 } + +sigtype :: { LHsType RdrName } + : ctype { 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 + +strict_mark :: { Located HsBang } + : '!' { L1 HsStrict } + | '{-# UNPACK' '#-}' '!' { LL HsUnbox } + +-- A ctype is a for-all type +ctype :: { LHsType RdrName } + : 'forall' tv_bndrs '.' ctype { LL $ mkExplicitHsForAllTy $2 (noLoc []) $4 } + | context '=>' type { LL $ mkImplicitHsForAllTy $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 :: { LHsContext RdrName } + : btype {% checkContext $1 } + +type :: { LHsType RdrName } + : ipvar '::' gentype { LL (HsPredTy (HsIParam (unLoc $1) $3)) } + | gentype { $1 } + +gentype :: { LHsType RdrName } + : 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 :: { LHsType RdrName } + : btype atype { LL $ HsAppTy $1 $2 } + | atype { $1 } + +atype :: { LHsType RdrName } + : gtycon { L1 (HsTyVar (unLoc $1)) } + | tyvar { L1 (HsTyVar (unLoc $1)) } + | strict_mark atype { LL (HsBangTy (unLoc $1) $2) } + | '(' ctype ',' comma_types1 ')' { LL $ HsTupleTy Boxed ($2:$4) } + | '(#' comma_types1 '#)' { LL $ HsTupleTy Unboxed $2 } + | '[' ctype ']' { LL $ HsListTy $2 } + | '[:' ctype ':]' { LL $ HsPArrTy $2 } + | '(' ctype ')' { LL $ HsParTy $2 } + | '(' ctype '::' kind ')' { LL $ HsKindSig $2 $4 } +-- Generics + | INTEGER { L1 (HsNumTy (getINTEGER $1)) } + +-- An inst_type is what occurs in the head of an instance decl +-- e.g. (Foo a, Gaz b) => Wibble a b +-- It's kept as a single type, with a MonoDictTy at the right +-- hand corner, for convenience. +inst_type :: { LHsType RdrName } + : sigtype {% checkInstType $1 } + +inst_types1 :: { [LHsType RdrName] } + : inst_type { [$1] } + | inst_type ',' inst_types1 { $1 : $3 } + +comma_types0 :: { [LHsType RdrName] } + : comma_types1 { $1 } + | {- empty -} { [] } + +comma_types1 :: { [LHsType RdrName] } + : ctype { [$1] } + | ctype ',' comma_types1 { $1 : $3 } + +tv_bndrs :: { [LHsTyVarBndr RdrName] } + : tv_bndr tv_bndrs { $1 : $2 } + | {- empty -} { [] } + +tv_bndr :: { LHsTyVarBndr RdrName } + : tyvar { L1 (UserTyVar (unLoc $1)) } + | '(' tyvar '::' kind ')' { LL (KindedTyVar (unLoc $2) $4) } + +fds :: { Located [Located ([RdrName], [RdrName])] } + : {- empty -} { noLoc [] } + | '|' fds1 { LL (reverse (unLoc $2)) } + +fds1 :: { Located [Located ([RdrName], [RdrName])] } + : fds1 ',' fd { LL ($3 : unLoc $1) } + | fd { L1 [$1] } + +fd :: { Located ([RdrName], [RdrName]) } + : varids0 '->' varids0 { L (comb3 $1 $2 $3) + (reverse (unLoc $1), reverse (unLoc $3)) } + +varids0 :: { Located [RdrName] } + : {- empty -} { noLoc [] } + | varids0 tyvar { LL (unLoc $2 : unLoc $1) } + +----------------------------------------------------------------------------- +-- Kinds + +kind :: { Kind } + : akind { $1 } + | akind '->' kind { mkArrowKind $1 $3 } + +akind :: { Kind } + : '*' { liftedTypeKind } + | '(' kind ')' { $2 } + + +----------------------------------------------------------------------------- +-- Datatype declarations + +gadt_constrlist :: { Located [LConDecl RdrName] } + : '{' gadt_constrs '}' { LL (unLoc $2) } + | vocurly gadt_constrs close { $2 } + +gadt_constrs :: { Located [LConDecl RdrName] } + : gadt_constrs ';' gadt_constr { LL ($3 : unLoc $1) } + | gadt_constrs ';' { $1 } + | gadt_constr { L1 [$1] } + +-- We allow the following forms: +-- C :: Eq a => a -> T a +-- C :: forall a. Eq a => !a -> T a +-- D { x,y :: a } :: T a +-- forall a. Eq a => D { x,y :: a } :: T a + +gadt_constr :: { LConDecl RdrName } + : con '::' sigtype + { LL (mkGadtDecl $1 $3) } + -- Syntax: Maybe merge the record stuff with the single-case above? + -- (to kill the mostly harmless reduce/reduce error) + -- XXX revisit autrijus + | constr_stuff_record '::' sigtype + { let (con,details) = unLoc $1 in + LL (ConDecl con Implicit [] (noLoc []) details (ResTyGADT $3)) } +{- + | forall context '=>' constr_stuff_record '::' sigtype + { let (con,details) = unLoc $4 in + LL (ConDecl con Implicit (unLoc $1) $2 details (ResTyGADT $6)) } + | forall constr_stuff_record '::' sigtype + { let (con,details) = unLoc $2 in + LL (ConDecl con Implicit (unLoc $1) (noLoc []) details (ResTyGADT $4)) } +-} + + +constrs :: { Located [LConDecl RdrName] } + : {- empty; a GHC extension -} { noLoc [] } + | '=' constrs1 { LL (unLoc $2) } + +constrs1 :: { Located [LConDecl RdrName] } + : constrs1 '|' constr { LL ($3 : unLoc $1) } + | 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) } + +forall :: { Located [LHsTyVarBndr RdrName] } + : 'forall' tv_bndrs '.' { LL $2 } + | {- empty -} { noLoc [] } + +constr_stuff :: { Located (Located RdrName, HsConDetails RdrName (LBangType RdrName)) } +-- We parse the constructor declaration +-- C t1 t2 +-- as a btype (treating C as a type constructor) and then convert C to be +-- a data constructor. Reason: it might continue like this: +-- C t1 t2 %: D Int +-- in which case C really would be a type constructor. We can't resolve this +-- ambiguity till we come across the constructor oprerator :% (or not, more usually) + : btype {% mkPrefixCon $1 [] >>= return.LL } + | oqtycon '{' '}' {% mkRecCon $1 [] >>= return.LL } + | 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)) } + : 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] } + +fielddecl :: { Located ([Located RdrName], LBangType RdrName) } + : sig_vars '::' ctype { LL (reverse (unLoc $1), $3) } + +-- 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). +-- The 'C [a]' part is converted to an HsPredTy by checkInstType +-- We don't allow a context, but that's sorted out by the type checker. +deriving :: { Located (Maybe [LHsType RdrName]) } + : {- empty -} { noLoc Nothing } + | 'deriving' qtycon {% do { let { L loc tv = $2 } + ; p <- checkInstType (L loc (HsTyVar tv)) + ; return (LL (Just [p])) } } + | 'deriving' '(' ')' { LL (Just []) } + | 'deriving' '(' inst_types1 ')' { LL (Just $3) } + -- Glasgow extension: allow partial + -- applications in derivings + +----------------------------------------------------------------------------- +-- Value definitions + +{- There's an awkward overlap with a type signature. Consider + f :: Int -> Int = ...rhs... + Then we can't tell whether it's a type signature or a value + definition with a result signature until we see the '='. + So we have to inline enough to postpone reductions until we know. +-} + +{- + ATTENTION: Dirty Hackery Ahead! If the second alternative of vars is var + instead of qvar, we get another shift/reduce-conflict. Consider the + following programs: + + { (^^) :: Int->Int ; } Type signature; only var allowed + + { (^^) :: Int->Int = ... ; } Value defn with result signature; + qvar allowed (because of instance decls) + + We can't tell whether to reduce var to qvar until after we've read the signatures. +-} + +decl :: { Located (OrdList (LHsDecl RdrName)) } + : sigdecl { $1 } + | '!' infixexp 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)) } } + +rhs :: { Located (GRHSs RdrName) } + : '=' exp wherebinds { L (comb3 $1 $2 $3) $ GRHSs (unguardedRHS $2) (unLoc $3) } + | gdrhs wherebinds { LL $ GRHSs (reverse (unLoc $1)) (unLoc $2) } + +gdrhs :: { Located [LGRHS RdrName] } + : gdrhs gdrh { LL ($2 : unLoc $1) } + | gdrh { L1 [$1] } + +gdrh :: { LGRHS RdrName } + : '|' quals '=' exp { sL (comb2 $1 $>) $ GRHS (reverse (unLoc $2)) $4 } + +sigdecl :: { Located (OrdList (LHsDecl RdrName)) } + : infixexp '::' sigtype + {% 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 + { 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) + | t <- $4] } + | '{-# SPECIALISE_INLINE' activation qvar '::' sigtypes1 '#-}' + { LL $ toOL [ LL $ SigD (SpecSig $3 t (mkInlineSpec $2 (getSPEC_INLINE $1))) + | t <- $5] } + | '{-# SPECIALISE' 'instance' inst_type '#-}' + { LL $ unitOL (LL $ SigD (SpecInstSig $3)) } + +----------------------------------------------------------------------------- +-- Expressions + +exp :: { LHsExpr RdrName } + : infixexp '::' sigtype { LL $ ExprWithTySig $1 $3 } + | infixexp '-<' exp { LL $ HsArrApp $1 $3 placeHolderType HsFirstOrderApp True } + | infixexp '>-' exp { LL $ HsArrApp $3 $1 placeHolderType HsFirstOrderApp False } + | infixexp '-<<' exp { LL $ HsArrApp $1 $3 placeHolderType HsHigherOrderApp True } + | infixexp '>>-' exp { LL $ HsArrApp $3 $1 placeHolderType HsHigherOrderApp False} + | infixexp { $1 } + +infixexp :: { LHsExpr RdrName } + : exp10 { $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 + )])) } + | '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 } + + | 'do' stmtlist {% let loc = comb2 $1 $2 in + checkDo loc (unLoc $2) >>= \ (stmts,body) -> + return (L loc (mkHsDo DoExpr stmts body)) } + | 'mdo' stmtlist {% let loc = comb2 $1 $2 in + checkDo loc (unLoc $2) >>= \ (stmts,body) -> + return (L loc (mkHsDo (MDoExpr noPostTcTable) stmts body)) } + | scc_annot exp { LL $ if opt_SccProfilingOn + then HsSCC (unLoc $1) $2 + else HsPar $2 } + + | 'proc' aexp '->' exp + {% checkPattern $2 >>= \ p -> + return (LL $ HsProc p (LL $ HsCmdTop $4 [] + placeHolderType undefined)) } + -- TODO: is LL right here? + + | '{-# CORE' STRING '#-}' exp { LL $ HsCoreAnn (getSTRING $2) $4 } + -- hdaume: core annotation + | fexp { $1 } + +scc_annot :: { Located FastString } + : '_scc_' STRING { LL $ getSTRING $2 } + | '{-# SCC' STRING '#-}' { LL $ getSTRING $2 } + +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 :: { LHsExpr RdrName } + : aexp1 '{' fbinds '}' {% do { r <- mkRecConstrOrUpdate $1 (comb2 $2 $4) + (reverse $3); + return (LL r) }} + | aexp2 { $1 } + +-- Here was the syntax for type applications that I was planning +-- but there are difficulties (e.g. what order for type args) +-- so it's not enabled yet. +-- But this case *is* used for the left hand side of a generic definition, +-- which is parsed as an expression before being munged into a pattern + | qcname '{|' gentype '|}' { LL $ HsApp (sL (getLoc $1) (HsVar (unLoc $1))) + (sL (getLoc $3) (HsType $3)) } + +aexp2 :: { LHsExpr RdrName } + : 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) } + | '(' 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 } + + -- MetaHaskell Extension + | TH_ID_SPLICE { L1 $ HsSpliceE (mkHsSplice + (L1 $ HsVar (mkUnqual varName + (getTH_ID_SPLICE $1)))) } -- $x + | '$(' exp ')' { LL $ HsSpliceE (mkHsSplice $2) } -- $( exp ) + + | 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)) } + | TH_TY_QUOTE gtycon { 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)) } + + -- arrow notation extension + | '(|' aexp2 cmdargs '|)' { LL $ HsArrForm $2 Nothing (reverse $3) } + +cmdargs :: { [LHsCmdTop RdrName] } + : cmdargs acmd { $2 : $1 } + | {- empty -} { [] } + +acmd :: { LHsCmdTop RdrName } + : aexp2 { L1 $ HsCmdTop $1 [] placeHolderType undefined } + +cvtopbody :: { [LHsDecl RdrName] } + : '{' cvtopdecls0 '}' { $2 } + | vocurly cvtopdecls0 close { $2 } + +cvtopdecls0 :: { [LHsDecl RdrName] } + : {- empty -} { [] } + | cvtopdecls { $1 } + +texp :: { LHsExpr RdrName } + : exp { $1 } + | qopm infixexp { LL $ SectionR $1 $2 } + -- The second production is really here only for bang patterns + -- but + +texps :: { [LHsExpr RdrName] } + : texps ',' texp { $3 : $1 } + | texp { [$1] } + + +----------------------------------------------------------------------------- +-- List expressions + +-- The rules below are little bit contorted to keep lexps left-recursive while +-- avoiding another shift/reduce-conflict. + +list :: { LHsExpr RdrName } + : texp { L1 $ ExplicitList placeHolderType [$1] } + | lexps { L1 $ ExplicitList placeHolderType (reverse (unLoc $1)) } + | texp '..' { LL $ ArithSeq noPostTcExpr (From $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 } + +lexps :: { Located [LHsExpr RdrName] } + : 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 ] + } + +pquals1 :: { Located [[LStmt RdrName]] } + : pquals1 '|' quals { LL (unLoc $3 : unLoc $1) } + | '|' quals { L (getLoc $2) [unLoc $2] } + +quals :: { Located [LStmt RdrName] } + : quals ',' qual { LL ($3 : unLoc $1) } + | qual { L1 [$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 :: { LHsExpr RdrName } + : { noLoc (ExplicitPArr placeHolderType []) } + | exp { 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 } + +-- We are reusing `lexps' and `pquals' from the list case. + +----------------------------------------------------------------------------- +-- Case alternatives + +altslist :: { Located [LMatch RdrName] } + : '{' alts '}' { LL (reverse (unLoc $2)) } + | vocurly alts close { L (getLoc $2) (reverse (unLoc $2)) } + +alts :: { Located [LMatch RdrName] } + : alts1 { L1 (unLoc $1) } + | ';' alts { LL (unLoc $2) } + +alts1 :: { Located [LMatch RdrName] } + : alts1 ';' alt { LL ($3 : unLoc $1) } + | alts1 ';' { LL (unLoc $1) } + | alt { L1 [$1] } + +alt :: { LMatch RdrName } + : infixexp opt_sig alt_rhs {% checkPattern $1 >>= \p -> + return (LL (Match [p] $2 (unLoc $3))) } + +alt_rhs :: { Located (GRHSs RdrName) } + : ralt wherebinds { LL (GRHSs (unLoc $1) (unLoc $2)) } + +ralt :: { Located [LGRHS RdrName] } + : '->' exp { LL (unguardedRHS $2) } + | gdpats { L1 (reverse (unLoc $1)) } + +gdpats :: { Located [LGRHS RdrName] } + : gdpats gdpat { LL ($2 : unLoc $1) } + | gdpat { L1 [$1] } + +gdpat :: { LGRHS RdrName } + : '|' quals '->' exp { sL (comb2 $1 $>) $ GRHS (reverse (unLoc $2)) $4 } + +----------------------------------------------------------------------------- +-- Statement sequences + +stmtlist :: { Located [LStmt RdrName] } + : '{' stmts '}' { LL (unLoc $2) } + | vocurly stmts close { $2 } + +-- do { ;; s ; s ; ; s ;; } +-- The last Stmt should be an expression, 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 :: { Located [LStmt RdrName] } + : stmt stmts_help { LL ($1 : unLoc $2) } + | ';' stmts { LL (unLoc $2) } + | {- empty -} { noLoc [] } + +stmts_help :: { Located [LStmt RdrName] } -- might be empty + : ';' stmts { LL (unLoc $2) } + | {- empty -} { noLoc [] } + +-- For typing stmts at the GHCi prompt, where +-- the input may consist of just comments. +maybe_stmt :: { Maybe (LStmt RdrName) } + : stmt { Just $1 } + | {- nothing -} { Nothing } + +stmt :: { LStmt RdrName } + : qual { $1 } + | infixexp '->' exp {% checkPattern $3 >>= \p -> + return (LL $ mkBindStmt p $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) } + +----------------------------------------------------------------------------- +-- Record Field Update/Construction + +fbinds :: { HsRecordBinds RdrName } + : fbinds1 { $1 } + | {- empty -} { [] } + +fbinds1 :: { HsRecordBinds RdrName } + : fbinds1 ',' fbind { $3 : $1 } + | fbind { [$1] } + +fbind :: { (Located RdrName, LHsExpr RdrName) } + : qvar '=' exp { ($1,$3) } + +----------------------------------------------------------------------------- +-- Implicit Parameter Bindings + +dbinds :: { Located [LIPBind RdrName] } + : dbinds ';' dbind { LL ($3 : unLoc $1) } + | dbinds ';' { LL (unLoc $1) } + | dbind { L1 [$1] } +-- | {- 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))) } + +----------------------------------------------------------------------------- +-- Deprecations + +depreclist :: { Located [RdrName] } +depreclist : deprec_var { L1 [unLoc $1] } + | deprec_var ',' depreclist { LL (unLoc $1 : unLoc $3) } + +deprec_var :: { Located RdrName } +deprec_var : var { $1 } + | con { $1 } + +----------------------------------------- +-- Data constructors +qcon :: { Located RdrName } + : qconid { $1 } + | '(' qconsym ')' { LL (unLoc $2) } + | sysdcon { L1 $ nameRdrName (dataConName (unLoc $1)) } +-- The case of '[:' ':]' is part of the production `parr' + +con :: { Located RdrName } + : conid { $1 } + | '(' consym ')' { LL (unLoc $2) } + | sysdcon { L1 $ nameRdrName (dataConName (unLoc $1)) } + +sysdcon :: { Located DataCon } -- Wired in data constructors + : '(' ')' { LL unitDataCon } + | '(' commas ')' { LL $ tupleCon Boxed $2 } + | '[' ']' { LL nilDataCon } + +conop :: { Located RdrName } + : consym { $1 } + | '`' conid '`' { LL (unLoc $2) } + +qconop :: { Located RdrName } + : qconsym { $1 } + | '`' qconid '`' { LL (unLoc $2) } + +----------------------------------------------------------------------------- +-- Type constructors + +gtycon :: { Located RdrName } -- A "general" qualified tycon + : oqtycon { $1 } + | '(' ')' { LL $ getRdrName unitTyCon } + | '(' commas ')' { LL $ getRdrName (tupleTyCon Boxed $2) } + | '(' '->' ')' { LL $ getRdrName funTyCon } + | '[' ']' { LL $ listTyCon_RDR } + | '[:' ':]' { LL $ parrTyCon_RDR } + +oqtycon :: { Located RdrName } -- An "ordinary" qualified tycon + : qtycon { $1 } + | '(' qtyconsym ')' { LL (unLoc $2) } + +qtyconop :: { Located RdrName } -- Qualified or unqualified + : qtyconsym { $1 } + | '`' qtycon '`' { LL (unLoc $2) } + +qtycon :: { Located RdrName } -- Qualified or unqualified + : QCONID { L1 $! mkQual tcClsName (getQCONID $1) } + | tycon { $1 } + +tycon :: { Located RdrName } -- Unqualified + : CONID { L1 $! mkUnqual tcClsName (getCONID $1) } + +qtyconsym :: { Located RdrName } + : QCONSYM { L1 $! mkQual tcClsName (getQCONSYM $1) } + | tyconsym { $1 } + +tyconsym :: { Located RdrName } + : CONSYM { L1 $! mkUnqual tcClsName (getCONSYM $1) } + +----------------------------------------------------------------------------- +-- Operators + +op :: { Located RdrName } -- used in infix decls + : varop { $1 } + | conop { $1 } + +varop :: { Located RdrName } + : varsym { $1 } + | '`' varid '`' { LL (unLoc $2) } + +qop :: { LHsExpr RdrName } -- used in sections + : qvarop { L1 $ HsVar (unLoc $1) } + | qconop { L1 $ HsVar (unLoc $1) } + +qopm :: { LHsExpr RdrName } -- used in sections + : qvaropm { L1 $ HsVar (unLoc $1) } + | qconop { L1 $ HsVar (unLoc $1) } + +qvarop :: { Located RdrName } + : qvarsym { $1 } + | '`' qvarid '`' { LL (unLoc $2) } + +qvaropm :: { Located RdrName } + : qvarsym_no_minus { $1 } + | '`' qvarid '`' { LL (unLoc $2) } + +----------------------------------------------------------------------------- +-- Type variables + +tyvar :: { Located RdrName } +tyvar : tyvarid { $1 } + | '(' tyvarsym ')' { LL (unLoc $2) } + +tyvarop :: { Located RdrName } +tyvarop : '`' tyvarid '`' { LL (unLoc $2) } + | tyvarsym { $1 } + +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") } + +tyvarsym :: { Located RdrName } +-- Does not include "!", because that is used for strictness marks +-- or ".", because that separates the quantified type vars from the rest +-- or "*", because that's used for kinds +tyvarsym : VARSYM { L1 $! mkUnqual tvName (getVARSYM $1) } + +----------------------------------------------------------------------------- +-- Variables + +var :: { Located RdrName } + : varid { $1 } + | '(' varsym ')' { LL (unLoc $2) } + +qvar :: { Located RdrName } + : qvarid { $1 } + | '(' varsym ')' { LL (unLoc $2) } + | '(' qvarsym1 ')' { LL (unLoc $2) } +-- We've inlined qvarsym here so that the decision about +-- whether it's a qvar or a var can be postponed until +-- *after* we see the close paren. + +qvarid :: { Located RdrName } + : varid { $1 } + | QVARID { L1 $ mkQual varName (getQVARID $1) } + +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") } + +varid_no_unsafe :: { Located RdrName } + : VARID { L1 $! mkUnqual varName (getVARID $1) } + | special_id { L1 $! mkUnqual varName (unLoc $1) } + | 'forall' { L1 $! mkUnqual varName FSLIT("forall") } + +qvarsym :: { Located RdrName } + : varsym { $1 } + | qvarsym1 { $1 } + +qvarsym_no_minus :: { Located RdrName } + : varsym_no_minus { $1 } + | qvarsym1 { $1 } + +qvarsym1 :: { Located RdrName } +qvarsym1 : QVARSYM { L1 $ mkQual varName (getQVARSYM $1) } + +varsym :: { Located RdrName } + : varsym_no_minus { $1 } + | '-' { L1 $ mkUnqual varName FSLIT("-") } + +varsym_no_minus :: { Located RdrName } -- varsym not including '-' + : VARSYM { L1 $ mkUnqual varName (getVARSYM $1) } + | special_sym { L1 $ mkUnqual varName (unLoc $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 +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") } + +special_sym :: { Located FastString } +special_sym : '!' { L1 FSLIT("!") } + | '.' { L1 FSLIT(".") } + | '*' { L1 FSLIT("*") } + +----------------------------------------------------------------------------- +-- Data constructors + +qconid :: { Located RdrName } -- Qualified or unqualified + : conid { $1 } + | QCONID { L1 $ mkQual dataName (getQCONID $1) } + +conid :: { Located RdrName } + : CONID { L1 $ mkUnqual dataName (getCONID $1) } + +qconsym :: { Located RdrName } -- Qualified or unqualified + : consym { $1 } + | QCONSYM { L1 $ mkQual dataName (getQCONSYM $1) } + +consym :: { Located RdrName } + : CONSYM { L1 $ mkUnqual dataName (getCONSYM $1) } + + -- ':' means only list cons + | ':' { L1 $ consDataCon_RDR } + + +----------------------------------------------------------------------------- +-- Literals + +literal :: { Located HsLit } + : CHAR { L1 $ HsChar $ getCHAR $1 } + | STRING { L1 $ HsString $ getSTRING $1 } + | PRIMINTEGER { L1 $ HsIntPrim $ getPRIMINTEGER $1 } + | PRIMCHAR { L1 $ HsCharPrim $ getPRIMCHAR $1 } + | PRIMSTRING { L1 $ HsStringPrim $ getPRIMSTRING $1 } + | PRIMFLOAT { L1 $ HsFloatPrim $ getPRIMFLOAT $1 } + | PRIMDOUBLE { L1 $ HsDoublePrim $ getPRIMDOUBLE $1 } + +----------------------------------------------------------------------------- +-- Layout + +close :: { () } + : vccurly { () } -- context popped in lexer. + | error {% popContext } + +----------------------------------------------------------------------------- +-- Miscellaneous (mostly renamings) + +modid :: { Located Module } + : CONID { L1 $ mkModuleFS (getCONID $1) } + | QCONID { L1 $ let (mod,c) = getQCONID $1 in + mkModuleFS + (mkFastString + (unpackFS mod ++ '.':unpackFS c)) + } + +commas :: { Int } + : commas ',' { $1 + 1 } + | ',' { 2 } + +----------------------------------------------------------------------------- + +{ +happyError :: P a +happyError = srcParseFail + +getVARID (L _ (ITvarid x)) = x +getCONID (L _ (ITconid x)) = x +getVARSYM (L _ (ITvarsym x)) = x +getCONSYM (L _ (ITconsym x)) = x +getQVARID (L _ (ITqvarid x)) = x +getQCONID (L _ (ITqconid x)) = x +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 +getRATIONAL (L _ (ITrational x)) = x +getPRIMCHAR (L _ (ITprimchar x)) = x +getPRIMSTRING (L _ (ITprimstring x)) = x +getPRIMINTEGER (L _ (ITprimint 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 + +-- Utilities for combining source spans +comb2 :: Located a -> Located b -> SrcSpan +comb2 = combineLocs + +comb3 :: Located a -> Located b -> Located c -> SrcSpan +comb3 a b c = 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) + +-- strict constructor version: +{-# INLINE sL #-} +sL :: SrcSpan -> a -> Located a +sL span a = span `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 +-- try to find the span of the whole file (ToDo). +fileSrcSpan :: P SrcSpan +fileSrcSpan = do + l <- getSrcLoc; + let loc = mkSrcLoc (srcLocFile l) 1 0; + return (mkSrcSpan loc loc) +} |