summaryrefslogtreecommitdiff
path: root/compiler/GHC/Parser.y
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/GHC/Parser.y')
-rw-r--r--compiler/GHC/Parser.y54
1 files changed, 51 insertions, 3 deletions
diff --git a/compiler/GHC/Parser.y b/compiler/GHC/Parser.y
index ac9976815f..9e822a9530 100644
--- a/compiler/GHC/Parser.y
+++ b/compiler/GHC/Parser.y
@@ -42,7 +42,7 @@ where
import Control.Monad ( unless, liftM, when, (<=<) )
import GHC.Exts
import Data.Maybe ( maybeToList )
-import Data.List.NonEmpty ( NonEmpty(..) )
+import Data.List.NonEmpty ( NonEmpty(..), (<|) )
import qualified Data.List.NonEmpty as NE
import qualified Prelude -- for happy-generated code
@@ -507,6 +507,22 @@ Ambiguity:
empty activation and inlining '[0] Something'.
-}
+{- Note [%shift: orpats -> pat]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Context:
+ orpats -> pat .
+ orpats -> pat . ',' orpats
+
+Example:
+
+ (one of a, b)
+
+Ambiguity:
+ We use ',' as a delimiter between options inside an or-pattern.
+ However, the ',' could also mean a tuple pattern.
+ If the user wants a tuple pattern, they have to put the or-pattern in parentheses.
+-}
+
{- Note [Parser API Annotations]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A lot of the productions are now cluttered with calls to
@@ -605,6 +621,7 @@ are the most common patterns, rewritten as regular expressions for clarity:
'interruptible' { L _ ITinterruptible }
'unsafe' { L _ ITunsafe }
'family' { L _ ITfamily }
+ 'one' { L _ ITone }
'role' { L _ ITrole }
'stdcall' { L _ ITstdcallconv }
'ccall' { L _ ITccallconv }
@@ -3051,12 +3068,32 @@ texp :: { ECP }
$1 >>= \ $1 ->
pvA $ mkHsSectionR_PV (comb2 (reLocN $1) (reLoc $>)) (n2l $1) $2 }
+
+ | 'one' 'of' vocurly orpats close
+ {% do {
+ let srcSpan = comb2 $1 (reLoc (NE.last $4))
+ ; cs <- getCommentsFor srcSpan
+ ; let pat' = OrPat (EpAnn (spanAsAnchor srcSpan) [mj AnnOne $1, mj AnnOf $2] cs) $4
+ ; let pat = sL (noAnnSrcSpan srcSpan) pat'
+ ; orPatsOn <- hintOrPats pat
+ ; when (orPatsOn && length $4 < 2) $ addError $ mkPlainErrorMsgEnvelope (locA (getLoc pat)) (PsErrOrPatNeedsTwoAlternatives pat)
+ ; return $ ecpFromPat pat
+ } }
+
-- View patterns get parenthesized above
| exp '->' texp { ECP $
unECP $1 >>= \ $1 ->
unECP $3 >>= \ $3 ->
mkHsViewPatPV (comb2 (reLoc $1) (reLoc $>)) $1 $3 [mu AnnRarrow $2] }
+orpats :: { NonEmpty (LPat GhcPs) }
+ : tpat %shift { NE.singleton $1 }
+
+ | tpat ',' orpats {% do {
+ a <- addTrailingCommaA $1 (getLoc $2)
+ ; return (a<|$3)
+ } }
+
-- 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]
@@ -3320,6 +3357,9 @@ gdpat :: { forall b. DisambECP b => PV (LGRHS GhcPs (LocatedA b)) }
pat :: { LPat GhcPs }
pat : exp {% (checkPattern <=< runPV) (unECP $1) }
+tpat :: { LPat GhcPs }
+tpat : texp {% (checkPattern <=< runPV) (unECP $1) }
+
-- 'pats1' does the same thing as 'pat', but returns it as a singleton
-- list so that it can be used with a parameterized production rule
pats1 :: { [LPat GhcPs] }
@@ -3812,8 +3852,8 @@ varsym_no_minus :: { LocatedN RdrName } -- varsym not including '-'
-- 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
+-- 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") }
@@ -3826,6 +3866,7 @@ special_id
| 'ccall' { sL1 $1 (fsLit "ccall") }
| 'capi' { sL1 $1 (fsLit "capi") }
| 'prim' { sL1 $1 (fsLit "prim") }
+ | 'one' { sL1 $1 (fsLit "one") }
| 'javascript' { sL1 $1 (fsLit "javascript") }
-- See Note [%shift: special_id -> 'group']
| 'group' %shift { sL1 $1 (fsLit "group") }
@@ -4167,6 +4208,13 @@ looksLikeMult ty1 l_op ty2
= True
| otherwise = False
+-- Hint about or-patterns
+hintOrPats :: MonadP m => LPat GhcPs -> m Bool
+hintOrPats pat = do
+ orPatsEnabled <- getBit OrPatternsBit
+ unless orPatsEnabled $ addError $ mkPlainErrorMsgEnvelope (locA (getLoc pat)) $ PsErrIllegalOrPat pat
+ return orPatsEnabled
+
-- Hint about the MultiWayIf extension
hintMultiWayIf :: SrcSpan -> P ()
hintMultiWayIf span = do