diff options
Diffstat (limited to 'compiler/GHC/Parser.y')
-rw-r--r-- | compiler/GHC/Parser.y | 4131 |
1 files changed, 4131 insertions, 0 deletions
diff --git a/compiler/GHC/Parser.y b/compiler/GHC/Parser.y new file mode 100644 index 0000000000..90b23f7ca6 --- /dev/null +++ b/compiler/GHC/Parser.y @@ -0,0 +1,4131 @@ +-- -*-haskell-*- +-- --------------------------------------------------------------------------- +-- (c) The University of Glasgow 1997-2003 +--- +-- The GHC grammar. +-- +-- Author(s): Simon Marlow, Sven Panne 1997, 1998, 1999 +-- --------------------------------------------------------------------------- + +{ +{-# LANGUAGE ViewPatterns #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE RankNTypes #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE ScopedTypeVariables #-} + +-- | This module provides the generated Happy parser for Haskell. It exports +-- a number of parsers which may be used in any library that uses the GHC API. +-- A common usage pattern is to initialize the parser state with a given string +-- and then parse that string: +-- +-- @ +-- runParser :: DynFlags -> String -> P a -> ParseResult a +-- runParser flags str parser = unP parser parseState +-- where +-- filename = "\<interactive\>" +-- location = mkRealSrcLoc (mkFastString filename) 1 1 +-- buffer = stringToStringBuffer str +-- parseState = mkPState flags buffer location +-- @ +module GHC.Parser + ( parseModule, parseSignature, parseImport, parseStatement, parseBackpack + , parseDeclaration, parseExpression, parsePattern + , parseTypeSignature + , parseStmt, parseIdentifier + , parseType, parseHeader + ) +where + +-- base +import Control.Monad ( unless, liftM, when, (<=<) ) +import GHC.Exts +import Data.Char +import Data.Maybe ( maybeToList ) +import Control.Monad ( mplus ) +import Control.Applicative ((<$)) +import qualified Prelude + +-- compiler +import GHC.Hs + +import GHC.Driver.Phases ( HscSource(..) ) +import GHC.Driver.Types ( IsBootInterface, WarningTxt(..) ) +import GHC.Driver.Session +import GHC.Driver.Backpack.Syntax +import UnitInfo + +-- compiler/utils +import OrdList +import BooleanFormula ( BooleanFormula(..), LBooleanFormula(..), mkTrue ) +import FastString +import Maybes ( isJust, orElse ) +import Outputable +import Util ( looksLikePackageName, fstOf3, sndOf3, thdOf3 ) +import GhcPrelude + +-- compiler/basicTypes +import GHC.Types.Name.Reader +import GHC.Types.Name.Occurrence ( varName, dataName, tcClsName, tvName, startsWithUnderscore ) +import GHC.Core.DataCon ( DataCon, dataConName ) +import GHC.Types.SrcLoc +import GHC.Types.Module +import GHC.Types.Basic +import GHC.Types.ForeignCall + +import GHC.Core.Type ( funTyCon ) +import GHC.Core.Class ( FunDep ) + +-- compiler/parser +import GHC.Parser.PostProcess +import GHC.Parser.PostProcess.Haddock +import GHC.Parser.Lexer +import GHC.Parser.Annotation + +import GHC.Tc.Types.Evidence ( emptyTcEvBinds ) + +-- compiler/prelude +import GHC.Builtin.Types.Prim ( eqPrimTyCon ) +import GHC.Builtin.Types ( unitTyCon, unitDataCon, tupleTyCon, tupleDataCon, nilDataCon, + unboxedUnitTyCon, unboxedUnitDataCon, + listTyCon_RDR, consDataCon_RDR, eqTyCon_RDR ) +} + +%expect 232 -- shift/reduce conflicts + +{- Last updated: 04 June 2018 + +If you modify this parser and add a conflict, please update this comment. +You can learn more about the conflicts by passing 'happy' the -i flag: + + happy -agc --strict compiler/GHC/Parser.y -idetailed-info + +How is this section formatted? Look up the state the conflict is +reported at, and copy the list of applicable rules (at the top, without the +rule numbers). Mark *** for the rule that is the conflicting reduction (that +is, the interpretation which is NOT taken). NB: Happy doesn't print a rule +in a state if it is empty, but you should include it in the list (you can +look these up in the Grammar section of the info file). + +Obviously the state numbers are not stable across modifications to the parser, +the idea is to reproduce enough information on each conflict so you can figure +out what happened if the states were renumbered. Try not to gratuitously move +productions around in this file. + +------------------------------------------------------------------------------- + +state 0 contains 1 shift/reduce conflicts. + + Conflicts: DOCNEXT (empty missing_module_keyword reduces) + +Ambiguity when the source file starts with "-- | doc". We need another +token of lookahead to determine if a top declaration or the 'module' keyword +follows. Shift parses as if the 'module' keyword follows. + +------------------------------------------------------------------------------- + +state 60 contains 1 shift/reduce conflict. + + context -> btype . + *** type -> btype . + type -> btype . '->' ctype + + Conflicts: '->' + +------------------------------------------------------------------------------- + +state 61 contains 47 shift/reduce conflicts. + + *** btype -> tyapps . + tyapps -> tyapps . tyapp + + Conflicts: '_' ':' '~' '!' '.' '`' '{' '[' '(' '(#' '`' TYPEAPP + SIMPLEQUOTE VARID CONID VARSYM CONSYM QCONID QVARSYM QCONSYM + STRING INTEGER TH_ID_SPLICE '$(' TH_QUASIQUOTE TH_QQUASIQUOTE + and all the special ids. + +Example ambiguity: + 'if x then y else z :: F a' + +Shift parses as (per longest-parse rule): + 'if x then y else z :: (F a)' + +------------------------------------------------------------------------------- + +state 143 contains 15 shift/reduce conflicts. + + exp -> infixexp . '::' sigtype + exp -> infixexp . '-<' exp + exp -> infixexp . '>-' exp + exp -> infixexp . '-<<' exp + exp -> infixexp . '>>-' exp + *** exp -> infixexp . + infixexp -> infixexp . qop exp10 + + Conflicts: ':' '::' '-' '!' '-<' '>-' '-<<' '>>-' + '.' '`' '*' VARSYM CONSYM QVARSYM QCONSYM + +Examples of ambiguity: + 'if x then y else z -< e' + 'if x then y else z :: T' + 'if x then y else z + 1' (NB: '+' is in VARSYM) + +Shift parses as (per longest-parse rule): + 'if x then y else (z -< T)' + 'if x then y else (z :: T)' + 'if x then y else (z + 1)' + +------------------------------------------------------------------------------- + +state 148 contains 67 shift/reduce conflicts. + + *** exp10 -> fexp . + fexp -> fexp . aexp + fexp -> fexp . TYPEAPP atype + + Conflicts: TYPEAPP and all the tokens that can start an aexp + +Examples of ambiguity: + 'if x then y else f z' + 'if x then y else f @ z' + +Shift parses as (per longest-parse rule): + 'if x then y else (f z)' + 'if x then y else (f @ z)' + +------------------------------------------------------------------------------- + +state 203 contains 27 shift/reduce conflicts. + + aexp2 -> TH_TY_QUOTE . tyvar + aexp2 -> TH_TY_QUOTE . gtycon + *** aexp2 -> TH_TY_QUOTE . + + Conflicts: two single quotes is error syntax with specific error message. + +Example of ambiguity: + 'x = ''' + 'x = ''a' + 'x = ''T' + +Shift parses as (per longest-parse rule): + 'x = ''a' + 'x = ''T' + +------------------------------------------------------------------------------- + +state 299 contains 1 shift/reduce conflicts. + + rule -> STRING . rule_activation rule_forall infixexp '=' exp + + Conflict: '[' (empty rule_activation reduces) + +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 + +Example ambiguity: + '{-# RULE [0] f = ... #-}' + +We parse this as having a [0] rule activation for rewriting 'f', rather +a rule instructing how to rewrite the expression '[0] f'. + +------------------------------------------------------------------------------- + +state 309 contains 1 shift/reduce conflict. + + *** type -> btype . + type -> btype . '->' ctype + + Conflict: '->' + +Same as state 61 but without contexts. + +------------------------------------------------------------------------------- + +state 353 contains 1 shift/reduce conflicts. + + tup_exprs -> commas . tup_tail + sysdcon_nolist -> '(' commas . ')' + commas -> commas . ',' + + Conflict: ')' (empty tup_tail reduces) + +A tuple section with NO free variables '(,,)' is indistinguishable +from the Haskell98 data constructor for a tuple. Shift resolves in +favor of sysdcon, which is good because a tuple section will get rejected +if -XTupleSections is not specified. + +See also Note [ExplicitTuple] in GHC.Hs.Expr. + +------------------------------------------------------------------------------- + +state 408 contains 1 shift/reduce conflicts. + + tup_exprs -> commas . tup_tail + sysdcon_nolist -> '(#' commas . '#)' + commas -> commas . ',' + + Conflict: '#)' (empty tup_tail reduces) + +Same as State 354 for unboxed tuples. + +------------------------------------------------------------------------------- + +state 416 contains 67 shift/reduce conflicts. + + *** exp10 -> '-' fexp . + fexp -> fexp . aexp + fexp -> fexp . TYPEAPP atype + +Same as 149 but with a unary minus. + +------------------------------------------------------------------------------- + +state 481 contains 1 shift/reduce conflict. + + oqtycon -> '(' qtyconsym . ')' + *** qtyconop -> qtyconsym . + + Conflict: ')' + +Example ambiguity: 'foo :: (:%)' + +Shift means '(:%)' gets parsed as a type constructor, rather than than a +parenthesized infix type expression of length 1. + +------------------------------------------------------------------------------- + +state 678 contains 1 shift/reduce conflicts. + + *** aexp2 -> ipvar . + dbind -> ipvar . '=' exp + + Conflict: '=' + +Example ambiguity: 'let ?x ...' + +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. + +------------------------------------------------------------------------------- + +state 756 contains 1 shift/reduce conflicts. + + rule -> STRING rule_activation . rule_forall infixexp '=' exp + + Conflict: 'forall' (empty rule_forall reduces) + +Example ambiguity: '{-# RULES "name" forall = ... #-}' + +'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'. + +------------------------------------------------------------------------------- + +state 992 contains 1 shift/reduce conflicts. + + transformqual -> 'then' 'group' . 'using' exp + transformqual -> 'then' 'group' . 'by' exp 'using' exp + *** special_id -> 'group' . + + Conflict: 'by' + +------------------------------------------------------------------------------- + +state 1089 contains 1 shift/reduce conflicts. + + rule_foralls -> 'forall' rule_vars '.' . 'forall' rule_vars '.' + *** rule_foralls -> 'forall' rule_vars '.' . + + Conflict: 'forall' + +Example ambiguity: '{-# RULES "name" forall a. forall ... #-}' + +Here the parser cannot tell whether the second 'forall' is the beginning of +a term-level quantifier, for example: + +'{-# RULES "name" forall a. forall x. id @a x = x #-}' + +or a valid variable named 'forall', for example a function @:: Int -> Int@ + +'{-# RULES "name" forall a. forall 0 = 0 #-}' + +Shift means the parser only allows the former. Also see conflict 753 above. + +------------------------------------------------------------------------------- + +state 1390 contains 1 shift/reduce conflict. + + *** atype -> tyvar . + tv_bndr -> '(' tyvar . '::' kind ')' + + Conflict: '::' + +Example ambiguity: 'class C a where type D a = ( a :: * ...' + +Here the parser cannot tell whether this is specifying a default for the +associated type like: + +'class C a where type D a = ( a :: * ); type D a' + +or it is an injectivity signature like: + +'class C a where type D a = ( r :: * ) | r -> a' + +Shift means the parser only allows the latter. + +------------------------------------------------------------------------------- +-- API Annotations +-- + +A lot of the productions are now cluttered with calls to +aa,am,ams,amms etc. + +These are helper functions to make sure that the locations of the +various keywords such as do / let / in are captured for use by tools +that want to do source to source conversions, such as refactorers or +structured editors. + +The helper functions are defined at the bottom of this file. + +See + https://gitlab.haskell.org/ghc/ghc/wikis/api-annotations and + https://gitlab.haskell.org/ghc/ghc/wikis/ghc-ast-annotations +for some background. + +If you modify the parser and want to ensure that the API annotations are processed +correctly, see the README in (REPO)/utils/check-api-annotations for details on +how to set up a test using the check-api-annotations utility, and interpret the +output it generates. + +Note [Parsing lists] +--------------------- +You might be wondering why we spend so much effort encoding our lists this +way: + +importdecls + : importdecls ';' importdecl + | importdecls ';' + | importdecl + | {- empty -} + +This might seem like an awfully roundabout way to declare a list; plus, to add +insult to injury you have to reverse the results at the end. The answer is that +left recursion prevents us from running out of stack space when parsing long +sequences. See: https://www.haskell.org/happy/doc/html/sec-sequences.html for +more guidance. + +By adding/removing branches, you can affect what lists are accepted. Here +are the most common patterns, rewritten as regular expressions for clarity: + + -- Equivalent to: ';'* (x ';'+)* x? (can be empty, permits leading/trailing semis) + xs : xs ';' x + | xs ';' + | x + | {- empty -} + + -- Equivalent to x (';' x)* ';'* (non-empty, permits trailing semis) + xs : xs ';' x + | xs ';' + | x + + -- Equivalent to ';'* alts (';' alts)* ';'* (non-empty, permits leading/trailing semis) + alts : alts1 + | ';' alts + alts1 : alts1 ';' alt + | alts1 ';' + | alt + + -- Equivalent to x (',' x)+ (non-empty, no trailing semis) + xs : x + | x ',' xs + +-- ----------------------------------------------------------------------------- + +-} + +%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 } + + 'forall' { L _ (ITforall _) } -- GHC extension keywords + 'foreign' { L _ ITforeign } + 'export' { L _ ITexport } + 'label' { L _ ITlabel } + 'dynamic' { L _ ITdynamic } + 'safe' { L _ ITsafe } + 'interruptible' { L _ ITinterruptible } + 'unsafe' { L _ ITunsafe } + 'mdo' { L _ ITmdo } + 'family' { L _ ITfamily } + 'role' { L _ ITrole } + 'stdcall' { L _ ITstdcallconv } + 'ccall' { L _ ITccallconv } + 'capi' { L _ ITcapiconv } + 'prim' { L _ ITprimcallconv } + 'javascript' { L _ ITjavascriptcallconv } + 'proc' { L _ ITproc } -- for arrow notation extension + 'rec' { L _ ITrec } -- for arrow notation extension + 'group' { L _ ITgroup } -- for list transform extension + 'by' { L _ ITby } -- for list transform extension + 'using' { L _ ITusing } -- for list transform extension + 'pattern' { L _ ITpattern } -- for pattern synonyms + 'static' { L _ ITstatic } -- for static pointers extension + 'stock' { L _ ITstock } -- for DerivingStrategies extension + 'anyclass' { L _ ITanyclass } -- for DerivingStrategies extension + 'via' { L _ ITvia } -- for DerivingStrategies extension + + 'unit' { L _ ITunit } + 'signature' { L _ ITsignature } + 'dependency' { L _ ITdependency } + + '{-# INLINE' { L _ (ITinline_prag _ _ _) } -- INLINE or INLINABLE + '{-# 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 _)} + '{-# GENERATED' { L _ (ITgenerated_prag _) } + '{-# DEPRECATED' { L _ (ITdeprecated_prag _) } + '{-# WARNING' { L _ (ITwarning_prag _) } + '{-# UNPACK' { L _ (ITunpack_prag _) } + '{-# NOUNPACK' { L _ (ITnounpack_prag _) } + '{-# ANN' { L _ (ITann_prag _) } + '{-# MINIMAL' { L _ (ITminimal_prag _) } + '{-# CTYPE' { L _ (ITctype _) } + '{-# OVERLAPPING' { L _ (IToverlapping_prag _) } + '{-# OVERLAPPABLE' { L _ (IToverlappable_prag _) } + '{-# OVERLAPS' { L _ (IToverlaps_prag _) } + '{-# INCOHERENT' { L _ (ITincoherent_prag _) } + '{-# COMPLETE' { L _ (ITcomplete_prag _) } + '#-}' { L _ ITclose_prag } + + '..' { L _ ITdotdot } -- reserved symbols + ':' { L _ ITcolon } + '::' { L _ (ITdcolon _) } + '=' { L _ ITequal } + '\\' { L _ ITlam } + 'lcase' { L _ ITlcase } + '|' { L _ ITvbar } + '<-' { L _ (ITlarrow _) } + '->' { L _ (ITrarrow _) } + TIGHT_INFIX_AT { L _ ITat } + '=>' { L _ (ITdarrow _) } + '-' { L _ ITminus } + PREFIX_TILDE { L _ ITtilde } + PREFIX_BANG { 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 } + PREFIX_AT { L _ ITtypeApp } + + '{' { L _ ITocurly } -- special symbols + '}' { L _ ITccurly } + vocurly { L _ ITvocurly } -- virtual open curly (from layout) + vccurly { L _ ITvccurly } -- virtual close curly (from layout) + '[' { L _ ITobrack } + ']' { L _ ITcbrack } + '(' { L _ IToparen } + ')' { L _ ITcparen } + '(#' { L _ IToubxparen } + '#)' { L _ ITcubxparen } + '(|' { L _ (IToparenbar _) } + '|)' { L _ (ITcparenbar _) } + ';' { L _ ITsemi } + ',' { L _ ITcomma } + '`' { L _ ITbackquote } + SIMPLEQUOTE { L _ ITsimpleQuote } -- 'x + + 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 + LABELVARID { L _ (ITlabelvarid _) } + + CHAR { L _ (ITchar _ _) } + STRING { L _ (ITstring _ _) } + INTEGER { L _ (ITinteger _) } + RATIONAL { L _ (ITrational _) } + + PRIMCHAR { L _ (ITprimchar _ _) } + PRIMSTRING { L _ (ITprimstring _ _) } + PRIMINTEGER { L _ (ITprimint _ _) } + PRIMWORD { L _ (ITprimword _ _) } + PRIMFLOAT { L _ (ITprimfloat _) } + PRIMDOUBLE { L _ (ITprimdouble _) } + + DOCNEXT { L _ (ITdocCommentNext _) } + DOCPREV { L _ (ITdocCommentPrev _) } + DOCNAMED { L _ (ITdocCommentNamed _) } + DOCSECTION { L _ (ITdocSection _ _) } + +-- Template Haskell +'[|' { L _ (ITopenExpQuote _ _) } +'[p|' { L _ ITopenPatQuote } +'[t|' { L _ ITopenTypQuote } +'[d|' { L _ ITopenDecQuote } +'|]' { L _ (ITcloseQuote _) } +'[||' { L _ (ITopenTExpQuote _) } +'||]' { L _ ITcloseTExpQuote } +PREFIX_DOLLAR { L _ ITdollar } +PREFIX_DOLLAR_DOLLAR { L _ ITdollardollar } +TH_TY_QUOTE { L _ ITtyQuote } -- ''T +TH_QUASIQUOTE { L _ (ITquasiQuote _) } +TH_QQUASIQUOTE { L _ (ITqQuasiQuote _) } + +%monad { P } { >>= } { return } +%lexer { (lexer True) } { L _ ITeof } + -- Replace 'lexer' above with 'lexerDbg' + -- to dump the tokens fed to the parser. +%tokentype { (Located Token) } + +-- Exported parsers +%name parseModule module +%name parseSignature signature +%name parseImport importdecl +%name parseStatement e_stmt +%name parseDeclaration topdecl +%name parseExpression exp +%name parsePattern pat +%name parseTypeSignature sigdecl +%name parseStmt maybe_stmt +%name parseIdentifier identifier +%name parseType ktype +%name parseBackpack backpack +%partial parseHeader header +%% + +----------------------------------------------------------------------------- +-- Identifiers; one of the entry points +identifier :: { Located RdrName } + : qvar { $1 } + | qcon { $1 } + | qvarop { $1 } + | qconop { $1 } + | '(' '->' ')' {% ams (sLL $1 $> $ getRdrName funTyCon) + [mop $1,mu AnnRarrow $2,mcp $3] } + +----------------------------------------------------------------------------- +-- Backpack stuff + +backpack :: { [LHsUnit PackageName] } + : implicit_top units close { fromOL $2 } + | '{' units '}' { fromOL $2 } + +units :: { OrdList (LHsUnit PackageName) } + : units ';' unit { $1 `appOL` unitOL $3 } + | units ';' { $1 } + | unit { unitOL $1 } + +unit :: { LHsUnit PackageName } + : 'unit' pkgname 'where' unitbody + { sL1 $1 $ HsUnit { hsunitName = $2 + , hsunitBody = fromOL $4 } } + +unitid :: { LHsUnitId PackageName } + : pkgname { sL1 $1 $ HsUnitId $1 [] } + | pkgname '[' msubsts ']' { sLL $1 $> $ HsUnitId $1 (fromOL $3) } + +msubsts :: { OrdList (LHsModuleSubst PackageName) } + : msubsts ',' msubst { $1 `appOL` unitOL $3 } + | msubsts ',' { $1 } + | msubst { unitOL $1 } + +msubst :: { LHsModuleSubst PackageName } + : modid '=' moduleid { sLL $1 $> $ ($1, $3) } + | modid VARSYM modid VARSYM { sLL $1 $> $ ($1, sLL $2 $> $ HsModuleVar $3) } + +moduleid :: { LHsModuleId PackageName } + : VARSYM modid VARSYM { sLL $1 $> $ HsModuleVar $2 } + | unitid ':' modid { sLL $1 $> $ HsModuleId $1 $3 } + +pkgname :: { Located PackageName } + : STRING { sL1 $1 $ PackageName (getSTRING $1) } + | litpkgname { sL1 $1 $ PackageName (unLoc $1) } + +litpkgname_segment :: { Located FastString } + : VARID { sL1 $1 $ getVARID $1 } + | CONID { sL1 $1 $ getCONID $1 } + | special_id { $1 } + +litpkgname :: { Located FastString } + : litpkgname_segment { $1 } + -- a bit of a hack, means p - b is parsed same as p-b, enough for now. + | litpkgname_segment '-' litpkgname { sLL $1 $> $ appendFS (unLoc $1) (consFS '-' (unLoc $3)) } + +mayberns :: { Maybe [LRenaming] } + : {- empty -} { Nothing } + | '(' rns ')' { Just (fromOL $2) } + +rns :: { OrdList LRenaming } + : rns ',' rn { $1 `appOL` unitOL $3 } + | rns ',' { $1 } + | rn { unitOL $1 } + +rn :: { LRenaming } + : modid 'as' modid { sLL $1 $> $ Renaming $1 (Just $3) } + | modid { sL1 $1 $ Renaming $1 Nothing } + +unitbody :: { OrdList (LHsUnitDecl PackageName) } + : '{' unitdecls '}' { $2 } + | vocurly unitdecls close { $2 } + +unitdecls :: { OrdList (LHsUnitDecl PackageName) } + : unitdecls ';' unitdecl { $1 `appOL` unitOL $3 } + | unitdecls ';' { $1 } + | unitdecl { unitOL $1 } + +unitdecl :: { LHsUnitDecl PackageName } + : maybedocheader 'module' maybe_src modid maybemodwarning maybeexports 'where' body + -- XXX not accurate + { sL1 $2 $ DeclD + (case snd $3 of + False -> HsSrcFile + True -> HsBootFile) + $4 + (Just $ sL1 $2 (HsModule (Just $4) $6 (fst $ snd $8) (snd $ snd $8) $5 $1)) } + | maybedocheader 'signature' modid maybemodwarning maybeexports 'where' body + { sL1 $2 $ DeclD + HsigFile + $3 + (Just $ sL1 $2 (HsModule (Just $3) $5 (fst $ snd $7) (snd $ snd $7) $4 $1)) } + -- NB: MUST have maybedocheader here, otherwise shift-reduce conflict + -- will prevent us from parsing both forms. + | maybedocheader 'module' maybe_src modid + { sL1 $2 $ DeclD (case snd $3 of + False -> HsSrcFile + True -> HsBootFile) $4 Nothing } + | maybedocheader 'signature' modid + { sL1 $2 $ DeclD HsigFile $3 Nothing } + | 'dependency' unitid mayberns + { sL1 $1 $ IncludeD (IncludeDecl { idUnitId = $2 + , idModRenaming = $3 + , idSignatureInclude = False }) } + | 'dependency' 'signature' unitid + { sL1 $1 $ IncludeD (IncludeDecl { idUnitId = $3 + , idModRenaming = Nothing + , idSignatureInclude = True }) } + +----------------------------------------------------------------------------- +-- 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. :-) + +signature :: { Located HsModule } + : maybedocheader 'signature' modid maybemodwarning maybeexports 'where' body + {% fileSrcSpan >>= \ loc -> + ams (L loc (HsModule (Just $3) $5 (fst $ snd $7) + (snd $ snd $7) $4 $1) + ) + ([mj AnnSignature $2, mj AnnWhere $6] ++ fst $7) } + +module :: { Located HsModule } + : maybedocheader 'module' modid maybemodwarning maybeexports 'where' body + {% fileSrcSpan >>= \ loc -> + ams (L loc (HsModule (Just $3) $5 (fst $ snd $7) + (snd $ snd $7) $4 $1) + ) + ([mj AnnModule $2, mj AnnWhere $6] ++ fst $7) } + | body2 + {% fileSrcSpan >>= \ loc -> + ams (L loc (HsModule Nothing Nothing + (fst $ snd $1) (snd $ snd $1) Nothing Nothing)) + (fst $1) } + +maybedocheader :: { Maybe LHsDocString } + : moduleheader { $1 } + | {- empty -} { Nothing } + +missing_module_keyword :: { () } + : {- empty -} {% pushModuleContext } + +implicit_top :: { () } + : {- empty -} {% pushModuleContext } + +maybemodwarning :: { Maybe (Located WarningTxt) } + : '{-# DEPRECATED' strings '#-}' + {% ajs (sLL $1 $> $ DeprecatedTxt (sL1 $1 (getDEPRECATED_PRAGs $1)) (snd $ unLoc $2)) + (mo $1:mc $3: (fst $ unLoc $2)) } + | '{-# WARNING' strings '#-}' + {% ajs (sLL $1 $> $ WarningTxt (sL1 $1 (getWARNING_PRAGs $1)) (snd $ unLoc $2)) + (mo $1:mc $3 : (fst $ unLoc $2)) } + | {- empty -} { Nothing } + +body :: { ([AddAnn] + ,([LImportDecl GhcPs], [LHsDecl GhcPs])) } + : '{' top '}' { (moc $1:mcc $3:(fst $2) + , snd $2) } + | vocurly top close { (fst $2, snd $2) } + +body2 :: { ([AddAnn] + ,([LImportDecl GhcPs], [LHsDecl GhcPs])) } + : '{' top '}' { (moc $1:mcc $3 + :(fst $2), snd $2) } + | missing_module_keyword top close { ([],snd $2) } + + +top :: { ([AddAnn] + ,([LImportDecl GhcPs], [LHsDecl GhcPs])) } + : semis top1 { ($1, $2) } + +top1 :: { ([LImportDecl GhcPs], [LHsDecl GhcPs]) } + : importdecls_semi topdecls_semi { (reverse $1, cvTopDecls $2) } + | importdecls_semi topdecls { (reverse $1, cvTopDecls $2) } + | importdecls { (reverse $1, []) } + +----------------------------------------------------------------------------- +-- Module declaration & imports only + +header :: { Located HsModule } + : maybedocheader 'module' modid maybemodwarning maybeexports 'where' header_body + {% fileSrcSpan >>= \ loc -> + ams (L loc (HsModule (Just $3) $5 $7 [] $4 $1 + )) [mj AnnModule $2,mj AnnWhere $6] } + | maybedocheader 'signature' modid maybemodwarning maybeexports 'where' header_body + {% fileSrcSpan >>= \ loc -> + ams (L loc (HsModule (Just $3) $5 $7 [] $4 $1 + )) [mj AnnModule $2,mj AnnWhere $6] } + | header_body2 + {% fileSrcSpan >>= \ loc -> + return (L loc (HsModule Nothing Nothing $1 [] Nothing + Nothing)) } + +header_body :: { [LImportDecl GhcPs] } + : '{' header_top { $2 } + | vocurly header_top { $2 } + +header_body2 :: { [LImportDecl GhcPs] } + : '{' header_top { $2 } + | missing_module_keyword header_top { $2 } + +header_top :: { [LImportDecl GhcPs] } + : semis header_top_importdecls { $2 } + +header_top_importdecls :: { [LImportDecl GhcPs] } + : importdecls_semi { $1 } + | importdecls { $1 } + +----------------------------------------------------------------------------- +-- The Export List + +maybeexports :: { (Maybe (Located [LIE GhcPs])) } + : '(' exportlist ')' {% amsL (comb2 $1 $>) [mop $1,mcp $3] >> + return (Just (sLL $1 $> (fromOL $2))) } + | {- empty -} { Nothing } + +exportlist :: { OrdList (LIE GhcPs) } + : expdoclist ',' expdoclist {% addAnnotation (oll $1) AnnComma (gl $2) + >> return ($1 `appOL` $3) } + | exportlist1 { $1 } + +exportlist1 :: { OrdList (LIE GhcPs) } + : expdoclist export expdoclist ',' exportlist1 + {% (addAnnotation (oll ($1 `appOL` $2 `appOL` $3)) + AnnComma (gl $4) ) >> + return ($1 `appOL` $2 `appOL` $3 `appOL` $5) } + | expdoclist export expdoclist { $1 `appOL` $2 `appOL` $3 } + | expdoclist { $1 } + +expdoclist :: { OrdList (LIE GhcPs) } + : exp_doc expdoclist { $1 `appOL` $2 } + | {- empty -} { nilOL } + +exp_doc :: { OrdList (LIE GhcPs) } + : docsection { unitOL (sL1 $1 (case (unLoc $1) of (n, doc) -> IEGroup noExtField n doc)) } + | docnamed { unitOL (sL1 $1 (IEDocNamed noExtField ((fst . unLoc) $1))) } + | docnext { unitOL (sL1 $1 (IEDoc noExtField (unLoc $1))) } + + + -- No longer allow things like [] and (,,,) to be exported + -- They are built in syntax, always available +export :: { OrdList (LIE GhcPs) } + : qcname_ext export_subspec {% mkModuleImpExp $1 (snd $ unLoc $2) + >>= \ie -> amsu (sLL $1 $> ie) (fst $ unLoc $2) } + | 'module' modid {% amsu (sLL $1 $> (IEModuleContents noExtField $2)) + [mj AnnModule $1] } + | 'pattern' qcon {% amsu (sLL $1 $> (IEVar noExtField (sLL $1 $> (IEPattern $2)))) + [mj AnnPattern $1] } + +export_subspec :: { Located ([AddAnn],ImpExpSubSpec) } + : {- empty -} { sL0 ([],ImpExpAbs) } + | '(' qcnames ')' {% mkImpExpSubSpec (reverse (snd $2)) + >>= \(as,ie) -> return $ sLL $1 $> + (as ++ [mop $1,mcp $3] ++ fst $2, ie) } + + +qcnames :: { ([AddAnn], [Located ImpExpQcSpec]) } + : {- empty -} { ([],[]) } + | qcnames1 { $1 } + +qcnames1 :: { ([AddAnn], [Located ImpExpQcSpec]) } -- A reversed list + : qcnames1 ',' qcname_ext_w_wildcard {% case (head (snd $1)) of + l@(L _ ImpExpQcWildcard) -> + return ([mj AnnComma $2, mj AnnDotdot l] + ,(snd (unLoc $3) : snd $1)) + l -> (ams (head (snd $1)) [mj AnnComma $2] >> + return (fst $1 ++ fst (unLoc $3), + snd (unLoc $3) : snd $1)) } + + + -- Annotations re-added in mkImpExpSubSpec + | qcname_ext_w_wildcard { (fst (unLoc $1),[snd (unLoc $1)]) } + +-- Variable, data constructor or wildcard +-- or tagged type constructor +qcname_ext_w_wildcard :: { Located ([AddAnn], Located ImpExpQcSpec) } + : qcname_ext { sL1 $1 ([],$1) } + | '..' { sL1 $1 ([mj AnnDotdot $1], sL1 $1 ImpExpQcWildcard) } + +qcname_ext :: { Located ImpExpQcSpec } + : qcname { sL1 $1 (ImpExpQcName $1) } + | 'type' oqtycon {% do { n <- mkTypeImpExp $2 + ; ams (sLL $1 $> (ImpExpQcType n)) + [mj AnnType $1] } } + +qcname :: { Located RdrName } -- Variable or type constructor + : qvar { $1 } -- Things which look like functions + -- Note: This includes record selectors but + -- also (-.->), see #11432 + | oqtycon_no_varcon { $1 } -- see Note [Type constructors in export list] + +----------------------------------------------------------------------------- +-- Import Declarations + +-- importdecls and topdecls must contain at least one declaration; +-- top handles the fact that these may be optional. + +-- One or more semicolons +semis1 :: { [AddAnn] } +semis1 : semis1 ';' { mj AnnSemi $2 : $1 } + | ';' { [mj AnnSemi $1] } + +-- Zero or more semicolons +semis :: { [AddAnn] } +semis : semis ';' { mj AnnSemi $2 : $1 } + | {- empty -} { [] } + +-- No trailing semicolons, non-empty +importdecls :: { [LImportDecl GhcPs] } +importdecls + : importdecls_semi importdecl + { $2 : $1 } + +-- May have trailing semicolons, can be empty +importdecls_semi :: { [LImportDecl GhcPs] } +importdecls_semi + : importdecls_semi importdecl semis1 + {% ams $2 $3 >> return ($2 : $1) } + | {- empty -} { [] } + +importdecl :: { LImportDecl GhcPs } + : 'import' maybe_src maybe_safe optqualified maybe_pkg modid optqualified maybeas maybeimpspec + {% do { + ; checkImportDecl $4 $7 + ; ams (L (comb4 $1 $6 (snd $8) $9) $ + ImportDecl { ideclExt = noExtField + , ideclSourceSrc = snd $ fst $2 + , ideclName = $6, ideclPkgQual = snd $5 + , ideclSource = snd $2, ideclSafe = snd $3 + , ideclQualified = importDeclQualifiedStyle $4 $7 + , ideclImplicit = False + , ideclAs = unLoc (snd $8) + , ideclHiding = unLoc $9 }) + (mj AnnImport $1 : fst (fst $2) ++ fst $3 ++ fmap (mj AnnQualified) (maybeToList $4) + ++ fst $5 ++ fmap (mj AnnQualified) (maybeToList $7) ++ fst $8) + } + } + + +maybe_src :: { (([AddAnn],SourceText),IsBootInterface) } + : '{-# SOURCE' '#-}' { (([mo $1,mc $2],getSOURCE_PRAGs $1) + , True) } + | {- empty -} { (([],NoSourceText),False) } + +maybe_safe :: { ([AddAnn],Bool) } + : 'safe' { ([mj AnnSafe $1],True) } + | {- empty -} { ([],False) } + +maybe_pkg :: { ([AddAnn],Maybe StringLiteral) } + : STRING {% do { let { pkgFS = getSTRING $1 } + ; unless (looksLikePackageName (unpackFS pkgFS)) $ + addError (getLoc $1) $ vcat [ + text "Parse error" <> colon <+> quotes (ppr pkgFS), + text "Version number or non-alphanumeric" <+> + text "character in package name"] + ; return ([mj AnnPackageName $1], Just (StringLiteral (getSTRINGs $1) pkgFS)) } } + | {- empty -} { ([],Nothing) } + +optqualified :: { Maybe (Located Token) } + : 'qualified' { Just $1 } + | {- empty -} { Nothing } + +maybeas :: { ([AddAnn],Located (Maybe (Located ModuleName))) } + : 'as' modid { ([mj AnnAs $1] + ,sLL $1 $> (Just $2)) } + | {- empty -} { ([],noLoc Nothing) } + +maybeimpspec :: { Located (Maybe (Bool, Located [LIE GhcPs])) } + : impspec {% let (b, ie) = unLoc $1 in + checkImportSpec ie + >>= \checkedIe -> + return (L (gl $1) (Just (b, checkedIe))) } + | {- empty -} { noLoc Nothing } + +impspec :: { Located (Bool, Located [LIE GhcPs]) } + : '(' exportlist ')' {% ams (sLL $1 $> (False, + sLL $1 $> $ fromOL $2)) + [mop $1,mcp $3] } + | 'hiding' '(' exportlist ')' {% ams (sLL $1 $> (True, + sLL $1 $> $ fromOL $3)) + [mj AnnHiding $1,mop $2,mcp $4] } + +----------------------------------------------------------------------------- +-- Fixity Declarations + +prec :: { Located (SourceText,Int) } + : {- empty -} { noLoc (NoSourceText,9) } + | INTEGER + { sL1 $1 (getINTEGERs $1,fromInteger (il_value (getINTEGER $1))) } + +infix :: { Located FixityDirection } + : 'infix' { sL1 $1 InfixN } + | 'infixl' { sL1 $1 InfixL } + | 'infixr' { sL1 $1 InfixR } + +ops :: { Located (OrdList (Located RdrName)) } + : ops ',' op {% addAnnotation (oll $ unLoc $1) AnnComma (gl $2) >> + return (sLL $1 $> ((unLoc $1) `appOL` unitOL $3))} + | op { sL1 $1 (unitOL $1) } + +----------------------------------------------------------------------------- +-- Top-Level Declarations + +-- No trailing semicolons, non-empty +topdecls :: { OrdList (LHsDecl GhcPs) } + : topdecls_semi topdecl { $1 `snocOL` $2 } + +-- May have trailing semicolons, can be empty +topdecls_semi :: { OrdList (LHsDecl GhcPs) } + : topdecls_semi topdecl semis1 {% ams $2 $3 >> return ($1 `snocOL` $2) } + | {- empty -} { nilOL } + +topdecl :: { LHsDecl GhcPs } + : cl_decl { sL1 $1 (TyClD noExtField (unLoc $1)) } + | ty_decl { sL1 $1 (TyClD noExtField (unLoc $1)) } + | standalone_kind_sig { sL1 $1 (KindSigD noExtField (unLoc $1)) } + | inst_decl { sL1 $1 (InstD noExtField (unLoc $1)) } + | stand_alone_deriving { sLL $1 $> (DerivD noExtField (unLoc $1)) } + | role_annot { sL1 $1 (RoleAnnotD noExtField (unLoc $1)) } + | 'default' '(' comma_types0 ')' {% ams (sLL $1 $> (DefD noExtField (DefaultDecl noExtField $3))) + [mj AnnDefault $1 + ,mop $2,mcp $4] } + | 'foreign' fdecl {% ams (sLL $1 $> (snd $ unLoc $2)) + (mj AnnForeign $1:(fst $ unLoc $2)) } + | '{-# DEPRECATED' deprecations '#-}' {% ams (sLL $1 $> $ WarningD noExtField (Warnings noExtField (getDEPRECATED_PRAGs $1) (fromOL $2))) + [mo $1,mc $3] } + | '{-# WARNING' warnings '#-}' {% ams (sLL $1 $> $ WarningD noExtField (Warnings noExtField (getWARNING_PRAGs $1) (fromOL $2))) + [mo $1,mc $3] } + | '{-# RULES' rules '#-}' {% ams (sLL $1 $> $ RuleD noExtField (HsRules noExtField (getRULES_PRAGs $1) (fromOL $2))) + [mo $1,mc $3] } + | annotation { $1 } + | decl_no_th { $1 } + + -- Template Haskell Extension + -- The $(..) form is one possible form of infixexp + -- but we treat an arbitrary expression just as if + -- it had a $(..) wrapped around it + | infixexp {% runECP_P $1 >>= \ $1 -> + return $ sLL $1 $> $ mkSpliceDecl $1 } + +-- Type classes +-- +cl_decl :: { LTyClDecl GhcPs } + : 'class' tycl_hdr fds where_cls + {% amms (mkClassDecl (comb4 $1 $2 $3 $4) $2 $3 (snd $ unLoc $4)) + (mj AnnClass $1:(fst $ unLoc $3)++(fst $ unLoc $4)) } + +-- Type declarations (toplevel) +-- +ty_decl :: { LTyClDecl GhcPs } + -- ordinary type synonyms + : 'type' type '=' ktypedoc + -- Note ktypedoc, not sigtype, on the right of '=' + -- We allow an explicit for-all but we don't insert one + -- in type Foo a = (b,b) + -- Instead we just say b is out of scope + -- + -- Note the use of type for the head; this allows + -- infix type constructors to be declared + {% amms (mkTySynonym (comb2 $1 $4) $2 $4) + [mj AnnType $1,mj AnnEqual $3] } + + -- type family declarations + | 'type' 'family' type opt_tyfam_kind_sig opt_injective_info + where_type_family + -- Note the use of type for the head; this allows + -- infix type constructors to be declared + {% amms (mkFamDecl (comb4 $1 $3 $4 $5) (snd $ unLoc $6) $3 + (snd $ unLoc $4) (snd $ unLoc $5)) + (mj AnnType $1:mj AnnFamily $2:(fst $ unLoc $4) + ++ (fst $ unLoc $5) ++ (fst $ unLoc $6)) } + + -- ordinary data type or newtype declaration + | data_or_newtype capi_ctype tycl_hdr constrs maybe_derivings + {% amms (mkTyData (comb4 $1 $3 $4 $5) (snd $ unLoc $1) $2 $3 + Nothing (reverse (snd $ unLoc $4)) + (fmap reverse $5)) + -- We need the location on tycl_hdr in case + -- constrs and deriving are both empty + ((fst $ unLoc $1):(fst $ unLoc $4)) } + + -- ordinary GADT declaration + | data_or_newtype capi_ctype tycl_hdr opt_kind_sig + gadt_constrlist + maybe_derivings + {% amms (mkTyData (comb4 $1 $3 $5 $6) (snd $ unLoc $1) $2 $3 + (snd $ unLoc $4) (snd $ unLoc $5) + (fmap reverse $6) ) + -- We need the location on tycl_hdr in case + -- constrs and deriving are both empty + ((fst $ unLoc $1):(fst $ unLoc $4)++(fst $ unLoc $5)) } + + -- data/newtype family + | 'data' 'family' type opt_datafam_kind_sig + {% amms (mkFamDecl (comb3 $1 $2 $4) DataFamily $3 + (snd $ unLoc $4) Nothing) + (mj AnnData $1:mj AnnFamily $2:(fst $ unLoc $4)) } + +-- standalone kind signature +standalone_kind_sig :: { LStandaloneKindSig GhcPs } + : 'type' sks_vars '::' ktypedoc + {% amms (mkStandaloneKindSig (comb2 $1 $4) $2 $4) + [mj AnnType $1,mu AnnDcolon $3] } + +-- See also: sig_vars +sks_vars :: { Located [Located RdrName] } -- Returned in reverse order + : sks_vars ',' oqtycon + {% addAnnotation (gl $ head $ unLoc $1) AnnComma (gl $2) >> + return (sLL $1 $> ($3 : unLoc $1)) } + | oqtycon { sL1 $1 [$1] } + +inst_decl :: { LInstDecl GhcPs } + : 'instance' overlap_pragma inst_type where_inst + {% do { (binds, sigs, _, ats, adts, _) <- cvBindsAndSigs (snd $ unLoc $4) + ; let cid = ClsInstDecl { cid_ext = noExtField + , cid_poly_ty = $3, cid_binds = binds + , cid_sigs = mkClassOpSigs sigs + , cid_tyfam_insts = ats + , cid_overlap_mode = $2 + , cid_datafam_insts = adts } + ; ams (L (comb3 $1 (hsSigType $3) $4) (ClsInstD { cid_d_ext = noExtField, cid_inst = cid })) + (mj AnnInstance $1 : (fst $ unLoc $4)) } } + + -- type instance declarations + | 'type' 'instance' ty_fam_inst_eqn + {% ams $3 (fst $ unLoc $3) + >> amms (mkTyFamInst (comb2 $1 $3) (snd $ unLoc $3)) + (mj AnnType $1:mj AnnInstance $2:(fst $ unLoc $3)) } + + -- data/newtype instance declaration + | data_or_newtype 'instance' capi_ctype tycl_hdr_inst constrs + maybe_derivings + {% amms (mkDataFamInst (comb4 $1 $4 $5 $6) (snd $ unLoc $1) $3 (snd $ unLoc $4) + Nothing (reverse (snd $ unLoc $5)) + (fmap reverse $6)) + ((fst $ unLoc $1):mj AnnInstance $2:(fst $ unLoc $4)++(fst $ unLoc $5)) } + + -- GADT instance declaration + | data_or_newtype 'instance' capi_ctype tycl_hdr_inst opt_kind_sig + gadt_constrlist + maybe_derivings + {% amms (mkDataFamInst (comb4 $1 $4 $6 $7) (snd $ unLoc $1) $3 (snd $ unLoc $4) + (snd $ unLoc $5) (snd $ unLoc $6) + (fmap reverse $7)) + ((fst $ unLoc $1):mj AnnInstance $2 + :(fst $ unLoc $4)++(fst $ unLoc $5)++(fst $ unLoc $6)) } + +overlap_pragma :: { Maybe (Located OverlapMode) } + : '{-# OVERLAPPABLE' '#-}' {% ajs (sLL $1 $> (Overlappable (getOVERLAPPABLE_PRAGs $1))) + [mo $1,mc $2] } + | '{-# OVERLAPPING' '#-}' {% ajs (sLL $1 $> (Overlapping (getOVERLAPPING_PRAGs $1))) + [mo $1,mc $2] } + | '{-# OVERLAPS' '#-}' {% ajs (sLL $1 $> (Overlaps (getOVERLAPS_PRAGs $1))) + [mo $1,mc $2] } + | '{-# INCOHERENT' '#-}' {% ajs (sLL $1 $> (Incoherent (getINCOHERENT_PRAGs $1))) + [mo $1,mc $2] } + | {- empty -} { Nothing } + +deriv_strategy_no_via :: { LDerivStrategy GhcPs } + : 'stock' {% ams (sL1 $1 StockStrategy) + [mj AnnStock $1] } + | 'anyclass' {% ams (sL1 $1 AnyclassStrategy) + [mj AnnAnyclass $1] } + | 'newtype' {% ams (sL1 $1 NewtypeStrategy) + [mj AnnNewtype $1] } + +deriv_strategy_via :: { LDerivStrategy GhcPs } + : 'via' type {% ams (sLL $1 $> (ViaStrategy (mkLHsSigType $2))) + [mj AnnVia $1] } + +deriv_standalone_strategy :: { Maybe (LDerivStrategy GhcPs) } + : 'stock' {% ajs (sL1 $1 StockStrategy) + [mj AnnStock $1] } + | 'anyclass' {% ajs (sL1 $1 AnyclassStrategy) + [mj AnnAnyclass $1] } + | 'newtype' {% ajs (sL1 $1 NewtypeStrategy) + [mj AnnNewtype $1] } + | deriv_strategy_via { Just $1 } + | {- empty -} { Nothing } + +-- Injective type families + +opt_injective_info :: { Located ([AddAnn], Maybe (LInjectivityAnn GhcPs)) } + : {- empty -} { noLoc ([], Nothing) } + | '|' injectivity_cond { sLL $1 $> ([mj AnnVbar $1] + , Just ($2)) } + +injectivity_cond :: { LInjectivityAnn GhcPs } + : tyvarid '->' inj_varids + {% ams (sLL $1 $> (InjectivityAnn $1 (reverse (unLoc $3)))) + [mu AnnRarrow $2] } + +inj_varids :: { Located [Located RdrName] } + : inj_varids tyvarid { sLL $1 $> ($2 : unLoc $1) } + | tyvarid { sLL $1 $> [$1] } + +-- Closed type families + +where_type_family :: { Located ([AddAnn],FamilyInfo GhcPs) } + : {- empty -} { noLoc ([],OpenTypeFamily) } + | 'where' ty_fam_inst_eqn_list + { sLL $1 $> (mj AnnWhere $1:(fst $ unLoc $2) + ,ClosedTypeFamily (fmap reverse $ snd $ unLoc $2)) } + +ty_fam_inst_eqn_list :: { Located ([AddAnn],Maybe [LTyFamInstEqn GhcPs]) } + : '{' ty_fam_inst_eqns '}' { sLL $1 $> ([moc $1,mcc $3] + ,Just (unLoc $2)) } + | vocurly ty_fam_inst_eqns close { let (L loc _) = $2 in + L loc ([],Just (unLoc $2)) } + | '{' '..' '}' { sLL $1 $> ([moc $1,mj AnnDotdot $2 + ,mcc $3],Nothing) } + | vocurly '..' close { let (L loc _) = $2 in + L loc ([mj AnnDotdot $2],Nothing) } + +ty_fam_inst_eqns :: { Located [LTyFamInstEqn GhcPs] } + : ty_fam_inst_eqns ';' ty_fam_inst_eqn + {% let (L loc (anns, eqn)) = $3 in + asl (unLoc $1) $2 (L loc eqn) + >> ams $3 anns + >> return (sLL $1 $> (L loc eqn : unLoc $1)) } + | ty_fam_inst_eqns ';' {% addAnnotation (gl $1) AnnSemi (gl $2) + >> return (sLL $1 $> (unLoc $1)) } + | ty_fam_inst_eqn {% let (L loc (anns, eqn)) = $1 in + ams $1 anns + >> return (sLL $1 $> [L loc eqn]) } + | {- empty -} { noLoc [] } + +ty_fam_inst_eqn :: { Located ([AddAnn],TyFamInstEqn GhcPs) } + : 'forall' tv_bndrs '.' type '=' ktype + {% do { hintExplicitForall $1 + ; (eqn,ann) <- mkTyFamInstEqn (Just $2) $4 $6 + ; return (sLL $1 $> + (mu AnnForall $1:mj AnnDot $3:mj AnnEqual $5:ann,eqn)) } } + | type '=' ktype + {% do { (eqn,ann) <- mkTyFamInstEqn Nothing $1 $3 + ; return (sLL $1 $> (mj AnnEqual $2:ann, eqn)) } } + -- Note the use of type for the head; this allows + -- infix type constructors and type patterns + +-- Associated type family declarations +-- +-- * They have a different syntax than on the toplevel (no family special +-- identifier). +-- +-- * They also need to be separate from instances; otherwise, data family +-- declarations without a kind signature cause parsing conflicts with empty +-- data declarations. +-- +at_decl_cls :: { LHsDecl GhcPs } + : -- data family declarations, with optional 'family' keyword + 'data' opt_family type opt_datafam_kind_sig + {% amms (liftM mkTyClD (mkFamDecl (comb3 $1 $3 $4) DataFamily $3 + (snd $ unLoc $4) Nothing)) + (mj AnnData $1:$2++(fst $ unLoc $4)) } + + -- type family declarations, with optional 'family' keyword + -- (can't use opt_instance because you get shift/reduce errors + | 'type' type opt_at_kind_inj_sig + {% amms (liftM mkTyClD + (mkFamDecl (comb3 $1 $2 $3) OpenTypeFamily $2 + (fst . snd $ unLoc $3) + (snd . snd $ unLoc $3))) + (mj AnnType $1:(fst $ unLoc $3)) } + | 'type' 'family' type opt_at_kind_inj_sig + {% amms (liftM mkTyClD + (mkFamDecl (comb3 $1 $3 $4) OpenTypeFamily $3 + (fst . snd $ unLoc $4) + (snd . snd $ unLoc $4))) + (mj AnnType $1:mj AnnFamily $2:(fst $ unLoc $4)) } + + -- default type instances, with optional 'instance' keyword + | 'type' ty_fam_inst_eqn + {% ams $2 (fst $ unLoc $2) >> + amms (liftM mkInstD (mkTyFamInst (comb2 $1 $2) (snd $ unLoc $2))) + (mj AnnType $1:(fst $ unLoc $2)) } + | 'type' 'instance' ty_fam_inst_eqn + {% ams $3 (fst $ unLoc $3) >> + amms (liftM mkInstD (mkTyFamInst (comb2 $1 $3) (snd $ unLoc $3))) + (mj AnnType $1:mj AnnInstance $2:(fst $ unLoc $3)) } + +opt_family :: { [AddAnn] } + : {- empty -} { [] } + | 'family' { [mj AnnFamily $1] } + +opt_instance :: { [AddAnn] } + : {- empty -} { [] } + | 'instance' { [mj AnnInstance $1] } + +-- Associated type instances +-- +at_decl_inst :: { LInstDecl GhcPs } + -- type instance declarations, with optional 'instance' keyword + : 'type' opt_instance ty_fam_inst_eqn + -- Note the use of type for the head; this allows + -- infix type constructors and type patterns + {% ams $3 (fst $ unLoc $3) >> + amms (mkTyFamInst (comb2 $1 $3) (snd $ unLoc $3)) + (mj AnnType $1:$2++(fst $ unLoc $3)) } + + -- data/newtype instance declaration, with optional 'instance' keyword + | data_or_newtype opt_instance capi_ctype tycl_hdr_inst constrs maybe_derivings + {% amms (mkDataFamInst (comb4 $1 $4 $5 $6) (snd $ unLoc $1) $3 (snd $ unLoc $4) + Nothing (reverse (snd $ unLoc $5)) + (fmap reverse $6)) + ((fst $ unLoc $1):$2++(fst $ unLoc $4)++(fst $ unLoc $5)) } + + -- GADT instance declaration, with optional 'instance' keyword + | data_or_newtype opt_instance capi_ctype tycl_hdr_inst opt_kind_sig + gadt_constrlist + maybe_derivings + {% amms (mkDataFamInst (comb4 $1 $4 $6 $7) (snd $ unLoc $1) $3 + (snd $ unLoc $4) (snd $ unLoc $5) (snd $ unLoc $6) + (fmap reverse $7)) + ((fst $ unLoc $1):$2++(fst $ unLoc $4)++(fst $ unLoc $5)++(fst $ unLoc $6)) } + +data_or_newtype :: { Located (AddAnn, NewOrData) } + : 'data' { sL1 $1 (mj AnnData $1,DataType) } + | 'newtype' { sL1 $1 (mj AnnNewtype $1,NewType) } + +-- Family result/return kind signatures + +opt_kind_sig :: { Located ([AddAnn], Maybe (LHsKind GhcPs)) } + : { noLoc ([] , Nothing) } + | '::' kind { sLL $1 $> ([mu AnnDcolon $1], Just $2) } + +opt_datafam_kind_sig :: { Located ([AddAnn], LFamilyResultSig GhcPs) } + : { noLoc ([] , noLoc (NoSig noExtField) )} + | '::' kind { sLL $1 $> ([mu AnnDcolon $1], sLL $1 $> (KindSig noExtField $2))} + +opt_tyfam_kind_sig :: { Located ([AddAnn], LFamilyResultSig GhcPs) } + : { noLoc ([] , noLoc (NoSig noExtField) )} + | '::' kind { sLL $1 $> ([mu AnnDcolon $1], sLL $1 $> (KindSig noExtField $2))} + | '=' tv_bndr { sLL $1 $> ([mj AnnEqual $1] , sLL $1 $> (TyVarSig noExtField $2))} + +opt_at_kind_inj_sig :: { Located ([AddAnn], ( LFamilyResultSig GhcPs + , Maybe (LInjectivityAnn GhcPs)))} + : { noLoc ([], (noLoc (NoSig noExtField), Nothing)) } + | '::' kind { sLL $1 $> ( [mu AnnDcolon $1] + , (sLL $2 $> (KindSig noExtField $2), Nothing)) } + | '=' tv_bndr '|' injectivity_cond + { sLL $1 $> ([mj AnnEqual $1, mj AnnVbar $3] + , (sLL $1 $2 (TyVarSig noExtField $2), Just $4))} + +-- tycl_hdr parses the header of a class or data type decl, +-- which takes the form +-- T a b +-- Eq a => T a +-- (Eq a, Ord b) => T a b +-- T Int [a] -- for associated types +-- Rather a lot of inlining here, else we get reduce/reduce errors +tycl_hdr :: { Located (Maybe (LHsContext GhcPs), LHsType GhcPs) } + : context '=>' type {% addAnnotation (gl $1) (toUnicodeAnn AnnDarrow $2) (gl $2) + >> (return (sLL $1 $> (Just $1, $3))) + } + | type { sL1 $1 (Nothing, $1) } + +tycl_hdr_inst :: { Located ([AddAnn],(Maybe (LHsContext GhcPs), Maybe [LHsTyVarBndr GhcPs], LHsType GhcPs)) } + : 'forall' tv_bndrs '.' context '=>' type {% hintExplicitForall $1 + >> (addAnnotation (gl $4) (toUnicodeAnn AnnDarrow $5) (gl $5) + >> return (sLL $1 $> ([mu AnnForall $1, mj AnnDot $3] + , (Just $4, Just $2, $6))) + ) + } + | 'forall' tv_bndrs '.' type {% hintExplicitForall $1 + >> return (sLL $1 $> ([mu AnnForall $1, mj AnnDot $3] + , (Nothing, Just $2, $4))) + } + | context '=>' type {% addAnnotation (gl $1) (toUnicodeAnn AnnDarrow $2) (gl $2) + >> (return (sLL $1 $>([], (Just $1, Nothing, $3)))) + } + | type { sL1 $1 ([], (Nothing, Nothing, $1)) } + + +capi_ctype :: { Maybe (Located CType) } +capi_ctype : '{-# CTYPE' STRING STRING '#-}' + {% ajs (sLL $1 $> (CType (getCTYPEs $1) (Just (Header (getSTRINGs $2) (getSTRING $2))) + (getSTRINGs $3,getSTRING $3))) + [mo $1,mj AnnHeader $2,mj AnnVal $3,mc $4] } + + | '{-# CTYPE' STRING '#-}' + {% ajs (sLL $1 $> (CType (getCTYPEs $1) Nothing (getSTRINGs $2, getSTRING $2))) + [mo $1,mj AnnVal $2,mc $3] } + + | { Nothing } + +----------------------------------------------------------------------------- +-- Stand-alone deriving + +-- Glasgow extension: stand-alone deriving declarations +stand_alone_deriving :: { LDerivDecl GhcPs } + : 'deriving' deriv_standalone_strategy 'instance' overlap_pragma inst_type + {% do { let { err = text "in the stand-alone deriving instance" + <> colon <+> quotes (ppr $5) } + ; ams (sLL $1 (hsSigType $>) + (DerivDecl noExtField (mkHsWildCardBndrs $5) $2 $4)) + [mj AnnDeriving $1, mj AnnInstance $3] } } + +----------------------------------------------------------------------------- +-- Role annotations + +role_annot :: { LRoleAnnotDecl GhcPs } +role_annot : 'type' 'role' oqtycon maybe_roles + {% amms (mkRoleAnnotDecl (comb3 $1 $3 $4) $3 (reverse (unLoc $4))) + [mj AnnType $1,mj AnnRole $2] } + +-- Reversed! +maybe_roles :: { Located [Located (Maybe FastString)] } +maybe_roles : {- empty -} { noLoc [] } + | roles { $1 } + +roles :: { Located [Located (Maybe FastString)] } +roles : role { sLL $1 $> [$1] } + | roles role { sLL $1 $> $ $2 : unLoc $1 } + +-- read it in as a varid for better error messages +role :: { Located (Maybe FastString) } +role : VARID { sL1 $1 $ Just $ getVARID $1 } + | '_' { sL1 $1 Nothing } + +-- Pattern synonyms + +-- Glasgow extension: pattern synonyms +pattern_synonym_decl :: { LHsDecl GhcPs } + : 'pattern' pattern_synonym_lhs '=' pat + {% let (name, args,as ) = $2 in + ams (sLL $1 $> . ValD noExtField $ mkPatSynBind name args $4 + ImplicitBidirectional) + (as ++ [mj AnnPattern $1, mj AnnEqual $3]) + } + + | 'pattern' pattern_synonym_lhs '<-' pat + {% let (name, args, as) = $2 in + ams (sLL $1 $> . ValD noExtField $ mkPatSynBind name args $4 Unidirectional) + (as ++ [mj AnnPattern $1,mu AnnLarrow $3]) } + + | 'pattern' pattern_synonym_lhs '<-' pat where_decls + {% do { let (name, args, as) = $2 + ; mg <- mkPatSynMatchGroup name (snd $ unLoc $5) + ; ams (sLL $1 $> . ValD noExtField $ + mkPatSynBind name args $4 (ExplicitBidirectional mg)) + (as ++ ((mj AnnPattern $1:mu AnnLarrow $3:(fst $ unLoc $5))) ) + }} + +pattern_synonym_lhs :: { (Located RdrName, HsPatSynDetails (Located RdrName), [AddAnn]) } + : con vars0 { ($1, PrefixCon $2, []) } + | varid conop varid { ($2, InfixCon $1 $3, []) } + | con '{' cvars1 '}' { ($1, RecCon $3, [moc $2, mcc $4] ) } + +vars0 :: { [Located RdrName] } + : {- empty -} { [] } + | varid vars0 { $1 : $2 } + +cvars1 :: { [RecordPatSynField (Located RdrName)] } + : var { [RecordPatSynField $1 $1] } + | var ',' cvars1 {% addAnnotation (getLoc $1) AnnComma (getLoc $2) >> + return ((RecordPatSynField $1 $1) : $3 )} + +where_decls :: { Located ([AddAnn] + , Located (OrdList (LHsDecl GhcPs))) } + : 'where' '{' decls '}' { sLL $1 $> ((mj AnnWhere $1:moc $2 + :mcc $4:(fst $ unLoc $3)),sL1 $3 (snd $ unLoc $3)) } + | 'where' vocurly decls close { L (comb2 $1 $3) ((mj AnnWhere $1:(fst $ unLoc $3)) + ,sL1 $3 (snd $ unLoc $3)) } + +pattern_synonym_sig :: { LSig GhcPs } + : 'pattern' con_list '::' sigtypedoc + {% ams (sLL $1 $> $ PatSynSig noExtField (unLoc $2) (mkLHsSigType $4)) + [mj AnnPattern $1, mu AnnDcolon $3] } + +----------------------------------------------------------------------------- +-- Nested declarations + +-- Declaration in class bodies +-- +decl_cls :: { LHsDecl GhcPs } +decl_cls : at_decl_cls { $1 } + | decl { $1 } + + -- A 'default' signature used with the generic-programming extension + | 'default' infixexp '::' sigtypedoc + {% runECP_P $2 >>= \ $2 -> + do { v <- checkValSigLhs $2 + ; let err = text "in default signature" <> colon <+> + quotes (ppr $2) + ; ams (sLL $1 $> $ SigD noExtField $ ClassOpSig noExtField True [v] $ mkLHsSigType $4) + [mj AnnDefault $1,mu AnnDcolon $3] } } + +decls_cls :: { Located ([AddAnn],OrdList (LHsDecl GhcPs)) } -- Reversed + : decls_cls ';' decl_cls {% if isNilOL (snd $ unLoc $1) + then return (sLL $1 $> (mj AnnSemi $2:(fst $ unLoc $1) + , unitOL $3)) + else ams (lastOL (snd $ unLoc $1)) [mj AnnSemi $2] + >> return (sLL $1 $> (fst $ unLoc $1 + ,(snd $ unLoc $1) `appOL` unitOL $3)) } + | decls_cls ';' {% if isNilOL (snd $ unLoc $1) + then return (sLL $1 $> (mj AnnSemi $2:(fst $ unLoc $1) + ,snd $ unLoc $1)) + else ams (lastOL (snd $ unLoc $1)) [mj AnnSemi $2] + >> return (sLL $1 $> (unLoc $1)) } + | decl_cls { sL1 $1 ([], unitOL $1) } + | {- empty -} { noLoc ([],nilOL) } + +decllist_cls + :: { Located ([AddAnn] + , OrdList (LHsDecl GhcPs)) } -- Reversed + : '{' decls_cls '}' { sLL $1 $> (moc $1:mcc $3:(fst $ unLoc $2) + ,snd $ unLoc $2) } + | vocurly decls_cls close { $2 } + +-- Class body +-- +where_cls :: { Located ([AddAnn] + ,(OrdList (LHsDecl GhcPs))) } -- Reversed + -- No implicit parameters + -- May have type declarations + : 'where' decllist_cls { sLL $1 $> (mj AnnWhere $1:(fst $ unLoc $2) + ,snd $ unLoc $2) } + | {- empty -} { noLoc ([],nilOL) } + +-- Declarations in instance bodies +-- +decl_inst :: { Located (OrdList (LHsDecl GhcPs)) } +decl_inst : at_decl_inst { sLL $1 $> (unitOL (sL1 $1 (InstD noExtField (unLoc $1)))) } + | decl { sLL $1 $> (unitOL $1) } + +decls_inst :: { Located ([AddAnn],OrdList (LHsDecl GhcPs)) } -- Reversed + : decls_inst ';' decl_inst {% if isNilOL (snd $ unLoc $1) + then return (sLL $1 $> (mj AnnSemi $2:(fst $ unLoc $1) + , unLoc $3)) + else ams (lastOL $ snd $ unLoc $1) [mj AnnSemi $2] + >> return + (sLL $1 $> (fst $ unLoc $1 + ,(snd $ unLoc $1) `appOL` unLoc $3)) } + | decls_inst ';' {% if isNilOL (snd $ unLoc $1) + then return (sLL $1 $> (mj AnnSemi $2:(fst $ unLoc $1) + ,snd $ unLoc $1)) + else ams (lastOL $ snd $ unLoc $1) [mj AnnSemi $2] + >> return (sLL $1 $> (unLoc $1)) } + | decl_inst { sL1 $1 ([],unLoc $1) } + | {- empty -} { noLoc ([],nilOL) } + +decllist_inst + :: { Located ([AddAnn] + , OrdList (LHsDecl GhcPs)) } -- Reversed + : '{' decls_inst '}' { sLL $1 $> (moc $1:mcc $3:(fst $ unLoc $2),snd $ unLoc $2) } + | vocurly decls_inst close { L (gl $2) (unLoc $2) } + +-- Instance body +-- +where_inst :: { Located ([AddAnn] + , OrdList (LHsDecl GhcPs)) } -- Reversed + -- No implicit parameters + -- May have type declarations + : 'where' decllist_inst { sLL $1 $> (mj AnnWhere $1:(fst $ unLoc $2) + ,(snd $ unLoc $2)) } + | {- empty -} { noLoc ([],nilOL) } + +-- Declarations in binding groups other than classes and instances +-- +decls :: { Located ([AddAnn],OrdList (LHsDecl GhcPs)) } + : decls ';' decl {% if isNilOL (snd $ unLoc $1) + then return (sLL $1 $> (mj AnnSemi $2:(fst $ unLoc $1) + , unitOL $3)) + else do ams (lastOL $ snd $ unLoc $1) [mj AnnSemi $2] + >> return ( + let { this = unitOL $3; + rest = snd $ unLoc $1; + these = rest `appOL` this } + in rest `seq` this `seq` these `seq` + (sLL $1 $> (fst $ unLoc $1,these))) } + | decls ';' {% if isNilOL (snd $ unLoc $1) + then return (sLL $1 $> ((mj AnnSemi $2:(fst $ unLoc $1) + ,snd $ unLoc $1))) + else ams (lastOL $ snd $ unLoc $1) [mj AnnSemi $2] + >> return (sLL $1 $> (unLoc $1)) } + | decl { sL1 $1 ([], unitOL $1) } + | {- empty -} { noLoc ([],nilOL) } + +decllist :: { Located ([AddAnn],Located (OrdList (LHsDecl GhcPs))) } + : '{' decls '}' { sLL $1 $> (moc $1:mcc $3:(fst $ unLoc $2) + ,sL1 $2 $ snd $ unLoc $2) } + | vocurly decls close { L (gl $2) (fst $ unLoc $2,sL1 $2 $ snd $ unLoc $2) } + +-- Binding groups other than those of class and instance declarations +-- +binds :: { Located ([AddAnn],Located (HsLocalBinds GhcPs)) } + -- May have implicit parameters + -- No type declarations + : decllist {% do { val_binds <- cvBindGroup (unLoc $ snd $ unLoc $1) + ; return (sL1 $1 (fst $ unLoc $1 + ,sL1 $1 $ HsValBinds noExtField val_binds)) } } + + | '{' dbinds '}' { sLL $1 $> ([moc $1,mcc $3] + ,sL1 $2 $ HsIPBinds noExtField (IPBinds noExtField (reverse $ unLoc $2))) } + + | vocurly dbinds close { L (getLoc $2) ([] + ,sL1 $2 $ HsIPBinds noExtField (IPBinds noExtField (reverse $ unLoc $2))) } + + +wherebinds :: { Located ([AddAnn],Located (HsLocalBinds GhcPs)) } + -- May have implicit parameters + -- No type declarations + : 'where' binds { sLL $1 $> (mj AnnWhere $1 : (fst $ unLoc $2) + ,snd $ unLoc $2) } + | {- empty -} { noLoc ([],noLoc emptyLocalBinds) } + + +----------------------------------------------------------------------------- +-- Transformation Rules + +rules :: { OrdList (LRuleDecl GhcPs) } + : rules ';' rule {% addAnnotation (oll $1) AnnSemi (gl $2) + >> return ($1 `snocOL` $3) } + | rules ';' {% addAnnotation (oll $1) AnnSemi (gl $2) + >> return $1 } + | rule { unitOL $1 } + | {- empty -} { nilOL } + +rule :: { LRuleDecl GhcPs } + : STRING rule_activation rule_foralls infixexp '=' exp + {%runECP_P $4 >>= \ $4 -> + runECP_P $6 >>= \ $6 -> + ams (sLL $1 $> $ HsRule { rd_ext = noExtField + , rd_name = L (gl $1) (getSTRINGs $1, getSTRING $1) + , rd_act = (snd $2) `orElse` AlwaysActive + , rd_tyvs = sndOf3 $3, rd_tmvs = thdOf3 $3 + , rd_lhs = $4, rd_rhs = $6 }) + (mj AnnEqual $5 : (fst $2) ++ (fstOf3 $3)) } + +-- Rules can be specified to be NeverActive, unlike inline/specialize pragmas +rule_activation :: { ([AddAnn],Maybe Activation) } + : {- empty -} { ([],Nothing) } + | rule_explicit_activation { (fst $1,Just (snd $1)) } + +-- This production is used to parse the tilde syntax in pragmas such as +-- * {-# INLINE[~2] ... #-} +-- * {-# SPECIALISE [~ 001] ... #-} +-- * {-# RULES ... [~0] ... g #-} +-- Note that it can be written either +-- without a space [~1] (the PREFIX_TILDE case), or +-- with a space [~ 1] (the VARSYM case). +-- See Note [Whitespace-sensitive operator parsing] in GHC.Parser.Lexer +rule_activation_marker :: { [AddAnn] } + : PREFIX_TILDE { [mj AnnTilde $1] } + | VARSYM {% if (getVARSYM $1 == fsLit "~") + then return [mj AnnTilde $1] + else do { addError (getLoc $1) $ text "Invalid rule activation marker" + ; return [] } } + +rule_explicit_activation :: { ([AddAnn] + ,Activation) } -- In brackets + : '[' INTEGER ']' { ([mos $1,mj AnnVal $2,mcs $3] + ,ActiveAfter (getINTEGERs $2) (fromInteger (il_value (getINTEGER $2)))) } + | '[' rule_activation_marker INTEGER ']' + { ($2++[mos $1,mj AnnVal $3,mcs $4] + ,ActiveBefore (getINTEGERs $3) (fromInteger (il_value (getINTEGER $3)))) } + | '[' rule_activation_marker ']' + { ($2++[mos $1,mcs $3] + ,NeverActive) } + +rule_foralls :: { ([AddAnn], Maybe [LHsTyVarBndr GhcPs], [LRuleBndr GhcPs]) } + : 'forall' rule_vars '.' 'forall' rule_vars '.' {% let tyvs = mkRuleTyVarBndrs $2 + in hintExplicitForall $1 + >> checkRuleTyVarBndrNames (mkRuleTyVarBndrs $2) + >> return ([mu AnnForall $1,mj AnnDot $3, + mu AnnForall $4,mj AnnDot $6], + Just (mkRuleTyVarBndrs $2), mkRuleBndrs $5) } + | 'forall' rule_vars '.' { ([mu AnnForall $1,mj AnnDot $3], + Nothing, mkRuleBndrs $2) } + | {- empty -} { ([], Nothing, []) } + +rule_vars :: { [LRuleTyTmVar] } + : rule_var rule_vars { $1 : $2 } + | {- empty -} { [] } + +rule_var :: { LRuleTyTmVar } + : varid { sLL $1 $> (RuleTyTmVar $1 Nothing) } + | '(' varid '::' ctype ')' {% ams (sLL $1 $> (RuleTyTmVar $2 (Just $4))) + [mop $1,mu AnnDcolon $3,mcp $5] } + +{- Note [Parsing explicit foralls in Rules] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +We really want the above definition of rule_foralls to be: + + rule_foralls : 'forall' tv_bndrs '.' 'forall' rule_vars '.' + | 'forall' rule_vars '.' + | {- empty -} + +where rule_vars (term variables) can be named "forall", "family", or "role", +but tv_vars (type variables) cannot be. However, such a definition results +in a reduce/reduce conflict. For example, when parsing: +> {-# RULE "name" forall a ... #-} +before the '...' it is impossible to determine whether we should be in the +first or second case of the above. + +This is resolved by using rule_vars (which is more general) for both, and +ensuring that type-level quantified variables do not have the names "forall", +"family", or "role" in the function 'checkRuleTyVarBndrNames' in +GHC.Parser.PostProcess. +Thus, whenever the definition of tyvarid (used for tv_bndrs) is changed relative +to varid (used for rule_vars), 'checkRuleTyVarBndrNames' must be updated. +-} + +----------------------------------------------------------------------------- +-- Warnings and deprecations (c.f. rules) + +warnings :: { OrdList (LWarnDecl GhcPs) } + : warnings ';' warning {% addAnnotation (oll $1) AnnSemi (gl $2) + >> return ($1 `appOL` $3) } + | warnings ';' {% addAnnotation (oll $1) AnnSemi (gl $2) + >> return $1 } + | warning { $1 } + | {- empty -} { nilOL } + +-- SUP: TEMPORARY HACK, not checking for `module Foo' +warning :: { OrdList (LWarnDecl GhcPs) } + : namelist strings + {% amsu (sLL $1 $> (Warning noExtField (unLoc $1) (WarningTxt (noLoc NoSourceText) $ snd $ unLoc $2))) + (fst $ unLoc $2) } + +deprecations :: { OrdList (LWarnDecl GhcPs) } + : deprecations ';' deprecation + {% addAnnotation (oll $1) AnnSemi (gl $2) + >> return ($1 `appOL` $3) } + | deprecations ';' {% addAnnotation (oll $1) AnnSemi (gl $2) + >> return $1 } + | deprecation { $1 } + | {- empty -} { nilOL } + +-- SUP: TEMPORARY HACK, not checking for `module Foo' +deprecation :: { OrdList (LWarnDecl GhcPs) } + : namelist strings + {% amsu (sLL $1 $> $ (Warning noExtField (unLoc $1) (DeprecatedTxt (noLoc NoSourceText) $ snd $ unLoc $2))) + (fst $ unLoc $2) } + +strings :: { Located ([AddAnn],[Located StringLiteral]) } + : STRING { sL1 $1 ([],[L (gl $1) (getStringLiteral $1)]) } + | '[' stringlist ']' { sLL $1 $> $ ([mos $1,mcs $3],fromOL (unLoc $2)) } + +stringlist :: { Located (OrdList (Located StringLiteral)) } + : stringlist ',' STRING {% addAnnotation (oll $ unLoc $1) AnnComma (gl $2) >> + return (sLL $1 $> (unLoc $1 `snocOL` + (L (gl $3) (getStringLiteral $3)))) } + | STRING { sLL $1 $> (unitOL (L (gl $1) (getStringLiteral $1))) } + | {- empty -} { noLoc nilOL } + +----------------------------------------------------------------------------- +-- Annotations +annotation :: { LHsDecl GhcPs } + : '{-# ANN' name_var aexp '#-}' {% runECP_P $3 >>= \ $3 -> + ams (sLL $1 $> (AnnD noExtField $ HsAnnotation noExtField + (getANN_PRAGs $1) + (ValueAnnProvenance $2) $3)) + [mo $1,mc $4] } + + | '{-# ANN' 'type' tycon aexp '#-}' {% runECP_P $4 >>= \ $4 -> + ams (sLL $1 $> (AnnD noExtField $ HsAnnotation noExtField + (getANN_PRAGs $1) + (TypeAnnProvenance $3) $4)) + [mo $1,mj AnnType $2,mc $5] } + + | '{-# ANN' 'module' aexp '#-}' {% runECP_P $3 >>= \ $3 -> + ams (sLL $1 $> (AnnD noExtField $ HsAnnotation noExtField + (getANN_PRAGs $1) + ModuleAnnProvenance $3)) + [mo $1,mj AnnModule $2,mc $4] } + + +----------------------------------------------------------------------------- +-- Foreign import and export declarations + +fdecl :: { Located ([AddAnn],HsDecl GhcPs) } +fdecl : 'import' callconv safety fspec + {% mkImport $2 $3 (snd $ unLoc $4) >>= \i -> + return (sLL $1 $> (mj AnnImport $1 : (fst $ unLoc $4),i)) } + | 'import' callconv fspec + {% do { d <- mkImport $2 (noLoc PlaySafe) (snd $ unLoc $3); + return (sLL $1 $> (mj AnnImport $1 : (fst $ unLoc $3),d)) }} + | 'export' callconv fspec + {% mkExport $2 (snd $ unLoc $3) >>= \i -> + return (sLL $1 $> (mj AnnExport $1 : (fst $ unLoc $3),i) ) } + +callconv :: { Located CCallConv } + : 'stdcall' { sLL $1 $> StdCallConv } + | 'ccall' { sLL $1 $> CCallConv } + | 'capi' { sLL $1 $> CApiConv } + | 'prim' { sLL $1 $> PrimCallConv} + | 'javascript' { sLL $1 $> JavaScriptCallConv } + +safety :: { Located Safety } + : 'unsafe' { sLL $1 $> PlayRisky } + | 'safe' { sLL $1 $> PlaySafe } + | 'interruptible' { sLL $1 $> PlayInterruptible } + +fspec :: { Located ([AddAnn] + ,(Located StringLiteral, Located RdrName, LHsSigType GhcPs)) } + : STRING var '::' sigtypedoc { sLL $1 $> ([mu AnnDcolon $3] + ,(L (getLoc $1) + (getStringLiteral $1), $2, mkLHsSigType $4)) } + | var '::' sigtypedoc { sLL $1 $> ([mu AnnDcolon $2] + ,(noLoc (StringLiteral NoSourceText nilFS), $1, mkLHsSigType $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 + +----------------------------------------------------------------------------- +-- Type signatures + +opt_sig :: { ([AddAnn], Maybe (LHsType GhcPs)) } + : {- empty -} { ([],Nothing) } + | '::' sigtype { ([mu AnnDcolon $1],Just $2) } + +opt_tyconsig :: { ([AddAnn], Maybe (Located RdrName)) } + : {- empty -} { ([], Nothing) } + | '::' gtycon { ([mu AnnDcolon $1], Just $2) } + +sigtype :: { LHsType GhcPs } + : ctype { $1 } + +sigtypedoc :: { LHsType GhcPs } + : ctypedoc { $1 } + + +sig_vars :: { Located [Located RdrName] } -- Returned in reversed order + : sig_vars ',' var {% addAnnotation (gl $ head $ unLoc $1) + AnnComma (gl $2) + >> return (sLL $1 $> ($3 : unLoc $1)) } + | var { sL1 $1 [$1] } + +sigtypes1 :: { (OrdList (LHsSigType GhcPs)) } + : sigtype { unitOL (mkLHsSigType $1) } + | sigtype ',' sigtypes1 {% addAnnotation (gl $1) AnnComma (gl $2) + >> return (unitOL (mkLHsSigType $1) `appOL` $3) } + +----------------------------------------------------------------------------- +-- Types + +unpackedness :: { Located ([AddAnn], SourceText, SrcUnpackedness) } + : '{-# UNPACK' '#-}' { sLL $1 $> ([mo $1, mc $2], getUNPACK_PRAGs $1, SrcUnpack) } + | '{-# NOUNPACK' '#-}' { sLL $1 $> ([mo $1, mc $2], getNOUNPACK_PRAGs $1, SrcNoUnpack) } + +forall_vis_flag :: { (AddAnn, ForallVisFlag) } + : '.' { (mj AnnDot $1, ForallInvis) } + | '->' { (mu AnnRarrow $1, ForallVis) } + +-- A ktype/ktypedoc is a ctype/ctypedoc, possibly with a kind annotation +ktype :: { LHsType GhcPs } + : ctype { $1 } + | ctype '::' kind {% ams (sLL $1 $> $ HsKindSig noExtField $1 $3) + [mu AnnDcolon $2] } + +ktypedoc :: { LHsType GhcPs } + : ctypedoc { $1 } + | ctypedoc '::' kind {% ams (sLL $1 $> $ HsKindSig noExtField $1 $3) + [mu AnnDcolon $2] } + +-- A ctype is a for-all type +ctype :: { LHsType GhcPs } + : 'forall' tv_bndrs forall_vis_flag ctype + {% let (fv_ann, fv_flag) = $3 in + hintExplicitForall $1 *> + ams (sLL $1 $> $ + HsForAllTy { hst_fvf = fv_flag + , hst_bndrs = $2 + , hst_xforall = noExtField + , hst_body = $4 }) + [mu AnnForall $1,fv_ann] } + | context '=>' ctype {% addAnnotation (gl $1) (toUnicodeAnn AnnDarrow $2) (gl $2) + >> return (sLL $1 $> $ + HsQualTy { hst_ctxt = $1 + , hst_xqual = noExtField + , hst_body = $3 }) } + | ipvar '::' type {% ams (sLL $1 $> (HsIParamTy noExtField $1 $3)) + [mu AnnDcolon $2] } + | type { $1 } + +-- Note [ctype and ctypedoc] +-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +-- It would have been nice to simplify the grammar by unifying `ctype` and +-- ctypedoc` into one production, allowing comments on types everywhere (and +-- rejecting them after parsing, where necessary). This is however not possible +-- since it leads to ambiguity. The reason is the support for comments on record +-- fields: +-- data R = R { field :: Int -- ^ comment on the field } +-- If we allow comments on types here, it's not clear if the comment applies +-- to 'field' or to 'Int'. So we must use `ctype` to describe the type. + +ctypedoc :: { LHsType GhcPs } + : 'forall' tv_bndrs forall_vis_flag ctypedoc + {% let (fv_ann, fv_flag) = $3 in + hintExplicitForall $1 *> + ams (sLL $1 $> $ + HsForAllTy { hst_fvf = fv_flag + , hst_bndrs = $2 + , hst_xforall = noExtField + , hst_body = $4 }) + [mu AnnForall $1,fv_ann] } + | context '=>' ctypedoc {% addAnnotation (gl $1) (toUnicodeAnn AnnDarrow $2) (gl $2) + >> return (sLL $1 $> $ + HsQualTy { hst_ctxt = $1 + , hst_xqual = noExtField + , hst_body = $3 }) } + | ipvar '::' type {% ams (sLL $1 $> (HsIParamTy noExtField $1 $3)) + [mu AnnDcolon $2] } + | typedoc { $1 } + +---------------------- +-- Notes for 'context' +-- 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 GhcPs } + : btype {% do { (anns,ctx) <- checkContext $1 + ; if null (unLoc ctx) + then addAnnotation (gl $1) AnnUnit (gl $1) + else return () + ; ams ctx anns + } } + +-- See Note [Constr variations of non-terminals] +constr_context :: { LHsContext GhcPs } + : constr_btype {% do { (anns,ctx) <- checkContext $1 + ; if null (unLoc ctx) + then addAnnotation (gl $1) AnnUnit (gl $1) + else return () + ; ams ctx anns + } } + +{- Note [GADT decl discards annotations] +~~~~~~~~~~~~~~~~~~~~~ +The type production for + + btype `->` ctypedoc + btype docprev `->` ctypedoc + +add the AnnRarrow annotation twice, in different places. + +This is because if the type is processed as usual, it belongs on the annotations +for the type as a whole. + +But if the type is passed to mkGadtDecl, it discards the top level SrcSpan, and +the top-level annotation will be disconnected. Hence for this specific case it +is connected to the first type too. +-} + +type :: { LHsType GhcPs } + : btype { $1 } + | btype '->' ctype {% ams $1 [mu AnnRarrow $2] -- See note [GADT decl discards annotations] + >> ams (sLL $1 $> $ HsFunTy noExtField $1 $3) + [mu AnnRarrow $2] } + + +typedoc :: { LHsType GhcPs } + : btype { $1 } + | btype docprev { sLL $1 $> $ HsDocTy noExtField $1 $2 } + | docnext btype { sLL $1 $> $ HsDocTy noExtField $2 $1 } + | btype '->' ctypedoc {% ams $1 [mu AnnRarrow $2] -- See note [GADT decl discards annotations] + >> ams (sLL $1 $> $ HsFunTy noExtField $1 $3) + [mu AnnRarrow $2] } + | btype docprev '->' ctypedoc {% ams $1 [mu AnnRarrow $3] -- See note [GADT decl discards annotations] + >> ams (sLL $1 $> $ + HsFunTy noExtField (L (comb2 $1 $2) + (HsDocTy noExtField $1 $2)) + $4) + [mu AnnRarrow $3] } + | docnext btype '->' ctypedoc {% ams $2 [mu AnnRarrow $3] -- See note [GADT decl discards annotations] + >> ams (sLL $1 $> $ + HsFunTy noExtField (L (comb2 $1 $2) + (HsDocTy noExtField $2 $1)) + $4) + [mu AnnRarrow $3] } + +-- See Note [Constr variations of non-terminals] +constr_btype :: { LHsType GhcPs } + : constr_tyapps {% mergeOps (unLoc $1) } + +-- See Note [Constr variations of non-terminals] +constr_tyapps :: { Located [Located TyEl] } -- NB: This list is reversed + : constr_tyapp { sL1 $1 [$1] } + | constr_tyapps constr_tyapp { sLL $1 $> $ $2 : (unLoc $1) } + +-- See Note [Constr variations of non-terminals] +constr_tyapp :: { Located TyEl } + : tyapp { $1 } + | docprev { sL1 $1 $ TyElDocPrev (unLoc $1) } + +btype :: { LHsType GhcPs } + : tyapps {% mergeOps $1 } + +tyapps :: { [Located TyEl] } -- NB: This list is reversed + : tyapp { [$1] } + | tyapps tyapp { $2 : $1 } + +tyapp :: { Located TyEl } + : atype { sL1 $1 $ TyElOpd (unLoc $1) } + + -- See Note [Whitespace-sensitive operator parsing] in GHC.Parser.Lexer + | PREFIX_AT atype { sLL $1 $> $ (TyElKindApp (comb2 $1 $2) $2) } + + | qtyconop { sL1 $1 $ TyElOpr (unLoc $1) } + | tyvarop { sL1 $1 $ TyElOpr (unLoc $1) } + | SIMPLEQUOTE qconop {% ams (sLL $1 $> $ TyElOpr (unLoc $2)) + [mj AnnSimpleQuote $1,mj AnnVal $2] } + | SIMPLEQUOTE varop {% ams (sLL $1 $> $ TyElOpr (unLoc $2)) + [mj AnnSimpleQuote $1,mj AnnVal $2] } + | unpackedness { sL1 $1 $ TyElUnpackedness (unLoc $1) } + +atype :: { LHsType GhcPs } + : ntgtycon { sL1 $1 (HsTyVar noExtField NotPromoted $1) } -- Not including unit tuples + | tyvar { sL1 $1 (HsTyVar noExtField NotPromoted $1) } -- (See Note [Unit tuples]) + | '*' {% do { warnStarIsType (getLoc $1) + ; return $ sL1 $1 (HsStarTy noExtField (isUnicode $1)) } } + + -- See Note [Whitespace-sensitive operator parsing] in GHC.Parser.Lexer + | PREFIX_TILDE atype {% ams (sLL $1 $> (mkBangTy SrcLazy $2)) [mj AnnTilde $1] } + | PREFIX_BANG atype {% ams (sLL $1 $> (mkBangTy SrcStrict $2)) [mj AnnBang $1] } + + | '{' fielddecls '}' {% amms (checkRecordSyntax + (sLL $1 $> $ HsRecTy noExtField $2)) + -- Constructor sigs only + [moc $1,mcc $3] } + | '(' ')' {% ams (sLL $1 $> $ HsTupleTy noExtField + HsBoxedOrConstraintTuple []) + [mop $1,mcp $2] } + | '(' ktype ',' comma_types1 ')' {% addAnnotation (gl $2) AnnComma + (gl $3) >> + ams (sLL $1 $> $ HsTupleTy noExtField + + HsBoxedOrConstraintTuple ($2 : $4)) + [mop $1,mcp $5] } + | '(#' '#)' {% ams (sLL $1 $> $ HsTupleTy noExtField HsUnboxedTuple []) + [mo $1,mc $2] } + | '(#' comma_types1 '#)' {% ams (sLL $1 $> $ HsTupleTy noExtField HsUnboxedTuple $2) + [mo $1,mc $3] } + | '(#' bar_types2 '#)' {% ams (sLL $1 $> $ HsSumTy noExtField $2) + [mo $1,mc $3] } + | '[' ktype ']' {% ams (sLL $1 $> $ HsListTy noExtField $2) [mos $1,mcs $3] } + | '(' ktype ')' {% ams (sLL $1 $> $ HsParTy noExtField $2) [mop $1,mcp $3] } + | quasiquote { mapLoc (HsSpliceTy noExtField) $1 } + | splice_untyped { mapLoc (HsSpliceTy noExtField) $1 } + -- see Note [Promotion] for the followings + | SIMPLEQUOTE qcon_nowiredlist {% ams (sLL $1 $> $ HsTyVar noExtField IsPromoted $2) [mj AnnSimpleQuote $1,mj AnnName $2] } + | SIMPLEQUOTE '(' ktype ',' comma_types1 ')' + {% addAnnotation (gl $3) AnnComma (gl $4) >> + ams (sLL $1 $> $ HsExplicitTupleTy noExtField ($3 : $5)) + [mj AnnSimpleQuote $1,mop $2,mcp $6] } + | SIMPLEQUOTE '[' comma_types0 ']' {% ams (sLL $1 $> $ HsExplicitListTy noExtField IsPromoted $3) + [mj AnnSimpleQuote $1,mos $2,mcs $4] } + | SIMPLEQUOTE var {% ams (sLL $1 $> $ HsTyVar noExtField IsPromoted $2) + [mj AnnSimpleQuote $1,mj AnnName $2] } + + -- Two or more [ty, ty, ty] must be a promoted list type, just as + -- if you had written '[ty, ty, ty] + -- (One means a list type, zero means the list type constructor, + -- so you have to quote those.) + | '[' ktype ',' comma_types1 ']' {% addAnnotation (gl $2) AnnComma + (gl $3) >> + ams (sLL $1 $> $ HsExplicitListTy noExtField NotPromoted ($2 : $4)) + [mos $1,mcs $5] } + | INTEGER { sLL $1 $> $ HsTyLit noExtField $ HsNumTy (getINTEGERs $1) + (il_value (getINTEGER $1)) } + | STRING { sLL $1 $> $ HsTyLit noExtField $ HsStrTy (getSTRINGs $1) + (getSTRING $1) } + | '_' { sL1 $1 $ mkAnonWildCardTy } + +-- 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 for convenience. +inst_type :: { LHsSigType GhcPs } + : sigtype { mkLHsSigType $1 } + +deriv_types :: { [LHsSigType GhcPs] } + : ktypedoc { [mkLHsSigType $1] } + + | ktypedoc ',' deriv_types {% addAnnotation (gl $1) AnnComma (gl $2) + >> return (mkLHsSigType $1 : $3) } + +comma_types0 :: { [LHsType GhcPs] } -- Zero or more: ty,ty,ty + : comma_types1 { $1 } + | {- empty -} { [] } + +comma_types1 :: { [LHsType GhcPs] } -- One or more: ty,ty,ty + : ktype { [$1] } + | ktype ',' comma_types1 {% addAnnotation (gl $1) AnnComma (gl $2) + >> return ($1 : $3) } + +bar_types2 :: { [LHsType GhcPs] } -- Two or more: ty|ty|ty + : ktype '|' ktype {% addAnnotation (gl $1) AnnVbar (gl $2) + >> return [$1,$3] } + | ktype '|' bar_types2 {% addAnnotation (gl $1) AnnVbar (gl $2) + >> return ($1 : $3) } + +tv_bndrs :: { [LHsTyVarBndr GhcPs] } + : tv_bndr tv_bndrs { $1 : $2 } + | {- empty -} { [] } + +tv_bndr :: { LHsTyVarBndr GhcPs } + : tyvar { sL1 $1 (UserTyVar noExtField $1) } + | '(' tyvar '::' kind ')' {% ams (sLL $1 $> (KindedTyVar noExtField $2 $4)) + [mop $1,mu AnnDcolon $3 + ,mcp $5] } + +fds :: { Located ([AddAnn],[Located (FunDep (Located RdrName))]) } + : {- empty -} { noLoc ([],[]) } + | '|' fds1 { (sLL $1 $> ([mj AnnVbar $1] + ,reverse (unLoc $2))) } + +fds1 :: { Located [Located (FunDep (Located RdrName))] } + : fds1 ',' fd {% addAnnotation (gl $ head $ unLoc $1) AnnComma (gl $2) + >> return (sLL $1 $> ($3 : unLoc $1)) } + | fd { sL1 $1 [$1] } + +fd :: { Located (FunDep (Located RdrName)) } + : varids0 '->' varids0 {% ams (L (comb3 $1 $2 $3) + (reverse (unLoc $1), reverse (unLoc $3))) + [mu AnnRarrow $2] } + +varids0 :: { Located [Located RdrName] } + : {- empty -} { noLoc [] } + | varids0 tyvar { sLL $1 $> ($2 : unLoc $1) } + +----------------------------------------------------------------------------- +-- Kinds + +kind :: { LHsKind GhcPs } + : ctype { $1 } + +{- Note [Promotion] + ~~~~~~~~~~~~~~~~ + +- Syntax of promoted qualified names +We write 'Nat.Zero instead of Nat.'Zero when dealing with qualified +names. Moreover ticks are only allowed in types, not in kinds, for a +few reasons: + 1. we don't need quotes since we cannot define names in kinds + 2. if one day we merge types and kinds, tick would mean look in DataName + 3. we don't have a kind namespace anyway + +- Name resolution +When the user write Zero instead of 'Zero in types, we parse it a +HsTyVar ("Zero", TcClsName) instead of HsTyVar ("Zero", DataName). We +deal with this in the renamer. If a HsTyVar ("Zero", TcClsName) is not +bounded in the type level, then we look for it in the term level (we +change its namespace to DataName, see Note [Demotion] in GHC.Types.Names.OccName). +And both become a HsTyVar ("Zero", DataName) after the renamer. + +-} + + +----------------------------------------------------------------------------- +-- Datatype declarations + +gadt_constrlist :: { Located ([AddAnn] + ,[LConDecl GhcPs]) } -- Returned in order + + : 'where' '{' gadt_constrs '}' {% checkEmptyGADTs $ + L (comb2 $1 $3) + ([mj AnnWhere $1 + ,moc $2 + ,mcc $4] + , unLoc $3) } + | 'where' vocurly gadt_constrs close {% checkEmptyGADTs $ + L (comb2 $1 $3) + ([mj AnnWhere $1] + , unLoc $3) } + | {- empty -} { noLoc ([],[]) } + +gadt_constrs :: { Located [LConDecl GhcPs] } + : gadt_constr_with_doc ';' gadt_constrs + {% addAnnotation (gl $1) AnnSemi (gl $2) + >> return (L (comb2 $1 $3) ($1 : unLoc $3)) } + | gadt_constr_with_doc { L (gl $1) [$1] } + | {- empty -} { noLoc [] } + +-- 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_with_doc :: { LConDecl GhcPs } +gadt_constr_with_doc + : maybe_docnext ';' gadt_constr + {% return $ addConDoc $3 $1 } + | gadt_constr + {% return $1 } + +gadt_constr :: { LConDecl GhcPs } + -- see Note [Difference in parsing GADT and data constructors] + -- Returns a list because of: C,D :: ty + : con_list '::' sigtypedoc + {% let (gadt,anns) = mkGadtDecl (unLoc $1) $3 + in ams (sLL $1 $> gadt) + (mu AnnDcolon $2:anns) } + +{- Note [Difference in parsing GADT and data constructors] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +GADT constructors have simpler syntax than usual data constructors: +in GADTs, types cannot occur to the left of '::', so they cannot be mixed +with constructor names (see Note [Parsing data constructors is hard]). + +Due to simplified syntax, GADT constructor names (left-hand side of '::') +use simpler grammar production than usual data constructor names. As a +consequence, GADT constructor names are restricted (names like '(*)' are +allowed in usual data constructors, but not in GADTs). +-} + +constrs :: { Located ([AddAnn],[LConDecl GhcPs]) } + : maybe_docnext '=' constrs1 { L (comb2 $2 $3) ([mj AnnEqual $2] + ,addConDocs (unLoc $3) $1)} + +constrs1 :: { Located [LConDecl GhcPs] } + : constrs1 maybe_docnext '|' maybe_docprev constr + {% addAnnotation (gl $ head $ unLoc $1) AnnVbar (gl $3) + >> return (sLL $1 $> (addConDoc $5 $2 : addConDocFirst (unLoc $1) $4)) } + | constr { sL1 $1 [$1] } + +{- Note [Constr variations of non-terminals] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In record declarations we assume that 'ctype' used to parse the type will not +consume the trailing docprev: + + data R = R { field :: Int -- ^ comment on the field } + +In 'R' we expect the comment to apply to the entire field, not to 'Int'. The +same issue is detailed in Note [ctype and ctypedoc]. + +So, we do not want 'ctype' to consume 'docprev', therefore + we do not want 'btype' to consume 'docprev', therefore + we do not want 'tyapps' to consume 'docprev'. + +At the same time, when parsing a 'constr', we do want to consume 'docprev': + + data T = C Int -- ^ comment on Int + Bool -- ^ comment on Bool + +So, we do want 'constr_stuff' to consume 'docprev'. + +The problem arises because the clauses in 'constr' have the following +structure: + + (a) context '=>' constr_stuff (e.g. data T a = Ord a => C a) + (b) constr_stuff (e.g. data T a = C a) + +and to avoid a reduce/reduce conflict, 'context' and 'constr_stuff' must be +compatible. And for 'context' to be compatible with 'constr_stuff', it must +consume 'docprev'. + +So, we want 'context' to consume 'docprev', therefore + we want 'btype' to consume 'docprev', therefore + we want 'tyapps' to consume 'docprev'. + +Our requirements end up conflicting: for parsing record types, we want 'tyapps' +to leave 'docprev' alone, but for parsing constructors, we want it to consume +'docprev'. + +As the result, we maintain two parallel hierarchies of non-terminals that +either consume 'docprev' or not: + + tyapps constr_tyapps + btype constr_btype + context constr_context + ... + +They must be kept identical except for their treatment of 'docprev'. + +-} + +constr :: { LConDecl GhcPs } + : maybe_docnext forall constr_context '=>' constr_stuff + {% ams (let (con,details,doc_prev) = unLoc $5 in + addConDoc (L (comb4 $2 $3 $4 $5) (mkConDeclH98 con + (snd $ unLoc $2) + (Just $3) + details)) + ($1 `mplus` doc_prev)) + (mu AnnDarrow $4:(fst $ unLoc $2)) } + | maybe_docnext forall constr_stuff + {% ams ( let (con,details,doc_prev) = unLoc $3 in + addConDoc (L (comb2 $2 $3) (mkConDeclH98 con + (snd $ unLoc $2) + Nothing -- No context + details)) + ($1 `mplus` doc_prev)) + (fst $ unLoc $2) } + +forall :: { Located ([AddAnn], Maybe [LHsTyVarBndr GhcPs]) } + : 'forall' tv_bndrs '.' { sLL $1 $> ([mu AnnForall $1,mj AnnDot $3], Just $2) } + | {- empty -} { noLoc ([], Nothing) } + +constr_stuff :: { Located (Located RdrName, HsConDeclDetails GhcPs, Maybe LHsDocString) } + : constr_tyapps {% do { c <- mergeDataCon (unLoc $1) + ; return $ sL1 $1 c } } + +fielddecls :: { [LConDeclField GhcPs] } + : {- empty -} { [] } + | fielddecls1 { $1 } + +fielddecls1 :: { [LConDeclField GhcPs] } + : fielddecl maybe_docnext ',' maybe_docprev fielddecls1 + {% addAnnotation (gl $1) AnnComma (gl $3) >> + return ((addFieldDoc $1 $4) : addFieldDocs $5 $2) } + | fielddecl { [$1] } + +fielddecl :: { LConDeclField GhcPs } + -- A list because of f,g :: Int + : maybe_docnext sig_vars '::' ctype maybe_docprev + {% ams (L (comb2 $2 $4) + (ConDeclField noExtField (reverse (map (\ln@(L l n) -> L l $ FieldOcc noExtField ln) (unLoc $2))) $4 ($1 `mplus` $5))) + [mu AnnDcolon $3] } + +-- Reversed! +maybe_derivings :: { HsDeriving GhcPs } + : {- empty -} { noLoc [] } + | derivings { $1 } + +-- A list of one or more deriving clauses at the end of a datatype +derivings :: { HsDeriving GhcPs } + : derivings deriving { sLL $1 $> $ $2 : unLoc $1 } + | deriving { sLL $1 $> [$1] } + +-- The outer Located is just to allow the caller to +-- know the rightmost extremity of the 'deriving' clause +deriving :: { LHsDerivingClause GhcPs } + : 'deriving' deriv_clause_types + {% let { full_loc = comb2 $1 $> } + in ams (L full_loc $ HsDerivingClause noExtField Nothing $2) + [mj AnnDeriving $1] } + + | 'deriving' deriv_strategy_no_via deriv_clause_types + {% let { full_loc = comb2 $1 $> } + in ams (L full_loc $ HsDerivingClause noExtField (Just $2) $3) + [mj AnnDeriving $1] } + + | 'deriving' deriv_clause_types deriv_strategy_via + {% let { full_loc = comb2 $1 $> } + in ams (L full_loc $ HsDerivingClause noExtField (Just $3) $2) + [mj AnnDeriving $1] } + +deriv_clause_types :: { Located [LHsSigType GhcPs] } + : qtycondoc { sL1 $1 [mkLHsSigType $1] } + | '(' ')' {% ams (sLL $1 $> []) + [mop $1,mcp $2] } + | '(' deriv_types ')' {% ams (sLL $1 $> $2) + [mop $1,mcp $3] } + -- Glasgow extension: allow partial + -- applications in derivings + +----------------------------------------------------------------------------- +-- Value definitions + +{- Note [Declaration/signature overlap] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +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. +-} + +docdecl :: { LHsDecl GhcPs } + : docdecld { sL1 $1 (DocD noExtField (unLoc $1)) } + +docdecld :: { LDocDecl } + : docnext { sL1 $1 (DocCommentNext (unLoc $1)) } + | docprev { sL1 $1 (DocCommentPrev (unLoc $1)) } + | docnamed { sL1 $1 (case (unLoc $1) of (n, doc) -> DocCommentNamed n doc) } + | docsection { sL1 $1 (case (unLoc $1) of (n, doc) -> DocGroup n doc) } + +decl_no_th :: { LHsDecl GhcPs } + : sigdecl { $1 } + + | infixexp opt_sig rhs {% runECP_P $1 >>= \ $1 -> + do { (ann,r) <- checkValDef $1 (snd $2) $3; + let { l = comb2 $1 $> }; + -- Depending upon what the pattern looks like we might get either + -- a FunBind or PatBind back from checkValDef. See Note + -- [FunBind vs PatBind] + case r of { + (FunBind _ n _ _) -> + amsL l (mj AnnFunId n:(fst $2)) >> return () ; + (PatBind _ (L lh _lhs) _rhs _) -> + amsL lh (fst $2) >> return () } ; + _ <- amsL l (ann ++ (fst $ unLoc $3)); + return $! (sL l $ ValD noExtField r) } } + | pattern_synonym_decl { $1 } + | docdecl { $1 } + +decl :: { LHsDecl GhcPs } + : decl_no_th { $1 } + + -- Why do we only allow naked declaration splices in top-level + -- declarations and not here? Short answer: because readFail009 + -- fails terribly with a panic in cvBindsAndSigs otherwise. + | splice_exp { sLL $1 $> $ mkSpliceDecl $1 } + +rhs :: { Located ([AddAnn],GRHSs GhcPs (LHsExpr GhcPs)) } + : '=' exp wherebinds {% runECP_P $2 >>= \ $2 -> return $ + sL (comb3 $1 $2 $3) + ((mj AnnEqual $1 : (fst $ unLoc $3)) + ,GRHSs noExtField (unguardedRHS (comb3 $1 $2 $3) $2) + (snd $ unLoc $3)) } + | gdrhs wherebinds { sLL $1 $> (fst $ unLoc $2 + ,GRHSs noExtField (reverse (unLoc $1)) + (snd $ unLoc $2)) } + +gdrhs :: { Located [LGRHS GhcPs (LHsExpr GhcPs)] } + : gdrhs gdrh { sLL $1 $> ($2 : unLoc $1) } + | gdrh { sL1 $1 [$1] } + +gdrh :: { LGRHS GhcPs (LHsExpr GhcPs) } + : '|' guardquals '=' exp {% runECP_P $4 >>= \ $4 -> + ams (sL (comb2 $1 $>) $ GRHS noExtField (unLoc $2) $4) + [mj AnnVbar $1,mj AnnEqual $3] } + +sigdecl :: { LHsDecl GhcPs } + : + -- See Note [Declaration/signature overlap] for why we need infixexp here + infixexp '::' sigtypedoc + {% do { $1 <- runECP_P $1 + ; v <- checkValSigLhs $1 + ; _ <- amsL (comb2 $1 $>) [mu AnnDcolon $2] + ; return (sLL $1 $> $ SigD noExtField $ + TypeSig noExtField [v] (mkLHsSigWcType $3))} } + + | var ',' sig_vars '::' sigtypedoc + {% do { let sig = TypeSig noExtField ($1 : reverse (unLoc $3)) + (mkLHsSigWcType $5) + ; addAnnotation (gl $1) AnnComma (gl $2) + ; ams ( sLL $1 $> $ SigD noExtField sig ) + [mu AnnDcolon $4] } } + + | infix prec ops + {% checkPrecP $2 $3 >> + ams (sLL $1 $> $ SigD noExtField + (FixSig noExtField (FixitySig noExtField (fromOL $ unLoc $3) + (Fixity (fst $ unLoc $2) (snd $ unLoc $2) (unLoc $1))))) + [mj AnnInfix $1,mj AnnVal $2] } + + | pattern_synonym_sig { sLL $1 $> . SigD noExtField . unLoc $ $1 } + + | '{-# COMPLETE' con_list opt_tyconsig '#-}' + {% let (dcolon, tc) = $3 + in ams + (sLL $1 $> + (SigD noExtField (CompleteMatchSig noExtField (getCOMPLETE_PRAGs $1) $2 tc))) + ([ mo $1 ] ++ dcolon ++ [mc $4]) } + + -- This rule is for both INLINE and INLINABLE pragmas + | '{-# INLINE' activation qvar '#-}' + {% ams ((sLL $1 $> $ SigD noExtField (InlineSig noExtField $3 + (mkInlinePragma (getINLINE_PRAGs $1) (getINLINE $1) + (snd $2))))) + ((mo $1:fst $2) ++ [mc $4]) } + + | '{-# SCC' qvar '#-}' + {% ams (sLL $1 $> (SigD noExtField (SCCFunSig noExtField (getSCC_PRAGs $1) $2 Nothing))) + [mo $1, mc $3] } + + | '{-# SCC' qvar STRING '#-}' + {% do { scc <- getSCC $3 + ; let str_lit = StringLiteral (getSTRINGs $3) scc + ; ams (sLL $1 $> (SigD noExtField (SCCFunSig noExtField (getSCC_PRAGs $1) $2 (Just ( sL1 $3 str_lit))))) + [mo $1, mc $4] } } + + | '{-# SPECIALISE' activation qvar '::' sigtypes1 '#-}' + {% ams ( + let inl_prag = mkInlinePragma (getSPEC_PRAGs $1) + (NoUserInline, FunLike) (snd $2) + in sLL $1 $> $ SigD noExtField (SpecSig noExtField $3 (fromOL $5) inl_prag)) + (mo $1:mu AnnDcolon $4:mc $6:(fst $2)) } + + | '{-# SPECIALISE_INLINE' activation qvar '::' sigtypes1 '#-}' + {% ams (sLL $1 $> $ SigD noExtField (SpecSig noExtField $3 (fromOL $5) + (mkInlinePragma (getSPEC_INLINE_PRAGs $1) + (getSPEC_INLINE $1) (snd $2)))) + (mo $1:mu AnnDcolon $4:mc $6:(fst $2)) } + + | '{-# SPECIALISE' 'instance' inst_type '#-}' + {% ams (sLL $1 $> + $ SigD noExtField (SpecInstSig noExtField (getSPEC_PRAGs $1) $3)) + [mo $1,mj AnnInstance $2,mc $4] } + + -- A minimal complete definition + | '{-# MINIMAL' name_boolformula_opt '#-}' + {% ams (sLL $1 $> $ SigD noExtField (MinimalSig noExtField (getMINIMAL_PRAGs $1) $2)) + [mo $1,mc $3] } + +activation :: { ([AddAnn],Maybe Activation) } + : {- empty -} { ([],Nothing) } + | explicit_activation { (fst $1,Just (snd $1)) } + +explicit_activation :: { ([AddAnn],Activation) } -- In brackets + : '[' INTEGER ']' { ([mj AnnOpenS $1,mj AnnVal $2,mj AnnCloseS $3] + ,ActiveAfter (getINTEGERs $2) (fromInteger (il_value (getINTEGER $2)))) } + | '[' rule_activation_marker INTEGER ']' + { ($2++[mj AnnOpenS $1,mj AnnVal $3,mj AnnCloseS $4] + ,ActiveBefore (getINTEGERs $3) (fromInteger (il_value (getINTEGER $3)))) } + +----------------------------------------------------------------------------- +-- Expressions + +quasiquote :: { Located (HsSplice GhcPs) } + : TH_QUASIQUOTE { let { loc = getLoc $1 + ; ITquasiQuote (quoter, quote, quoteSpan) = unLoc $1 + ; quoterId = mkUnqual varName quoter } + in sL1 $1 (mkHsQuasiQuote quoterId (mkSrcSpanPs quoteSpan) quote) } + | TH_QQUASIQUOTE { let { loc = getLoc $1 + ; ITqQuasiQuote (qual, quoter, quote, quoteSpan) = unLoc $1 + ; quoterId = mkQual varName (qual, quoter) } + in sL (getLoc $1) (mkHsQuasiQuote quoterId (mkSrcSpanPs quoteSpan) quote) } + +exp :: { ECP } + : infixexp '::' sigtype + { ECP $ + runECP_PV $1 >>= \ $1 -> + rejectPragmaPV $1 >> + amms (mkHsTySigPV (comb2 $1 $>) $1 $3) + [mu AnnDcolon $2] } + | infixexp '-<' exp {% runECP_P $1 >>= \ $1 -> + runECP_P $3 >>= \ $3 -> + fmap ecpFromCmd $ + ams (sLL $1 $> $ HsCmdArrApp noExtField $1 $3 + HsFirstOrderApp True) + [mu Annlarrowtail $2] } + | infixexp '>-' exp {% runECP_P $1 >>= \ $1 -> + runECP_P $3 >>= \ $3 -> + fmap ecpFromCmd $ + ams (sLL $1 $> $ HsCmdArrApp noExtField $3 $1 + HsFirstOrderApp False) + [mu Annrarrowtail $2] } + | infixexp '-<<' exp {% runECP_P $1 >>= \ $1 -> + runECP_P $3 >>= \ $3 -> + fmap ecpFromCmd $ + ams (sLL $1 $> $ HsCmdArrApp noExtField $1 $3 + HsHigherOrderApp True) + [mu AnnLarrowtail $2] } + | infixexp '>>-' exp {% runECP_P $1 >>= \ $1 -> + runECP_P $3 >>= \ $3 -> + fmap ecpFromCmd $ + ams (sLL $1 $> $ HsCmdArrApp noExtField $3 $1 + HsHigherOrderApp False) + [mu AnnRarrowtail $2] } + | infixexp { $1 } + | exp_prag(exp) { $1 } -- See Note [Pragmas and operator fixity] + +infixexp :: { ECP } + : exp10 { $1 } + | infixexp qop exp10p -- See Note [Pragmas and operator fixity] + { ECP $ + superInfixOp $ + $2 >>= \ $2 -> + runECP_PV $1 >>= \ $1 -> + runECP_PV $3 >>= \ $3 -> + rejectPragmaPV $1 >> + amms (mkHsOpAppPV (comb2 $1 $>) $1 $2 $3) + [mj AnnVal $2] } + -- AnnVal annotation for NPlusKPat, which discards the operator + +exp10p :: { ECP } + : exp10 { $1 } + | exp_prag(exp10p) { $1 } -- See Note [Pragmas and operator fixity] + +exp_prag(e) :: { ECP } + : prag_e e -- See Note [Pragmas and operator fixity] + {% runECP_P $2 >>= \ $2 -> + fmap ecpFromExp $ + ams (sLL $1 $> $ HsPragE noExtField (snd $ unLoc $1) $2) + (fst $ unLoc $1) } + +exp10 :: { ECP } + : '-' fexp { ECP $ + runECP_PV $2 >>= \ $2 -> + amms (mkHsNegAppPV (comb2 $1 $>) $2) + [mj AnnMinus $1] } + | fexp { $1 } + +optSemi :: { ([Located Token],Bool) } + : ';' { ([$1],True) } + | {- empty -} { ([],False) } + +{- Note [Pragmas and operator fixity] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +'prag_e' is an expression pragma, such as {-# SCC ... #-}, {-# CORE ... #-}, or +{-# GENERATED ... #-}. + +It must be used with care, or else #15730 happens. Consider this infix +expression: + + 1 / 2 / 2 + +There are two ways to parse it: + + 1. (1 / 2) / 2 = 0.25 + 2. 1 / (2 / 2) = 1.0 + +Due to the fixity of the (/) operator (assuming it comes from Prelude), +option 1 is the correct parse. However, in the past GHC's parser used to get +confused by the SCC annotation when it occurred in the middle of an infix +expression: + + 1 / {-# SCC ann #-} 2 / 2 -- used to get parsed as option 2 + +There are several ways to address this issue, see GHC Proposal #176 for a +detailed exposition: + + https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0176-scc-parsing.rst + +The accepted fix is to disallow pragmas that occur within infix expressions. +Infix expressions are assembled out of 'exp10', so 'exp10' must not accept +pragmas. Instead, we accept them in exactly two places: + +* at the start of an expression or a parenthesized subexpression: + + f = {-# SCC ann #-} 1 / 2 / 2 -- at the start of the expression + g = 5 + ({-# SCC ann #-} 1 / 2 / 2) -- at the start of a parenthesized subexpression + +* immediately after the last operator: + + f = 1 / 2 / {-# SCC ann #-} 2 + +In both cases, the parse does not depend on operator fixity. The second case +may sound unnecessary, but it's actually needed to support a common idiom: + + f $ {-# SCC ann $-} ... + +-} +prag_e :: { Located ([AddAnn], HsPragE GhcPs) } + : '{-# SCC' STRING '#-}' {% do scc <- getSCC $2 + ; return $ sLL $1 $> + ([mo $1,mj AnnValStr $2,mc $3], + HsPragSCC noExtField + (getSCC_PRAGs $1) + (StringLiteral (getSTRINGs $2) scc)) } + | '{-# SCC' VARID '#-}' { sLL $1 $> ([mo $1,mj AnnVal $2,mc $3], + HsPragSCC noExtField + (getSCC_PRAGs $1) + (StringLiteral NoSourceText (getVARID $2))) } + | '{-# GENERATED' STRING INTEGER ':' INTEGER '-' INTEGER ':' INTEGER '#-}' + { let getINT = fromInteger . il_value . getINTEGER in + sLL $1 $> $ ([mo $1,mj AnnVal $2 + ,mj AnnVal $3,mj AnnColon $4 + ,mj AnnVal $5,mj AnnMinus $6 + ,mj AnnVal $7,mj AnnColon $8 + ,mj AnnVal $9,mc $10], + HsPragTick noExtField + (getGENERATED_PRAGs $1) + (getStringLiteral $2, + (getINT $3, getINT $5), + (getINT $7, getINT $9)) + ((getINTEGERs $3, getINTEGERs $5), + (getINTEGERs $7, getINTEGERs $9) )) } + | '{-# CORE' STRING '#-}' + { sLL $1 $> $ + ([mo $1,mj AnnVal $2,mc $3], + HsPragCore noExtField (getCORE_PRAGs $1) (getStringLiteral $2)) } + +fexp :: { ECP } + : fexp aexp { ECP $ + superFunArg $ + runECP_PV $1 >>= \ $1 -> + runECP_PV $2 >>= \ $2 -> + mkHsAppPV (comb2 $1 $>) $1 $2 } + + -- See Note [Whitespace-sensitive operator parsing] in GHC.Parser.Lexer + | fexp PREFIX_AT atype {% runECP_P $1 >>= \ $1 -> + runPV (checkExpBlockArguments $1) >>= \_ -> + fmap ecpFromExp $ + ams (sLL $1 $> $ HsAppType noExtField $1 (mkHsWildCardBndrs $3)) + [mj AnnAt $2] } + + | 'static' aexp {% runECP_P $2 >>= \ $2 -> + fmap ecpFromExp $ + ams (sLL $1 $> $ HsStatic noExtField $2) + [mj AnnStatic $1] } + | aexp { $1 } + +aexp :: { ECP } + -- See Note [Whitespace-sensitive operator parsing] in GHC.Parser.Lexer + : qvar TIGHT_INFIX_AT aexp + { ECP $ + runECP_PV $3 >>= \ $3 -> + amms (mkHsAsPatPV (comb2 $1 $>) $1 $3) [mj AnnAt $2] } + + -- See Note [Whitespace-sensitive operator parsing] in GHC.Parser.Lexer + | PREFIX_TILDE aexp { ECP $ + runECP_PV $2 >>= \ $2 -> + amms (mkHsLazyPatPV (comb2 $1 $>) $2) [mj AnnTilde $1] } + | PREFIX_BANG aexp { ECP $ + runECP_PV $2 >>= \ $2 -> + amms (mkHsBangPatPV (comb2 $1 $>) $2) [mj AnnBang $1] } + + | '\\' apat apats '->' exp + { ECP $ + runECP_PV $5 >>= \ $5 -> + amms (mkHsLamPV (comb2 $1 $>) (mkMatchGroup FromSource + [sLL $1 $> $ Match { m_ext = noExtField + , m_ctxt = LambdaExpr + , m_pats = $2:$3 + , m_grhss = unguardedGRHSs $5 }])) + [mj AnnLam $1, mu AnnRarrow $4] } + | 'let' binds 'in' exp { ECP $ + runECP_PV $4 >>= \ $4 -> + amms (mkHsLetPV (comb2 $1 $>) (snd (unLoc $2)) $4) + (mj AnnLet $1:mj AnnIn $3 + :(fst $ unLoc $2)) } + | '\\' 'lcase' altslist + {% runPV $3 >>= \ $3 -> + fmap ecpFromExp $ + ams (sLL $1 $> $ HsLamCase noExtField + (mkMatchGroup FromSource (snd $ unLoc $3))) + (mj AnnLam $1:mj AnnCase $2:(fst $ unLoc $3)) } + | 'if' exp optSemi 'then' exp optSemi 'else' exp + {% runECP_P $2 >>= \ $2 -> + return $ ECP $ + runECP_PV $5 >>= \ $5 -> + runECP_PV $8 >>= \ $8 -> + amms (mkHsIfPV (comb2 $1 $>) $2 (snd $3) $5 (snd $6) $8) + (mj AnnIf $1:mj AnnThen $4 + :mj AnnElse $7 + :(map (\l -> mj AnnSemi l) (fst $3)) + ++(map (\l -> mj AnnSemi l) (fst $6))) } + | 'if' ifgdpats {% hintMultiWayIf (getLoc $1) >>= \_ -> + fmap ecpFromExp $ + ams (sLL $1 $> $ HsMultiIf noExtField + (reverse $ snd $ unLoc $2)) + (mj AnnIf $1:(fst $ unLoc $2)) } + | 'case' exp 'of' altslist {% runECP_P $2 >>= \ $2 -> + return $ ECP $ + $4 >>= \ $4 -> + amms (mkHsCasePV (comb3 $1 $3 $4) $2 (mkMatchGroup + FromSource (snd $ unLoc $4))) + (mj AnnCase $1:mj AnnOf $3 + :(fst $ unLoc $4)) } + | 'do' stmtlist { ECP $ + $2 >>= \ $2 -> + amms (mkHsDoPV (comb2 $1 $2) (mapLoc snd $2)) + (mj AnnDo $1:(fst $ unLoc $2)) } + | 'mdo' stmtlist {% runPV $2 >>= \ $2 -> + fmap ecpFromExp $ + ams (L (comb2 $1 $2) + (mkHsDo MDoExpr (snd $ unLoc $2))) + (mj AnnMdo $1:(fst $ unLoc $2)) } + | 'proc' aexp '->' exp + {% (checkPattern <=< runECP_P) $2 >>= \ p -> + runECP_P $4 >>= \ $4@cmd -> + fmap ecpFromExp $ + ams (sLL $1 $> $ HsProc noExtField p (sLL $1 $> $ HsCmdTop noExtField cmd)) + -- TODO: is LL right here? + [mj AnnProc $1,mu AnnRarrow $3] } + + | aexp1 { $1 } + +aexp1 :: { ECP } + : aexp1 '{' fbinds '}' { ECP $ + runECP_PV $1 >>= \ $1 -> + $3 >>= \ $3 -> + amms (mkHsRecordPV (comb2 $1 $>) (comb2 $2 $4) $1 (snd $3)) + (moc $2:mcc $4:(fst $3)) } + | aexp2 { $1 } + +aexp2 :: { ECP } + : qvar { ECP $ mkHsVarPV $! $1 } + | qcon { ECP $ mkHsVarPV $! $1 } + | ipvar { ecpFromExp $ sL1 $1 (HsIPVar noExtField $! unLoc $1) } + | overloaded_label { ecpFromExp $ sL1 $1 (HsOverLabel noExtField Nothing $! unLoc $1) } + | literal { ECP $ mkHsLitPV $! $1 } +-- This will enable overloaded strings permanently. Normally the renamer turns HsString +-- into HsOverLit when -foverloaded-strings is on. +-- | STRING { sL (getLoc $1) (HsOverLit $! mkHsIsString (getSTRINGs $1) +-- (getSTRING $1) noExtField) } + | INTEGER { ECP $ mkHsOverLitPV (sL1 $1 $ mkHsIntegral (getINTEGER $1)) } + | RATIONAL { ECP $ mkHsOverLitPV (sL1 $1 $ mkHsFractional (getRATIONAL $1)) } + + -- N.B.: sections get parsed by these next two productions. + -- This allows you to write, e.g., '(+ 3, 4 -)', which isn't + -- correct Haskell (you'd have to write '((+ 3), (4 -))') + -- but the less cluttered version fell out of having texps. + | '(' texp ')' { ECP $ + runECP_PV $2 >>= \ $2 -> + amms (mkHsParPV (comb2 $1 $>) $2) [mop $1,mcp $3] } + | '(' tup_exprs ')' { ECP $ + $2 >>= \ $2 -> + amms (mkSumOrTuplePV (comb2 $1 $>) Boxed (snd $2)) + ((mop $1:fst $2) ++ [mcp $3]) } + + | '(#' texp '#)' { ECP $ + runECP_PV $2 >>= \ $2 -> + amms (mkSumOrTuplePV (comb2 $1 $>) Unboxed (Tuple [L (gl $2) (Just $2)])) + [mo $1,mc $3] } + | '(#' tup_exprs '#)' { ECP $ + $2 >>= \ $2 -> + amms (mkSumOrTuplePV (comb2 $1 $>) Unboxed (snd $2)) + ((mo $1:fst $2) ++ [mc $3]) } + + | '[' list ']' { ECP $ $2 (comb2 $1 $>) >>= \a -> ams a [mos $1,mcs $3] } + | '_' { ECP $ mkHsWildCardPV (getLoc $1) } + + -- Template Haskell Extension + | splice_untyped { ECP $ mkHsSplicePV $1 } + | splice_typed { ecpFromExp $ mapLoc (HsSpliceE noExtField) $1 } + + | SIMPLEQUOTE qvar {% fmap ecpFromExp $ ams (sLL $1 $> $ HsBracket noExtField (VarBr noExtField True (unLoc $2))) [mj AnnSimpleQuote $1,mj AnnName $2] } + | SIMPLEQUOTE qcon {% fmap ecpFromExp $ ams (sLL $1 $> $ HsBracket noExtField (VarBr noExtField True (unLoc $2))) [mj AnnSimpleQuote $1,mj AnnName $2] } + | TH_TY_QUOTE tyvar {% fmap ecpFromExp $ ams (sLL $1 $> $ HsBracket noExtField (VarBr noExtField False (unLoc $2))) [mj AnnThTyQuote $1,mj AnnName $2] } + | TH_TY_QUOTE gtycon {% fmap ecpFromExp $ ams (sLL $1 $> $ HsBracket noExtField (VarBr noExtField False (unLoc $2))) [mj AnnThTyQuote $1,mj AnnName $2] } + | TH_TY_QUOTE {- nothing -} {% reportEmptyDoubleQuotes (getLoc $1) } + | '[|' exp '|]' {% runECP_P $2 >>= \ $2 -> + fmap ecpFromExp $ + ams (sLL $1 $> $ HsBracket noExtField (ExpBr noExtField $2)) + (if (hasE $1) then [mj AnnOpenE $1, mu AnnCloseQ $3] + else [mu AnnOpenEQ $1,mu AnnCloseQ $3]) } + | '[||' exp '||]' {% runECP_P $2 >>= \ $2 -> + fmap ecpFromExp $ + ams (sLL $1 $> $ HsBracket noExtField (TExpBr noExtField $2)) + (if (hasE $1) then [mj AnnOpenE $1,mc $3] else [mo $1,mc $3]) } + | '[t|' ktype '|]' {% fmap ecpFromExp $ + ams (sLL $1 $> $ HsBracket noExtField (TypBr noExtField $2)) [mo $1,mu AnnCloseQ $3] } + | '[p|' infixexp '|]' {% (checkPattern <=< runECP_P) $2 >>= \p -> + fmap ecpFromExp $ + ams (sLL $1 $> $ HsBracket noExtField (PatBr noExtField p)) + [mo $1,mu AnnCloseQ $3] } + | '[d|' cvtopbody '|]' {% fmap ecpFromExp $ + ams (sLL $1 $> $ HsBracket noExtField (DecBrL noExtField (snd $2))) + (mo $1:mu AnnCloseQ $3:fst $2) } + | quasiquote { ECP $ mkHsSplicePV $1 } + + -- arrow notation extension + | '(|' aexp2 cmdargs '|)' {% runECP_P $2 >>= \ $2 -> + fmap ecpFromCmd $ + ams (sLL $1 $> $ HsCmdArrForm noExtField $2 Prefix + Nothing (reverse $3)) + [mu AnnOpenB $1,mu AnnCloseB $4] } + +splice_exp :: { LHsExpr GhcPs } + : splice_untyped { mapLoc (HsSpliceE noExtField) $1 } + | splice_typed { mapLoc (HsSpliceE noExtField) $1 } + +splice_untyped :: { Located (HsSplice GhcPs) } + -- See Note [Whitespace-sensitive operator parsing] in GHC.Parser.Lexer + : PREFIX_DOLLAR aexp2 {% runECP_P $2 >>= \ $2 -> + ams (sLL $1 $> $ mkUntypedSplice DollarSplice $2) + [mj AnnDollar $1] } + +splice_typed :: { Located (HsSplice GhcPs) } + -- See Note [Whitespace-sensitive operator parsing] in GHC.Parser.Lexer + : PREFIX_DOLLAR_DOLLAR aexp2 + {% runECP_P $2 >>= \ $2 -> + ams (sLL $1 $> $ mkTypedSplice DollarSplice $2) + [mj AnnDollarDollar $1] } + +cmdargs :: { [LHsCmdTop GhcPs] } + : cmdargs acmd { $2 : $1 } + | {- empty -} { [] } + +acmd :: { LHsCmdTop GhcPs } + : aexp2 {% runECP_P $1 >>= \ cmd -> + return (sL1 cmd $ HsCmdTop noExtField cmd) } + +cvtopbody :: { ([AddAnn],[LHsDecl GhcPs]) } + : '{' cvtopdecls0 '}' { ([mj AnnOpenC $1 + ,mj AnnCloseC $3],$2) } + | vocurly cvtopdecls0 close { ([],$2) } + +cvtopdecls0 :: { [LHsDecl GhcPs] } + : topdecls_semi { cvTopDecls $1 } + | topdecls { cvTopDecls $1 } + +----------------------------------------------------------------------------- +-- Tuple expressions + +-- "texp" is short for tuple expressions: +-- things that can appear unparenthesized as long as they're +-- inside parens or delimitted by commas +texp :: { ECP } + : exp { $1 } + + -- Note [Parsing sections] + -- ~~~~~~~~~~~~~~~~~~~~~~~ + -- We include left and right sections here, which isn't + -- technically right according to the Haskell standard. + -- For example (3 +, True) isn't legal. + -- However, we want to parse bang patterns like + -- (!x, !y) + -- and it's convenient to do so here as a section + -- Then when converting expr to pattern we unravel it again + -- Meanwhile, the renamer checks that real sections appear + -- inside parens. + | infixexp qop + {% runECP_P $1 >>= \ $1 -> + runPV (rejectPragmaPV $1) >> + runPV $2 >>= \ $2 -> + return $ ecpFromExp $ + sLL $1 $> $ SectionL noExtField $1 $2 } + | qopm infixexp { ECP $ + superInfixOp $ + runECP_PV $2 >>= \ $2 -> + $1 >>= \ $1 -> + mkHsSectionR_PV (comb2 $1 $>) $1 $2 } + + -- View patterns get parenthesized above + | exp '->' texp { ECP $ + runECP_PV $1 >>= \ $1 -> + runECP_PV $3 >>= \ $3 -> + amms (mkHsViewPatPV (comb2 $1 $>) $1 $3) [mu AnnRarrow $2] } + +-- Always at least one comma or bar. +-- Though this can parse just commas (without any expressions), it won't +-- in practice, because (,,,) is parsed as a name. See Note [ExplicitTuple] +-- in GHC.Hs.Expr. +tup_exprs :: { forall b. DisambECP b => PV ([AddAnn],SumOrTuple b) } + : texp commas_tup_tail + { runECP_PV $1 >>= \ $1 -> + $2 >>= \ $2 -> + do { addAnnotation (gl $1) AnnComma (fst $2) + ; return ([],Tuple ((sL1 $1 (Just $1)) : snd $2)) } } + + | texp bars { runECP_PV $1 >>= \ $1 -> return $ + (mvbars (fst $2), Sum 1 (snd $2 + 1) $1) } + + | commas tup_tail + { $2 >>= \ $2 -> + do { mapM_ (\ll -> addAnnotation ll AnnComma ll) (fst $1) + ; return + ([],Tuple (map (\l -> L l Nothing) (fst $1) ++ $2)) } } + + | bars texp bars0 + { runECP_PV $2 >>= \ $2 -> return $ + (mvbars (fst $1) ++ mvbars (fst $3), Sum (snd $1 + 1) (snd $1 + snd $3 + 1) $2) } + +-- Always starts with commas; always follows an expr +commas_tup_tail :: { forall b. DisambECP b => PV (SrcSpan,[Located (Maybe (Located b))]) } +commas_tup_tail : commas tup_tail + { $2 >>= \ $2 -> + do { mapM_ (\ll -> addAnnotation ll AnnComma ll) (tail $ fst $1) + ; return ( + (head $ fst $1 + ,(map (\l -> L l Nothing) (tail $ fst $1)) ++ $2)) } } + +-- Always follows a comma +tup_tail :: { forall b. DisambECP b => PV [Located (Maybe (Located b))] } + : texp commas_tup_tail { runECP_PV $1 >>= \ $1 -> + $2 >>= \ $2 -> + addAnnotation (gl $1) AnnComma (fst $2) >> + return ((L (gl $1) (Just $1)) : snd $2) } + | texp { runECP_PV $1 >>= \ $1 -> + return [L (gl $1) (Just $1)] } + | {- empty -} { return [noLoc Nothing] } + +----------------------------------------------------------------------------- +-- List expressions + +-- The rules below are little bit contorted to keep lexps left-recursive while +-- avoiding another shift/reduce-conflict. +-- Never empty. +list :: { forall b. DisambECP b => SrcSpan -> PV (Located b) } + : texp { \loc -> runECP_PV $1 >>= \ $1 -> + mkHsExplicitListPV loc [$1] } + | lexps { \loc -> $1 >>= \ $1 -> + mkHsExplicitListPV loc (reverse $1) } + | texp '..' { \loc -> runECP_PV $1 >>= \ $1 -> + ams (L loc $ ArithSeq noExtField Nothing (From $1)) + [mj AnnDotdot $2] + >>= ecpFromExp' } + | texp ',' exp '..' { \loc -> + runECP_PV $1 >>= \ $1 -> + runECP_PV $3 >>= \ $3 -> + ams (L loc $ ArithSeq noExtField Nothing (FromThen $1 $3)) + [mj AnnComma $2,mj AnnDotdot $4] + >>= ecpFromExp' } + | texp '..' exp { \loc -> runECP_PV $1 >>= \ $1 -> + runECP_PV $3 >>= \ $3 -> + ams (L loc $ ArithSeq noExtField Nothing (FromTo $1 $3)) + [mj AnnDotdot $2] + >>= ecpFromExp' } + | texp ',' exp '..' exp { \loc -> + runECP_PV $1 >>= \ $1 -> + runECP_PV $3 >>= \ $3 -> + runECP_PV $5 >>= \ $5 -> + ams (L loc $ ArithSeq noExtField Nothing (FromThenTo $1 $3 $5)) + [mj AnnComma $2,mj AnnDotdot $4] + >>= ecpFromExp' } + | texp '|' flattenedpquals + { \loc -> + checkMonadComp >>= \ ctxt -> + runECP_PV $1 >>= \ $1 -> + ams (L loc $ mkHsComp ctxt (unLoc $3) $1) + [mj AnnVbar $2] + >>= ecpFromExp' } + +lexps :: { forall b. DisambECP b => PV [Located b] } + : lexps ',' texp { $1 >>= \ $1 -> + runECP_PV $3 >>= \ $3 -> + addAnnotation (gl $ head $ $1) + AnnComma (gl $2) >> + return (((:) $! $3) $! $1) } + | texp ',' texp { runECP_PV $1 >>= \ $1 -> + runECP_PV $3 >>= \ $3 -> + addAnnotation (gl $1) AnnComma (gl $2) >> + return [$3,$1] } + +----------------------------------------------------------------------------- +-- List Comprehensions + +flattenedpquals :: { Located [LStmt GhcPs (LHsExpr GhcPs)] } + : pquals { case (unLoc $1) of + [qs] -> sL1 $1 qs + -- We just had one thing in our "parallel" list so + -- we simply return that thing directly + + qss -> sL1 $1 [sL1 $1 $ ParStmt noExtField [ParStmtBlock noExtField qs [] noSyntaxExpr | + qs <- qss] + noExpr noSyntaxExpr] + -- We actually found some actual parallel lists so + -- we wrap them into as a ParStmt + } + +pquals :: { Located [[LStmt GhcPs (LHsExpr GhcPs)]] } + : squals '|' pquals + {% addAnnotation (gl $ head $ unLoc $1) AnnVbar (gl $2) >> + return (sLL $1 $> (reverse (unLoc $1) : unLoc $3)) } + | squals { L (getLoc $1) [reverse (unLoc $1)] } + +squals :: { Located [LStmt GhcPs (LHsExpr GhcPs)] } -- In reverse order, because the last + -- one can "grab" the earlier ones + : squals ',' transformqual + {% addAnnotation (gl $ head $ unLoc $1) AnnComma (gl $2) >> + amsL (comb2 $1 $>) (fst $ unLoc $3) >> + return (sLL $1 $> [sLL $1 $> ((snd $ unLoc $3) (reverse (unLoc $1)))]) } + | squals ',' qual + {% runPV $3 >>= \ $3 -> + addAnnotation (gl $ head $ unLoc $1) AnnComma (gl $2) >> + return (sLL $1 $> ($3 : unLoc $1)) } + | transformqual {% ams $1 (fst $ unLoc $1) >> + return (sLL $1 $> [L (getLoc $1) ((snd $ unLoc $1) [])]) } + | qual {% runPV $1 >>= \ $1 -> + return $ sL1 $1 [$1] } +-- | transformquals1 ',' '{|' pquals '|}' { sLL $1 $> ($4 : unLoc $1) } +-- | '{|' pquals '|}' { sL1 $1 [$2] } + +-- It is possible to enable bracketing (associating) qualifier lists +-- by uncommenting the lines with {| |} above. Due to a lack of +-- consensus on the syntax, this feature is not being used until we +-- get user demand. + +transformqual :: { Located ([AddAnn],[LStmt GhcPs (LHsExpr GhcPs)] -> Stmt GhcPs (LHsExpr GhcPs)) } + -- Function is applied to a list of stmts *in order* + : 'then' exp {% runECP_P $2 >>= \ $2 -> return $ + sLL $1 $> ([mj AnnThen $1], \ss -> (mkTransformStmt ss $2)) } + | 'then' exp 'by' exp {% runECP_P $2 >>= \ $2 -> + runECP_P $4 >>= \ $4 -> + return $ sLL $1 $> ([mj AnnThen $1,mj AnnBy $3], + \ss -> (mkTransformByStmt ss $2 $4)) } + | 'then' 'group' 'using' exp + {% runECP_P $4 >>= \ $4 -> + return $ sLL $1 $> ([mj AnnThen $1,mj AnnGroup $2,mj AnnUsing $3], + \ss -> (mkGroupUsingStmt ss $4)) } + + | 'then' 'group' 'by' exp 'using' exp + {% runECP_P $4 >>= \ $4 -> + runECP_P $6 >>= \ $6 -> + return $ sLL $1 $> ([mj AnnThen $1,mj AnnGroup $2,mj AnnBy $3,mj AnnUsing $5], + \ss -> (mkGroupByUsingStmt ss $4 $6)) } + +-- Note that 'group' is a special_id, which means that you can enable +-- TransformListComp while still using Data.List.group. However, this +-- introduces a shift/reduce conflict. Happy chooses to resolve the conflict +-- in by choosing the "group by" variant, which is what we want. + +----------------------------------------------------------------------------- +-- Guards + +guardquals :: { Located [LStmt GhcPs (LHsExpr GhcPs)] } + : guardquals1 { L (getLoc $1) (reverse (unLoc $1)) } + +guardquals1 :: { Located [LStmt GhcPs (LHsExpr GhcPs)] } + : guardquals1 ',' qual {% runPV $3 >>= \ $3 -> + addAnnotation (gl $ head $ unLoc $1) AnnComma + (gl $2) >> + return (sLL $1 $> ($3 : unLoc $1)) } + | qual {% runPV $1 >>= \ $1 -> + return $ sL1 $1 [$1] } + +----------------------------------------------------------------------------- +-- Case alternatives + +altslist :: { forall b. DisambECP b => PV (Located ([AddAnn],[LMatch GhcPs (Located b)])) } + : '{' alts '}' { $2 >>= \ $2 -> return $ + sLL $1 $> ((moc $1:mcc $3:(fst $ unLoc $2)) + ,(reverse (snd $ unLoc $2))) } + | vocurly alts close { $2 >>= \ $2 -> return $ + L (getLoc $2) (fst $ unLoc $2 + ,(reverse (snd $ unLoc $2))) } + | '{' '}' { return $ sLL $1 $> ([moc $1,mcc $2],[]) } + | vocurly close { return $ noLoc ([],[]) } + +alts :: { forall b. DisambECP b => PV (Located ([AddAnn],[LMatch GhcPs (Located b)])) } + : alts1 { $1 >>= \ $1 -> return $ + sL1 $1 (fst $ unLoc $1,snd $ unLoc $1) } + | ';' alts { $2 >>= \ $2 -> return $ + sLL $1 $> ((mj AnnSemi $1:(fst $ unLoc $2)) + ,snd $ unLoc $2) } + +alts1 :: { forall b. DisambECP b => PV (Located ([AddAnn],[LMatch GhcPs (Located b)])) } + : alts1 ';' alt { $1 >>= \ $1 -> + $3 >>= \ $3 -> + if null (snd $ unLoc $1) + then return (sLL $1 $> (mj AnnSemi $2:(fst $ unLoc $1) + ,[$3])) + else (ams (head $ snd $ unLoc $1) + (mj AnnSemi $2:(fst $ unLoc $1)) + >> return (sLL $1 $> ([],$3 : (snd $ unLoc $1))) ) } + | alts1 ';' { $1 >>= \ $1 -> + if null (snd $ unLoc $1) + then return (sLL $1 $> (mj AnnSemi $2:(fst $ unLoc $1) + ,snd $ unLoc $1)) + else (ams (head $ snd $ unLoc $1) + (mj AnnSemi $2:(fst $ unLoc $1)) + >> return (sLL $1 $> ([],snd $ unLoc $1))) } + | alt { $1 >>= \ $1 -> return $ sL1 $1 ([],[$1]) } + +alt :: { forall b. DisambECP b => PV (LMatch GhcPs (Located b)) } + : pat alt_rhs { $2 >>= \ $2 -> + ams (sLL $1 $> (Match { m_ext = noExtField + , m_ctxt = CaseAlt + , m_pats = [$1] + , m_grhss = snd $ unLoc $2 })) + (fst $ unLoc $2)} + +alt_rhs :: { forall b. DisambECP b => PV (Located ([AddAnn],GRHSs GhcPs (Located b))) } + : ralt wherebinds { $1 >>= \alt -> + return $ sLL alt $> (fst $ unLoc $2, GRHSs noExtField (unLoc alt) (snd $ unLoc $2)) } + +ralt :: { forall b. DisambECP b => PV (Located [LGRHS GhcPs (Located b)]) } + : '->' exp { runECP_PV $2 >>= \ $2 -> + ams (sLL $1 $> (unguardedRHS (comb2 $1 $2) $2)) + [mu AnnRarrow $1] } + | gdpats { $1 >>= \gdpats -> + return $ sL1 gdpats (reverse (unLoc gdpats)) } + +gdpats :: { forall b. DisambECP b => PV (Located [LGRHS GhcPs (Located b)]) } + : gdpats gdpat { $1 >>= \gdpats -> + $2 >>= \gdpat -> + return $ sLL gdpats gdpat (gdpat : unLoc gdpats) } + | gdpat { $1 >>= \gdpat -> return $ sL1 gdpat [gdpat] } + +-- layout for MultiWayIf doesn't begin with an open brace, because it's hard to +-- generate the open brace in addition to the vertical bar in the lexer, and +-- we don't need it. +ifgdpats :: { Located ([AddAnn],[LGRHS GhcPs (LHsExpr GhcPs)]) } + : '{' gdpats '}' {% runPV $2 >>= \ $2 -> + return $ sLL $1 $> ([moc $1,mcc $3],unLoc $2) } + | gdpats close {% runPV $1 >>= \ $1 -> + return $ sL1 $1 ([],unLoc $1) } + +gdpat :: { forall b. DisambECP b => PV (LGRHS GhcPs (Located b)) } + : '|' guardquals '->' exp + { runECP_PV $4 >>= \ $4 -> + ams (sL (comb2 $1 $>) $ GRHS noExtField (unLoc $2) $4) + [mj AnnVbar $1,mu AnnRarrow $3] } + +-- 'pat' recognises a pattern, including one with a bang at the top +-- e.g. "!x" or "!(x,y)" or "C a b" etc +-- Bangs inside are parsed as infix operator applications, so that +-- we parse them right when bang-patterns are off +pat :: { LPat GhcPs } +pat : exp {% (checkPattern <=< runECP_P) $1 } + +bindpat :: { LPat GhcPs } +bindpat : exp {% -- See Note [Parser-Validator ReaderT SDoc] in GHC.Parser.PostProcess + checkPattern_msg (text "Possibly caused by a missing 'do'?") + (runECP_PV $1) } + +apat :: { LPat GhcPs } +apat : aexp {% (checkPattern <=< runECP_P) $1 } + +apats :: { [LPat GhcPs] } + : apat apats { $1 : $2 } + | {- empty -} { [] } + +----------------------------------------------------------------------------- +-- Statement sequences + +stmtlist :: { forall b. DisambECP b => PV (Located ([AddAnn],[LStmt GhcPs (Located b)])) } + : '{' stmts '}' { $2 >>= \ $2 -> return $ + sLL $1 $> ((moc $1:mcc $3:(fst $ unLoc $2)) + ,(reverse $ snd $ unLoc $2)) } -- AZ:performance of reverse? + | vocurly stmts close { $2 >>= \ $2 -> return $ + L (gl $2) (fst $ unLoc $2 + ,reverse $ snd $ unLoc $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 BodyStmts throughout, and switch the last one over +-- in ParseUtils.checkDo instead + +stmts :: { forall b. DisambECP b => PV (Located ([AddAnn],[LStmt GhcPs (Located b)])) } + : stmts ';' stmt { $1 >>= \ $1 -> + $3 >>= \ $3 -> + if null (snd $ unLoc $1) + then return (sLL $1 $> (mj AnnSemi $2:(fst $ unLoc $1) + ,$3 : (snd $ unLoc $1))) + else do + { ams (head $ snd $ unLoc $1) [mj AnnSemi $2] + ; return $ sLL $1 $> (fst $ unLoc $1,$3 :(snd $ unLoc $1)) }} + + | stmts ';' { $1 >>= \ $1 -> + if null (snd $ unLoc $1) + then return (sLL $1 $> (mj AnnSemi $2:(fst $ unLoc $1),snd $ unLoc $1)) + else do + { ams (head $ snd $ unLoc $1) + [mj AnnSemi $2] + ; return $1 } + } + | stmt { $1 >>= \ $1 -> + return $ sL1 $1 ([],[$1]) } + | {- empty -} { return $ noLoc ([],[]) } + + +-- For typing stmts at the GHCi prompt, where +-- the input may consist of just comments. +maybe_stmt :: { Maybe (LStmt GhcPs (LHsExpr GhcPs)) } + : stmt {% fmap Just (runPV $1) } + | {- nothing -} { Nothing } + +-- For GHC API. +e_stmt :: { LStmt GhcPs (LHsExpr GhcPs) } + : stmt {% runPV $1 } + +stmt :: { forall b. DisambECP b => PV (LStmt GhcPs (Located b)) } + : qual { $1 } + | 'rec' stmtlist { $2 >>= \ $2 -> + ams (sLL $1 $> $ mkRecStmt (snd $ unLoc $2)) + (mj AnnRec $1:(fst $ unLoc $2)) } + +qual :: { forall b. DisambECP b => PV (LStmt GhcPs (Located b)) } + : bindpat '<-' exp { runECP_PV $3 >>= \ $3 -> + ams (sLL $1 $> $ mkPsBindStmt $1 $3) + [mu AnnLarrow $2] } + | exp { runECP_PV $1 >>= \ $1 -> + return $ sL1 $1 $ mkBodyStmt $1 } + | 'let' binds { ams (sLL $1 $> $ LetStmt noExtField (snd $ unLoc $2)) + (mj AnnLet $1:(fst $ unLoc $2)) } + +----------------------------------------------------------------------------- +-- Record Field Update/Construction + +fbinds :: { forall b. DisambECP b => PV ([AddAnn],([LHsRecField GhcPs (Located b)], Maybe SrcSpan)) } + : fbinds1 { $1 } + | {- empty -} { return ([],([], Nothing)) } + +fbinds1 :: { forall b. DisambECP b => PV ([AddAnn],([LHsRecField GhcPs (Located b)], Maybe SrcSpan)) } + : fbind ',' fbinds1 + { $1 >>= \ $1 -> + $3 >>= \ $3 -> + addAnnotation (gl $1) AnnComma (gl $2) >> + return (case $3 of (ma,(flds, dd)) -> (ma,($1 : flds, dd))) } + | fbind { $1 >>= \ $1 -> + return ([],([$1], Nothing)) } + | '..' { return ([mj AnnDotdot $1],([], Just (getLoc $1))) } + +fbind :: { forall b. DisambECP b => PV (LHsRecField GhcPs (Located b)) } + : qvar '=' texp { runECP_PV $3 >>= \ $3 -> + ams (sLL $1 $> $ HsRecField (sL1 $1 $ mkFieldOcc $1) $3 False) + [mj AnnEqual $2] } + -- RHS is a 'texp', allowing view patterns (#6038) + -- and, incidentally, sections. Eg + -- f (R { x = show -> s }) = ... + + | qvar { placeHolderPunRhs >>= \rhs -> + return $ sLL $1 $> $ HsRecField (sL1 $1 $ mkFieldOcc $1) rhs True } + -- In the punning case, use a place-holder + -- The renamer fills in the final value + +----------------------------------------------------------------------------- +-- Implicit Parameter Bindings + +dbinds :: { Located [LIPBind GhcPs] } + : dbinds ';' dbind + {% addAnnotation (gl $ last $ unLoc $1) AnnSemi (gl $2) >> + return (let { this = $3; rest = unLoc $1 } + in rest `seq` this `seq` sLL $1 $> (this : rest)) } + | dbinds ';' {% addAnnotation (gl $ last $ unLoc $1) AnnSemi (gl $2) >> + return (sLL $1 $> (unLoc $1)) } + | dbind { let this = $1 in this `seq` sL1 $1 [this] } +-- | {- empty -} { [] } + +dbind :: { LIPBind GhcPs } +dbind : ipvar '=' exp {% runECP_P $3 >>= \ $3 -> + ams (sLL $1 $> (IPBind noExtField (Left $1) $3)) + [mj AnnEqual $2] } + +ipvar :: { Located HsIPName } + : IPDUPVARID { sL1 $1 (HsIPName (getIPDUPVARID $1)) } + +----------------------------------------------------------------------------- +-- Overloaded labels + +overloaded_label :: { Located FastString } + : LABELVARID { sL1 $1 (getLABELVARID $1) } + +----------------------------------------------------------------------------- +-- Warnings and deprecations + +name_boolformula_opt :: { LBooleanFormula (Located RdrName) } + : name_boolformula { $1 } + | {- empty -} { noLoc mkTrue } + +name_boolformula :: { LBooleanFormula (Located RdrName) } + : name_boolformula_and { $1 } + | name_boolformula_and '|' name_boolformula + {% aa $1 (AnnVbar, $2) + >> return (sLL $1 $> (Or [$1,$3])) } + +name_boolformula_and :: { LBooleanFormula (Located RdrName) } + : name_boolformula_and_list + { sLL (head $1) (last $1) (And ($1)) } + +name_boolformula_and_list :: { [LBooleanFormula (Located RdrName)] } + : name_boolformula_atom { [$1] } + | name_boolformula_atom ',' name_boolformula_and_list + {% aa $1 (AnnComma, $2) >> return ($1 : $3) } + +name_boolformula_atom :: { LBooleanFormula (Located RdrName) } + : '(' name_boolformula ')' {% ams (sLL $1 $> (Parens $2)) [mop $1,mcp $3] } + | name_var { sL1 $1 (Var $1) } + +namelist :: { Located [Located RdrName] } +namelist : name_var { sL1 $1 [$1] } + | name_var ',' namelist {% addAnnotation (gl $1) AnnComma (gl $2) >> + return (sLL $1 $> ($1 : unLoc $3)) } + +name_var :: { Located RdrName } +name_var : var { $1 } + | con { $1 } + +----------------------------------------- +-- Data constructors +-- There are two different productions here as lifted list constructors +-- are parsed differently. + +qcon_nowiredlist :: { Located RdrName } + : gen_qcon { $1 } + | sysdcon_nolist { sL1 $1 $ nameRdrName (dataConName (unLoc $1)) } + +qcon :: { Located RdrName } + : gen_qcon { $1} + | sysdcon { sL1 $1 $ nameRdrName (dataConName (unLoc $1)) } + +gen_qcon :: { Located RdrName } + : qconid { $1 } + | '(' qconsym ')' {% ams (sLL $1 $> (unLoc $2)) + [mop $1,mj AnnVal $2,mcp $3] } + +con :: { Located RdrName } + : conid { $1 } + | '(' consym ')' {% ams (sLL $1 $> (unLoc $2)) + [mop $1,mj AnnVal $2,mcp $3] } + | sysdcon { sL1 $1 $ nameRdrName (dataConName (unLoc $1)) } + +con_list :: { Located [Located RdrName] } +con_list : con { sL1 $1 [$1] } + | con ',' con_list {% addAnnotation (gl $1) AnnComma (gl $2) >> + return (sLL $1 $> ($1 : unLoc $3)) } + +-- See Note [ExplicitTuple] in GHC.Hs.Expr +sysdcon_nolist :: { Located DataCon } -- Wired in data constructors + : '(' ')' {% ams (sLL $1 $> unitDataCon) [mop $1,mcp $2] } + | '(' commas ')' {% ams (sLL $1 $> $ tupleDataCon Boxed (snd $2 + 1)) + (mop $1:mcp $3:(mcommas (fst $2))) } + | '(#' '#)' {% ams (sLL $1 $> $ unboxedUnitDataCon) [mo $1,mc $2] } + | '(#' commas '#)' {% ams (sLL $1 $> $ tupleDataCon Unboxed (snd $2 + 1)) + (mo $1:mc $3:(mcommas (fst $2))) } + +-- See Note [Empty lists] in GHC.Hs.Expr +sysdcon :: { Located DataCon } + : sysdcon_nolist { $1 } + | '[' ']' {% ams (sLL $1 $> nilDataCon) [mos $1,mcs $2] } + +conop :: { Located RdrName } + : consym { $1 } + | '`' conid '`' {% ams (sLL $1 $> (unLoc $2)) + [mj AnnBackquote $1,mj AnnVal $2 + ,mj AnnBackquote $3] } + +qconop :: { Located RdrName } + : qconsym { $1 } + | '`' qconid '`' {% ams (sLL $1 $> (unLoc $2)) + [mj AnnBackquote $1,mj AnnVal $2 + ,mj AnnBackquote $3] } + +---------------------------------------------------------------------------- +-- Type constructors + + +-- See Note [Unit tuples] in GHC.Hs.Types for the distinction +-- between gtycon and ntgtycon +gtycon :: { Located RdrName } -- A "general" qualified tycon, including unit tuples + : ntgtycon { $1 } + | '(' ')' {% ams (sLL $1 $> $ getRdrName unitTyCon) + [mop $1,mcp $2] } + | '(#' '#)' {% ams (sLL $1 $> $ getRdrName unboxedUnitTyCon) + [mo $1,mc $2] } + +ntgtycon :: { Located RdrName } -- A "general" qualified tycon, excluding unit tuples + : oqtycon { $1 } + | '(' commas ')' {% ams (sLL $1 $> $ getRdrName (tupleTyCon Boxed + (snd $2 + 1))) + (mop $1:mcp $3:(mcommas (fst $2))) } + | '(#' commas '#)' {% ams (sLL $1 $> $ getRdrName (tupleTyCon Unboxed + (snd $2 + 1))) + (mo $1:mc $3:(mcommas (fst $2))) } + | '(' '->' ')' {% ams (sLL $1 $> $ getRdrName funTyCon) + [mop $1,mu AnnRarrow $2,mcp $3] } + | '[' ']' {% ams (sLL $1 $> $ listTyCon_RDR) [mos $1,mcs $2] } + +oqtycon :: { Located RdrName } -- An "ordinary" qualified tycon; + -- These can appear in export lists + : qtycon { $1 } + | '(' qtyconsym ')' {% ams (sLL $1 $> (unLoc $2)) + [mop $1,mj AnnVal $2,mcp $3] } + +oqtycon_no_varcon :: { Located RdrName } -- Type constructor which cannot be mistaken + -- for variable constructor in export lists + -- see Note [Type constructors in export list] + : qtycon { $1 } + | '(' QCONSYM ')' {% let { name :: Located RdrName + ; name = sL1 $2 $! mkQual tcClsName (getQCONSYM $2) } + in ams (sLL $1 $> (unLoc name)) [mop $1,mj AnnVal name,mcp $3] } + | '(' CONSYM ')' {% let { name :: Located RdrName + ; name = sL1 $2 $! mkUnqual tcClsName (getCONSYM $2) } + in ams (sLL $1 $> (unLoc name)) [mop $1,mj AnnVal name,mcp $3] } + | '(' ':' ')' {% let { name :: Located RdrName + ; name = sL1 $2 $! consDataCon_RDR } + in ams (sLL $1 $> (unLoc name)) [mop $1,mj AnnVal name,mcp $3] } + +{- Note [Type constructors in export list] +~~~~~~~~~~~~~~~~~~~~~ +Mixing type constructors and data constructors in export lists introduces +ambiguity in grammar: e.g. (*) may be both a type constructor and a function. + +-XExplicitNamespaces allows to disambiguate by explicitly prefixing type +constructors with 'type' keyword. + +This ambiguity causes reduce/reduce conflicts in parser, which are always +resolved in favour of data constructors. To get rid of conflicts we demand +that ambiguous type constructors (those, which are formed by the same +productions as variable constructors) are always prefixed with 'type' keyword. +Unambiguous type constructors may occur both with or without 'type' keyword. + +Note that in the parser we still parse data constructors as type +constructors. As such, they still end up in the type constructor namespace +until after renaming when we resolve the proper namespace for each exported +child. +-} + +qtyconop :: { Located RdrName } -- Qualified or unqualified + : qtyconsym { $1 } + | '`' qtycon '`' {% ams (sLL $1 $> (unLoc $2)) + [mj AnnBackquote $1,mj AnnVal $2 + ,mj AnnBackquote $3] } + +qtycon :: { Located RdrName } -- Qualified or unqualified + : QCONID { sL1 $1 $! mkQual tcClsName (getQCONID $1) } + | tycon { $1 } + +qtycondoc :: { LHsType GhcPs } -- Qualified or unqualified + : qtycon { sL1 $1 (HsTyVar noExtField NotPromoted $1) } + | qtycon docprev { sLL $1 $> (HsDocTy noExtField (sL1 $1 (HsTyVar noExtField NotPromoted $1)) $2) } + +tycon :: { Located RdrName } -- Unqualified + : CONID { sL1 $1 $! mkUnqual tcClsName (getCONID $1) } + +qtyconsym :: { Located RdrName } + : QCONSYM { sL1 $1 $! mkQual tcClsName (getQCONSYM $1) } + | QVARSYM { sL1 $1 $! mkQual tcClsName (getQVARSYM $1) } + | tyconsym { $1 } + +tyconsym :: { Located RdrName } + : CONSYM { sL1 $1 $! mkUnqual tcClsName (getCONSYM $1) } + | VARSYM { sL1 $1 $! + -- See Note [eqTyCon (~) is built-in syntax] in GHC.Builtin.Types + if getVARSYM $1 == fsLit "~" + then eqTyCon_RDR + else mkUnqual tcClsName (getVARSYM $1) } + | ':' { sL1 $1 $! consDataCon_RDR } + | '-' { sL1 $1 $! mkUnqual tcClsName (fsLit "-") } + | '.' { sL1 $1 $! mkUnqual tcClsName (fsLit ".") } + + +----------------------------------------------------------------------------- +-- Operators + +op :: { Located RdrName } -- used in infix decls + : varop { $1 } + | conop { $1 } + | '->' { sL1 $1 $ getRdrName funTyCon } + +varop :: { Located RdrName } + : varsym { $1 } + | '`' varid '`' {% ams (sLL $1 $> (unLoc $2)) + [mj AnnBackquote $1,mj AnnVal $2 + ,mj AnnBackquote $3] } + +qop :: { forall b. DisambInfixOp b => PV (Located b) } -- used in sections + : qvarop { mkHsVarOpPV $1 } + | qconop { mkHsConOpPV $1 } + | hole_op { $1 } + +qopm :: { forall b. DisambInfixOp b => PV (Located b) } -- used in sections + : qvaropm { mkHsVarOpPV $1 } + | qconop { mkHsConOpPV $1 } + | hole_op { $1 } + +hole_op :: { forall b. DisambInfixOp b => PV (Located b) } -- used in sections +hole_op : '`' '_' '`' { amms (mkHsInfixHolePV (comb2 $1 $>)) + [mj AnnBackquote $1,mj AnnVal $2 + ,mj AnnBackquote $3] } + +qvarop :: { Located RdrName } + : qvarsym { $1 } + | '`' qvarid '`' {% ams (sLL $1 $> (unLoc $2)) + [mj AnnBackquote $1,mj AnnVal $2 + ,mj AnnBackquote $3] } + +qvaropm :: { Located RdrName } + : qvarsym_no_minus { $1 } + | '`' qvarid '`' {% ams (sLL $1 $> (unLoc $2)) + [mj AnnBackquote $1,mj AnnVal $2 + ,mj AnnBackquote $3] } + +----------------------------------------------------------------------------- +-- Type variables + +tyvar :: { Located RdrName } +tyvar : tyvarid { $1 } + +tyvarop :: { Located RdrName } +tyvarop : '`' tyvarid '`' {% ams (sLL $1 $> (unLoc $2)) + [mj AnnBackquote $1,mj AnnVal $2 + ,mj AnnBackquote $3] } + +tyvarid :: { Located RdrName } + : VARID { sL1 $1 $! mkUnqual tvName (getVARID $1) } + | special_id { sL1 $1 $! mkUnqual tvName (unLoc $1) } + | 'unsafe' { sL1 $1 $! mkUnqual tvName (fsLit "unsafe") } + | 'safe' { sL1 $1 $! mkUnqual tvName (fsLit "safe") } + | 'interruptible' { sL1 $1 $! mkUnqual tvName (fsLit "interruptible") } + -- If this changes relative to varid, update 'checkRuleTyVarBndrNames' + -- in GHC.Parser.PostProcess + -- See Note [Parsing explicit foralls in Rules] + +----------------------------------------------------------------------------- +-- Variables + +var :: { Located RdrName } + : varid { $1 } + | '(' varsym ')' {% ams (sLL $1 $> (unLoc $2)) + [mop $1,mj AnnVal $2,mcp $3] } + +qvar :: { Located RdrName } + : qvarid { $1 } + | '(' varsym ')' {% ams (sLL $1 $> (unLoc $2)) + [mop $1,mj AnnVal $2,mcp $3] } + | '(' qvarsym1 ')' {% ams (sLL $1 $> (unLoc $2)) + [mop $1,mj AnnVal $2,mcp $3] } +-- 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 { sL1 $1 $! mkQual varName (getQVARID $1) } + +-- Note that 'role' and 'family' get lexed separately regardless of +-- the use of extensions. However, because they are listed here, +-- this is OK and they can be used as normal varids. +-- See Note [Lexing type pseudo-keywords] in GHC.Parser.Lexer +varid :: { Located RdrName } + : VARID { sL1 $1 $! mkUnqual varName (getVARID $1) } + | special_id { sL1 $1 $! mkUnqual varName (unLoc $1) } + | 'unsafe' { sL1 $1 $! mkUnqual varName (fsLit "unsafe") } + | 'safe' { sL1 $1 $! mkUnqual varName (fsLit "safe") } + | 'interruptible' { sL1 $1 $! mkUnqual varName (fsLit "interruptible")} + | 'forall' { sL1 $1 $! mkUnqual varName (fsLit "forall") } + | 'family' { sL1 $1 $! mkUnqual varName (fsLit "family") } + | 'role' { sL1 $1 $! mkUnqual varName (fsLit "role") } + -- If this changes relative to tyvarid, update 'checkRuleTyVarBndrNames' + -- in GHC.Parser.PostProcess + -- See Note [Parsing explicit foralls in Rules] + +qvarsym :: { Located RdrName } + : varsym { $1 } + | qvarsym1 { $1 } + +qvarsym_no_minus :: { Located RdrName } + : varsym_no_minus { $1 } + | qvarsym1 { $1 } + +qvarsym1 :: { Located RdrName } +qvarsym1 : QVARSYM { sL1 $1 $ mkQual varName (getQVARSYM $1) } + +varsym :: { Located RdrName } + : varsym_no_minus { $1 } + | '-' { sL1 $1 $ mkUnqual varName (fsLit "-") } + +varsym_no_minus :: { Located RdrName } -- varsym not including '-' + : VARSYM { sL1 $1 $ mkUnqual varName (getVARSYM $1) } + | special_sym { sL1 $1 $ 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', 'interruptible', 'forall', 'family', 'role', 'stock', and +-- 'anyclass', whose treatment differs depending on context +special_id :: { Located FastString } +special_id + : 'as' { sL1 $1 (fsLit "as") } + | 'qualified' { sL1 $1 (fsLit "qualified") } + | 'hiding' { sL1 $1 (fsLit "hiding") } + | 'export' { sL1 $1 (fsLit "export") } + | 'label' { sL1 $1 (fsLit "label") } + | 'dynamic' { sL1 $1 (fsLit "dynamic") } + | 'stdcall' { sL1 $1 (fsLit "stdcall") } + | 'ccall' { sL1 $1 (fsLit "ccall") } + | 'capi' { sL1 $1 (fsLit "capi") } + | 'prim' { sL1 $1 (fsLit "prim") } + | 'javascript' { sL1 $1 (fsLit "javascript") } + | 'group' { sL1 $1 (fsLit "group") } + | 'stock' { sL1 $1 (fsLit "stock") } + | 'anyclass' { sL1 $1 (fsLit "anyclass") } + | 'via' { sL1 $1 (fsLit "via") } + | 'unit' { sL1 $1 (fsLit "unit") } + | 'dependency' { sL1 $1 (fsLit "dependency") } + | 'signature' { sL1 $1 (fsLit "signature") } + +special_sym :: { Located FastString } +special_sym : '.' { sL1 $1 (fsLit ".") } + | '*' { sL1 $1 (fsLit (starSym (isUnicode $1))) } + +----------------------------------------------------------------------------- +-- Data constructors + +qconid :: { Located RdrName } -- Qualified or unqualified + : conid { $1 } + | QCONID { sL1 $1 $! mkQual dataName (getQCONID $1) } + +conid :: { Located RdrName } + : CONID { sL1 $1 $ mkUnqual dataName (getCONID $1) } + +qconsym :: { Located RdrName } -- Qualified or unqualified + : consym { $1 } + | QCONSYM { sL1 $1 $ mkQual dataName (getQCONSYM $1) } + +consym :: { Located RdrName } + : CONSYM { sL1 $1 $ mkUnqual dataName (getCONSYM $1) } + + -- ':' means only list cons + | ':' { sL1 $1 $ consDataCon_RDR } + + +----------------------------------------------------------------------------- +-- Literals + +literal :: { Located (HsLit GhcPs) } + : CHAR { sL1 $1 $ HsChar (getCHARs $1) $ getCHAR $1 } + | STRING { sL1 $1 $ HsString (getSTRINGs $1) + $ getSTRING $1 } + | PRIMINTEGER { sL1 $1 $ HsIntPrim (getPRIMINTEGERs $1) + $ getPRIMINTEGER $1 } + | PRIMWORD { sL1 $1 $ HsWordPrim (getPRIMWORDs $1) + $ getPRIMWORD $1 } + | PRIMCHAR { sL1 $1 $ HsCharPrim (getPRIMCHARs $1) + $ getPRIMCHAR $1 } + | PRIMSTRING { sL1 $1 $ HsStringPrim (getPRIMSTRINGs $1) + $ getPRIMSTRING $1 } + | PRIMFLOAT { sL1 $1 $ HsFloatPrim noExtField $ getPRIMFLOAT $1 } + | PRIMDOUBLE { sL1 $1 $ HsDoublePrim noExtField $ getPRIMDOUBLE $1 } + +----------------------------------------------------------------------------- +-- Layout + +close :: { () } + : vccurly { () } -- context popped in lexer. + | error {% popContext } + +----------------------------------------------------------------------------- +-- Miscellaneous (mostly renamings) + +modid :: { Located ModuleName } + : CONID { sL1 $1 $ mkModuleNameFS (getCONID $1) } + | QCONID { sL1 $1 $ let (mod,c) = getQCONID $1 in + mkModuleNameFS + (mkFastString + (unpackFS mod ++ '.':unpackFS c)) + } + +commas :: { ([SrcSpan],Int) } -- One or more commas + : commas ',' { ((fst $1)++[gl $2],snd $1 + 1) } + | ',' { ([gl $1],1) } + +bars0 :: { ([SrcSpan],Int) } -- Zero or more bars + : bars { $1 } + | { ([], 0) } + +bars :: { ([SrcSpan],Int) } -- One or more bars + : bars '|' { ((fst $1)++[gl $2],snd $1 + 1) } + | '|' { ([gl $1],1) } + +----------------------------------------------------------------------------- +-- Documentation comments + +docnext :: { LHsDocString } + : DOCNEXT {% return (sL1 $1 (mkHsDocString (getDOCNEXT $1))) } + +docprev :: { LHsDocString } + : DOCPREV {% return (sL1 $1 (mkHsDocString (getDOCPREV $1))) } + +docnamed :: { Located (String, HsDocString) } + : DOCNAMED {% + let string = getDOCNAMED $1 + (name, rest) = break isSpace string + in return (sL1 $1 (name, mkHsDocString rest)) } + +docsection :: { Located (Int, HsDocString) } + : DOCSECTION {% let (n, doc) = getDOCSECTION $1 in + return (sL1 $1 (n, mkHsDocString doc)) } + +moduleheader :: { Maybe LHsDocString } + : DOCNEXT {% let string = getDOCNEXT $1 in + return (Just (sL1 $1 (mkHsDocString string))) } + +maybe_docprev :: { Maybe LHsDocString } + : docprev { Just $1 } + | {- empty -} { Nothing } + +maybe_docnext :: { Maybe LHsDocString } + : docnext { Just $1 } + | {- empty -} { Nothing } + +{ +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 +getLABELVARID (L _ (ITlabelvarid 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 +getPRIMWORD (L _ (ITprimword _ x)) = x +getPRIMFLOAT (L _ (ITprimfloat x)) = x +getPRIMDOUBLE (L _ (ITprimdouble x)) = x +getINLINE (L _ (ITinline_prag _ inl conl)) = (inl,conl) +getSPEC_INLINE (L _ (ITspec_inline_prag _ True)) = (Inline, FunLike) +getSPEC_INLINE (L _ (ITspec_inline_prag _ False)) = (NoInline,FunLike) +getCOMPLETE_PRAGs (L _ (ITcomplete_prag x)) = x + +getDOCNEXT (L _ (ITdocCommentNext x)) = x +getDOCPREV (L _ (ITdocCommentPrev x)) = x +getDOCNAMED (L _ (ITdocCommentNamed x)) = x +getDOCSECTION (L _ (ITdocSection n x)) = (n, x) + +getINTEGERs (L _ (ITinteger (IL src _ _))) = src +getCHARs (L _ (ITchar src _)) = src +getSTRINGs (L _ (ITstring src _)) = src +getPRIMCHARs (L _ (ITprimchar src _)) = src +getPRIMSTRINGs (L _ (ITprimstring src _)) = src +getPRIMINTEGERs (L _ (ITprimint src _)) = src +getPRIMWORDs (L _ (ITprimword src _)) = src + +-- See Note [Pragma source text] in BasicTypes for the following +getINLINE_PRAGs (L _ (ITinline_prag src _ _)) = src +getSPEC_PRAGs (L _ (ITspec_prag src)) = src +getSPEC_INLINE_PRAGs (L _ (ITspec_inline_prag src _)) = src +getSOURCE_PRAGs (L _ (ITsource_prag src)) = src +getRULES_PRAGs (L _ (ITrules_prag src)) = src +getWARNING_PRAGs (L _ (ITwarning_prag src)) = src +getDEPRECATED_PRAGs (L _ (ITdeprecated_prag src)) = src +getSCC_PRAGs (L _ (ITscc_prag src)) = src +getGENERATED_PRAGs (L _ (ITgenerated_prag src)) = src +getCORE_PRAGs (L _ (ITcore_prag src)) = src +getUNPACK_PRAGs (L _ (ITunpack_prag src)) = src +getNOUNPACK_PRAGs (L _ (ITnounpack_prag src)) = src +getANN_PRAGs (L _ (ITann_prag src)) = src +getMINIMAL_PRAGs (L _ (ITminimal_prag src)) = src +getOVERLAPPABLE_PRAGs (L _ (IToverlappable_prag src)) = src +getOVERLAPPING_PRAGs (L _ (IToverlapping_prag src)) = src +getOVERLAPS_PRAGs (L _ (IToverlaps_prag src)) = src +getINCOHERENT_PRAGs (L _ (ITincoherent_prag src)) = src +getCTYPEs (L _ (ITctype src)) = src + +getStringLiteral l = StringLiteral (getSTRINGs l) (getSTRING l) + +isUnicode :: Located Token -> Bool +isUnicode (L _ (ITforall iu)) = iu == UnicodeSyntax +isUnicode (L _ (ITdarrow iu)) = iu == UnicodeSyntax +isUnicode (L _ (ITdcolon iu)) = iu == UnicodeSyntax +isUnicode (L _ (ITlarrow iu)) = iu == UnicodeSyntax +isUnicode (L _ (ITrarrow iu)) = iu == UnicodeSyntax +isUnicode (L _ (ITlarrowtail iu)) = iu == UnicodeSyntax +isUnicode (L _ (ITrarrowtail iu)) = iu == UnicodeSyntax +isUnicode (L _ (ITLarrowtail iu)) = iu == UnicodeSyntax +isUnicode (L _ (ITRarrowtail iu)) = iu == UnicodeSyntax +isUnicode (L _ (IToparenbar iu)) = iu == UnicodeSyntax +isUnicode (L _ (ITcparenbar iu)) = iu == UnicodeSyntax +isUnicode (L _ (ITopenExpQuote _ iu)) = iu == UnicodeSyntax +isUnicode (L _ (ITcloseQuote iu)) = iu == UnicodeSyntax +isUnicode (L _ (ITstar iu)) = iu == UnicodeSyntax +isUnicode _ = False + +hasE :: Located Token -> Bool +hasE (L _ (ITopenExpQuote HasE _)) = True +hasE (L _ (ITopenTExpQuote HasE)) = True +hasE _ = False + +getSCC :: Located Token -> P FastString +getSCC lt = do let s = getSTRING lt + err = "Spaces are not allowed in SCCs" + -- We probably actually want to be more restrictive than this + if ' ' `elem` unpackFS s + then addFatalError (getLoc lt) (text err) + else return s + +-- Utilities for combining source spans +comb2 :: Located a -> Located b -> SrcSpan +comb2 a b = a `seq` b `seq` combineLocs a b + +comb3 :: Located a -> Located b -> Located c -> SrcSpan +comb3 a b c = a `seq` b `seq` c `seq` + combineSrcSpans (getLoc a) (combineSrcSpans (getLoc b) (getLoc c)) + +comb4 :: Located a -> Located b -> Located c -> Located d -> SrcSpan +comb4 a b c d = a `seq` b `seq` c `seq` d `seq` + (combineSrcSpans (getLoc a) $ combineSrcSpans (getLoc b) $ + combineSrcSpans (getLoc c) (getLoc d)) + +-- strict constructor version: +{-# INLINE sL #-} +sL :: SrcSpan -> a -> Located a +sL span a = span `seq` a `seq` L span a + +-- See Note [Adding location info] for how these utility functions are used + +-- replaced last 3 CPP macros in this file +{-# INLINE sL0 #-} +sL0 :: a -> Located a +sL0 = L noSrcSpan -- #define L0 L noSrcSpan + +{-# INLINE sL1 #-} +sL1 :: Located a -> b -> Located b +sL1 x = sL (getLoc x) -- #define sL1 sL (getLoc $1) + +{-# INLINE sLL #-} +sLL :: Located a -> Located b -> c -> Located c +sLL x y = sL (comb2 x y) -- #define LL sL (comb2 $1 $>) + +{- Note [Adding location info] + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This is done using the three functions below, sL0, sL1 +and sLL. Note that these functions were mechanically +converted from the three macros that used to exist before, +namely L0, L1 and LL. + +They each add a SrcSpan to their argument. + + sL0 adds 'noSrcSpan', used for empty productions + -- This doesn't seem to work anymore -=chak + + sL1 for a production with a single token on the lhs. Grabs the SrcSpan + from that token. + + sLL 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: sLL 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. + +-} + +-- 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 <- getRealSrcLoc; + let loc = mkSrcLoc (srcLocFile l) 1 1; + return (mkSrcSpan loc loc) + +-- Hint about the MultiWayIf extension +hintMultiWayIf :: SrcSpan -> P () +hintMultiWayIf span = do + mwiEnabled <- getBit MultiWayIfBit + unless mwiEnabled $ addError span $ + text "Multi-way if-expressions need MultiWayIf turned on" + +-- Hint about explicit-forall +hintExplicitForall :: Located Token -> P () +hintExplicitForall tok = do + forall <- getBit ExplicitForallBit + rulePrag <- getBit InRulePragBit + unless (forall || rulePrag) $ addError (getLoc tok) $ vcat + [ text "Illegal symbol" <+> quotes forallSymDoc <+> text "in type" + , text "Perhaps you intended to use RankNTypes or a similar language" + , text "extension to enable explicit-forall syntax:" <+> + forallSymDoc <+> text "<tvs>. <type>" + ] + where + forallSymDoc = text (forallSym (isUnicode tok)) + +-- When two single quotes don't followed by tyvar or gtycon, we report the +-- error as empty character literal, or TH quote that missing proper type +-- variable or constructor. See #13450. +reportEmptyDoubleQuotes :: SrcSpan -> P a +reportEmptyDoubleQuotes span = do + thQuotes <- getBit ThQuotesBit + if thQuotes + then addFatalError span $ vcat + [ text "Parser error on `''`" + , text "Character literals may not be empty" + , text "Or perhaps you intended to use quotation syntax of TemplateHaskell," + , text "but the type variable or constructor is missing" + ] + else addFatalError span $ vcat + [ text "Parser error on `''`" + , text "Character literals may not be empty" + ] + +{- +%************************************************************************ +%* * + Helper functions for generating annotations in the parser +%* * +%************************************************************************ + +For the general principles of the following routines, see Note [Api annotations] +in GHC.Parser.Annotation + +-} + +-- |Construct an AddAnn from the annotation keyword and the location +-- of the keyword itself +mj :: AnnKeywordId -> Located e -> AddAnn +mj a l = AddAnn a (gl l) + + +-- |Construct an AddAnn from the annotation keyword and the Located Token. If +-- the token has a unicode equivalent and this has been used, provide the +-- unicode variant of the annotation. +mu :: AnnKeywordId -> Located Token -> AddAnn +mu a lt@(L l t) = AddAnn (toUnicodeAnn a lt) l + +-- | If the 'Token' is using its unicode variant return the unicode variant of +-- the annotation +toUnicodeAnn :: AnnKeywordId -> Located Token -> AnnKeywordId +toUnicodeAnn a t = if isUnicode t then unicodeAnn a else a + +gl :: Located a -> SrcSpan +gl = getLoc + +-- |Add an annotation to the located element, and return the located +-- element as a pass through +aa :: Located a -> (AnnKeywordId, Located c) -> P (Located a) +aa a@(L l _) (b,s) = addAnnotation l b (gl s) >> return a + +-- |Add an annotation to a located element resulting from a monadic action +am :: P (Located a) -> (AnnKeywordId, Located b) -> P (Located a) +am a (b,s) = do + av@(L l _) <- a + addAnnotation l b (gl s) + return av + +-- | Add a list of AddAnns to the given AST element. For example, +-- the parsing rule for @let@ looks like: +-- +-- @ +-- | 'let' binds 'in' exp {% ams (sLL $1 $> $ HsLet (snd $ unLoc $2) $4) +-- (mj AnnLet $1:mj AnnIn $3 +-- :(fst $ unLoc $2)) } +-- @ +-- +-- This adds an AnnLet annotation for @let@, an AnnIn for @in@, as well +-- as any annotations that may arise in the binds. This will include open +-- and closing braces if they are used to delimit the let expressions. +-- +ams :: MonadP m => Located a -> [AddAnn] -> m (Located a) +ams a@(L l _) bs = addAnnsAt l bs >> return a + +amsL :: SrcSpan -> [AddAnn] -> P () +amsL sp bs = addAnnsAt sp bs >> return () + +-- |Add all [AddAnn] to an AST element, and wrap it in a 'Just' +ajs :: MonadP m => Located a -> [AddAnn] -> m (Maybe (Located a)) +ajs a bs = Just <$> ams a bs + +-- |Add a list of AddAnns to the given AST element, where the AST element is the +-- result of a monadic action +amms :: MonadP m => m (Located a) -> [AddAnn] -> m (Located a) +amms a bs = do { av@(L l _) <- a + ; addAnnsAt l bs + ; return av } + +-- |Add a list of AddAnns to the AST element, and return the element as a +-- OrdList +amsu :: Located a -> [AddAnn] -> P (OrdList (Located a)) +amsu a@(L l _) bs = addAnnsAt l bs >> return (unitOL a) + +-- |Synonyms for AddAnn versions of AnnOpen and AnnClose +mo,mc :: Located Token -> AddAnn +mo ll = mj AnnOpen ll +mc ll = mj AnnClose ll + +moc,mcc :: Located Token -> AddAnn +moc ll = mj AnnOpenC ll +mcc ll = mj AnnCloseC ll + +mop,mcp :: Located Token -> AddAnn +mop ll = mj AnnOpenP ll +mcp ll = mj AnnCloseP ll + +mos,mcs :: Located Token -> AddAnn +mos ll = mj AnnOpenS ll +mcs ll = mj AnnCloseS ll + +-- |Given a list of the locations of commas, provide a [AddAnn] with an AnnComma +-- entry for each SrcSpan +mcommas :: [SrcSpan] -> [AddAnn] +mcommas = map (AddAnn AnnCommaTuple) + +-- |Given a list of the locations of '|'s, provide a [AddAnn] with an AnnVbar +-- entry for each SrcSpan +mvbars :: [SrcSpan] -> [AddAnn] +mvbars = map (AddAnn AnnVbar) + +-- |Get the location of the last element of a OrdList, or noSrcSpan +oll :: OrdList (Located a) -> SrcSpan +oll l = + if isNilOL l then noSrcSpan + else getLoc (lastOL l) + +-- |Add a semicolon annotation in the right place in a list. If the +-- leading list is empty, add it to the tail +asl :: [Located a] -> Located b -> Located a -> P () +asl [] (L ls _) (L l _) = addAnnotation l AnnSemi ls +asl (x:_xs) (L ls _) _x = addAnnotation (getLoc x) AnnSemi ls +} |