[project @ 2000-03-23 17:45:17 by simonpj]
[ghc-hetmet.git] / ghc / compiler / parser / Parser.y
index 4c29906..a1f0283 100644 (file)
@@ -1,6 +1,6 @@
 {-
 -----------------------------------------------------------------------------
-$Id: Parser.y,v 1.4 1999/06/02 16:05:56 simonmar Exp $
+$Id: Parser.y,v 1.28 2000/03/23 17:45:22 simonpj Exp $
 
 Haskell grammar.
 
@@ -19,7 +19,7 @@ import Lex
 import ParseUtil
 import RdrName
 import PrelMods                ( mAIN_Name )
-import OccName         ( varName, dataName, tcClsName, tvName )
+import OccName         ( varName, ipName, dataName, tcClsName, tvName )
 import SrcLoc          ( SrcLoc )
 import Module
 import CallConv
@@ -28,6 +28,7 @@ import BasicTypes     ( Fixity(..), FixityDirection(..), NewOrData(..) )
 import Panic
 
 import GlaExts
+import FastString      ( tailFS )
 
 #include "HsVersions.h"
 }
@@ -35,6 +36,7 @@ import GlaExts
 {-
 -----------------------------------------------------------------------------
 Conflicts: 14 shift/reduce
+       (note: it's currently 21 -- JRL, 31/1/2000)
 
 8 for abiguity in 'if x then y else z + 1'
        (shift parses as 'if x then y else (z + 1)', as per longest-parse rule)
@@ -93,6 +95,9 @@ Conflicts: 14 shift/reduce
  'label'       { ITlabel } 
  'dynamic'     { ITdynamic }
  'unsafe'      { ITunsafe }
+ 'with'        { ITwith }
+ 'stdcall'      { ITstdcallconv }
+ 'ccall'        { ITccallconv }
  '_ccall_'     { ITccall (False, False, False) }
  '_ccall_GC_'  { ITccall (False, False, True)  }
  '_casm_'      { ITccall (False, True,  False) }
@@ -103,6 +108,7 @@ Conflicts: 14 shift/reduce
  '{-# INLINE'      { ITinline_prag }
  '{-# NOINLINE'    { ITnoinline_prag }
  '{-# RULES'      { ITrules_prag }
+ '{-# DEPRECATED'  { ITdeprecated_prag }
  '#-}'            { ITclose_prag }
 
 {-
@@ -172,6 +178,8 @@ Conflicts: 14 shift/reduce
  QVARSYM       { ITqvarsym  $$ }
  QCONSYM       { ITqconsym  $$ }
 
+ IPVARID       { ITipvarid  $$ }               -- GHC extension
+
  PRAGMA                { ITpragma   $$ }
 
  CHAR          { ITchar     $$ }
@@ -183,7 +191,7 @@ Conflicts: 14 shift/reduce
  PRIMSTRING    { ITprimstring $$ }
  PRIMINTEGER   { ITprimint    $$ }
  PRIMFLOAT     { ITprimfloat  $$ }
- PRIMDOUBLE    { ITprimdouble  $$ }
+ PRIMDOUBLE    { ITprimdouble $$ }
  CLITLIT       { ITlitlit     $$ }
 
  UNKNOWN       { ITunknown  $$ }
@@ -197,11 +205,22 @@ Conflicts: 14 shift/reduce
 -----------------------------------------------------------------------------
 -- Module Header
 
+-- The place for module deprecation is really too restrictive, but if it
+-- was allowed at its natural place just before 'module', we get an ugly
+-- s/r conflict with the second alternative. Another solution would be the
+-- introduction of a new pragma DEPRECATED_MODULE, but this is not very nice,
+-- either, and DEPRECATED is only expected to be used by people who really
+-- know what they are doing. :-)
+
 module         :: { RdrNameHsModule }
-       : srcloc 'module' modid maybeexports 'where' body 
-               { HsModule $3 Nothing $4 (fst $6) (snd $6) $1 }
-       | srcloc body   
-               { HsModule mAIN_Name Nothing Nothing (fst $2) (snd $2) $1 }
+       : srcloc 'module' modid maybemoddeprec maybeexports 'where' body 
+               { HsModule $3 Nothing $5 (fst $7) (snd $7) $4 $1 }
+       | srcloc body
+               { HsModule mAIN_Name Nothing Nothing (fst $2) (snd $2) Nothing $1 }
+
+maybemoddeprec :: { Maybe DeprecTxt }
+       : '{-# DEPRECATED' STRING '#-}'         { Just $2 }
+       |  {- empty -}                          { Nothing }
 
 body   :: { ([RdrNameImportDecl], [RdrNameHsDecl]) }
        :  '{'            top '}'               { $2 }
@@ -322,14 +341,14 @@ topdecl :: { RdrBinding }
                      (TyData NewType cs c ts [$5] $6
                        NoDataPragmas $1))) }
 
-       | srcloc 'class' ctype where
+       | srcloc 'class' ctype fds where
                {% checkDataHeader $3 `thenP` \(cs,c,ts) ->
                   let (binds,sigs) 
                           = cvMonoBindsAndSigs cvClassOpSig 
-                               (groupBindings $4) 
+                               (groupBindings $5) 
                   in
                   returnP (RdrHsDecl (TyClD
-                     (mkClassDecl cs c ts sigs binds 
+                     (mkClassDecl cs c ts $4 sigs binds 
                        NoClassPragmas $1))) }
 
        | srcloc 'instance' inst_type where
@@ -344,13 +363,13 @@ topdecl :: { RdrBinding }
 
        | srcloc 'foreign' 'import' callconv ext_name 
          unsafe_flag varid_no_unsafe '::' sigtype
-               { RdrHsDecl (ForD (ForeignDecl $7 (FoImport $6) $9 $5 $4 $1)) }
+               { RdrHsDecl (ForD (ForeignDecl $7 (FoImport $6) $9 (mkExtName $5 $7) $4 $1)) }
 
        | srcloc 'foreign' 'export' callconv ext_name varid '::' sigtype
-               { RdrHsDecl (ForD (ForeignDecl $6 FoExport $8 $5 $4 $1)) }
+               { RdrHsDecl (ForD (ForeignDecl $6 FoExport $8 (mkExtName $5 $6) $4 $1)) }
 
        | srcloc 'foreign' 'label' ext_name varid '::' sigtype
-               { RdrHsDecl (ForD (ForeignDecl $5 FoLabel $7 $4 
+               { RdrHsDecl (ForD (ForeignDecl $5 FoLabel $7 (mkExtName $4 $5)
                                        defaultCallConv $1)) }
 
        | decl          { $1 }
@@ -362,17 +381,21 @@ decls     :: { [RdrBinding] }
        | {- empty -}                   { [] }
 
 decl   :: { RdrBinding }
-       : signdecl                      { $1 }
-       | fixdecl                       { $1 }
-       | valdef                        { RdrValBinding $1 }
-       | '{-# INLINE'   srcloc qvar '#-}'      { RdrSig (InlineSig $3 $2) }
-       | '{-# NOINLINE' srcloc qvar '#-}'      { RdrSig (NoInlineSig $3 $2) }
+       : fixdecl                       { $1 }
+       | valdef                        { $1 }
+       | '{-# INLINE'   srcloc opt_phase qvar '#-}'    { RdrSig (InlineSig $4 $3 $2) }
+       | '{-# NOINLINE' srcloc opt_phase qvar '#-}'    { RdrSig (NoInlineSig $4 $3 $2) }
        | '{-# SPECIALISE' srcloc qvar '::' sigtypes '#-}'
                { foldr1 RdrAndBindings 
                    (map (\t -> RdrSig (SpecSig $3 t $2)) $5) }
        | '{-# SPECIALISE' srcloc 'instance' inst_type '#-}'
                { RdrSig (SpecInstSig $4 $2) }
        | '{-# RULES' rules '#-}'       { $2 }
+       | '{-# DEPRECATED' deprecations '#-}'   { $2 }
+
+opt_phase :: { Maybe Int }
+          : INTEGER                     { Just (fromInteger $1) }
+          | {- empty -}                 { Nothing }
 
 sigtypes :: { [RdrNameHsType] }
        : sigtype                       { [ $1 ] }
@@ -398,31 +421,12 @@ fixdecl :: { RdrBinding }
                                                            (Fixity $3 $2) $1))
                                            | n <- $4 ] }
 
-signdecl :: { RdrBinding }
-       : vars srcloc '::' sigtype      { foldr1 RdrAndBindings 
-                                             [ RdrSig (Sig n $4 $2) | n <- $1 ] }
-
 sigtype :: { RdrNameHsType }
-       : ctype                 { case $1 of
-                                   HsForAllTy _ _ _ -> $1
-                                   other            -> HsForAllTy Nothing [] $1 }
+       : ctype                         { mkHsForAllTy Nothing [] $1 }
 
-{-
-  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:
-  
-     { (+) :: ... }          only var
-     { (+) x y  = ... }      could (incorrectly) be qvar
-  
-  We re-use expressions for patterns, so a qvar would be allowed in patterns
-  instead of a var only (which would be correct). But deciding what the + is,
-  would require more lookahead. So let's check for ourselves...
--}
-
-vars   :: { [RdrName] }
-       : vars ',' var                  { $3 : $1 }
-       | qvar                          { [ $1 ] }
+sig_vars :: { [RdrName] }
+        : sig_vars ',' var             { $3 : $1 }
+        | var                          { [ $1 ] }
 
 -----------------------------------------------------------------------------
 -- Transformation Rules
@@ -443,35 +447,57 @@ rule_forall :: { [RdrNameRuleBndr] }
 
 rule_var_list :: { [RdrNameRuleBndr] }
         : rule_var                             { [$1] }
-        | rule_var ',' rule_var_list           { $1 : $3 }
+        | rule_var rule_var_list               { $1 : $2 }
 
 rule_var :: { RdrNameRuleBndr }
        : varid                                 { RuleBndr $1 }
-               | varid '::' ctype                      { RuleBndrSig $1 $3 }
+               | '(' varid '::' ctype ')'              { RuleBndrSig $2 $4 }
+
+-----------------------------------------------------------------------------
+-- Deprecations
+
+deprecations :: { RdrBinding }
+       : deprecations ';' deprecation          { $1 `RdrAndBindings` $3 }
+       | deprecations ';'                      { $1 }
+       | deprecation                           { $1 }
+       | {- empty -}                           { RdrNullBind }
+
+-- SUP: TEMPORARY HACK, not checking for `module Foo'
+deprecation :: { RdrBinding }
+       : srcloc exportlist STRING
+               { foldr1 RdrAndBindings [ RdrSig (DeprecSig (Deprecation n $3) $1) | n <- $2 ] }
 
 -----------------------------------------------------------------------------
 -- Foreign import/export
 
 callconv :: { Int }
-       : VARID                 {% checkCallConv $1 }
+       : 'stdcall'             { stdCallConv }
+       | 'ccall'               { cCallConv }
        | {- empty -}           { defaultCallConv }
 
 unsafe_flag :: { Bool }
        : 'unsafe'              { True }
        | {- empty -}           { False }
 
-ext_name :: { ExtName }
-       : 'dynamic'             { Dynamic }
-       | STRING                { ExtName $1 Nothing }
-       | STRING STRING         { ExtName $2 (Just $1) }
+ext_name :: { Maybe ExtName }
+       : 'dynamic'             { Just Dynamic }
+       | STRING                { Just (ExtName $1 Nothing)   }
+       | STRING STRING         { Just (ExtName $2 (Just $1)) }
+       | {- empty -}           { Nothing }
 
 -----------------------------------------------------------------------------
 -- Types
 
-{- ToDo: forall stuff -}
+-- A ctype is a for-all type
+ctype  :: { RdrNameHsType }
+       : 'forall' tyvars '.' ctype     { mkHsForAllTy (Just $2) [] $4 }
+       | context type                  { mkHsForAllTy Nothing   $1 $2 }
+               -- A type of form (context => type) is an *implicit* HsForAllTy
+       | type                          { $1 }
 
 type :: { RdrNameHsType }
        : btype '->' type               { MonoFunTy $1 $3 }
+       | ipvar '::' type               { MonoIParamTy $1 $3 }
        | btype                         { $1 }
 
 btype :: { RdrNameHsType }
@@ -500,15 +526,6 @@ gtycon     :: { RdrName }
 inst_type :: { RdrNameHsType }
        : ctype                         {% checkInstType $1 }
 
-ctype  :: { RdrNameHsType }
-       : 'forall' tyvars '.' btype '=>' type
-                                       {% checkContext $4 `thenP` \c ->
-                                          returnP (HsForAllTy (Just $2) c $6) }
-       | 'forall' tyvars '.' type      { HsForAllTy (Just $2) [] $4 }
-       | btype '=>' type               {% checkContext $1 `thenP` \c ->
-                                          returnP (HsForAllTy Nothing c $3) }
-       | type                          { $1 }
-
 types0  :: { [RdrNameHsType] }
        : types                         { $1 }
        | {- empty -}                   { [] }
@@ -524,6 +541,21 @@ tyvars :: { [RdrNameHsTyVar] }
        : tyvars tyvar                  { UserTyVar $2 : $1 }
        | {- empty -}                   { [] }
 
+fds :: { [([RdrName], [RdrName])] }
+       : {- empty -}                   { [] }
+       | '|' fds1                      { reverse $2 }
+
+fds1 :: { [([RdrName], [RdrName])] }
+       : fds1 ',' fd                   { $3 : $1 }
+       | fd                            { [$1] }
+
+fd :: { ([RdrName], [RdrName]) }
+       : varids0 '->' varids0          { (reverse $1, reverse $3) }
+
+varids0        :: { [RdrName] }
+       : {- empty -}                   { [] }
+       | varids0 tyvar                 { $2 : $1 }
+
 -----------------------------------------------------------------------------
 -- Datatype declarations
 
@@ -531,20 +563,28 @@ constrs :: { [RdrNameConDecl] }
        : constrs '|' constr            { $3 : $1 }
        | constr                        { [$1] }
 
-{- ToDo: existential stuff -}
-
 constr :: { RdrNameConDecl }
-       : srcloc scontype   
-               { ConDecl (fst $2) [] [] (VanillaCon (snd $2)) $1 }
-       | srcloc sbtype conop sbtype    
-               { ConDecl $3 [] [] (InfixCon $2 $4) $1 }
-       | srcloc con '{' fielddecls '}' 
-               { ConDecl $2 [] [] (RecCon (reverse $4)) $1 }
+       : srcloc forall context constr_stuff
+               { mkConDecl (fst $4) $2 $3 (snd $4) $1 }
+       | srcloc forall constr_stuff
+               { mkConDecl (fst $3) $2 [] (snd $3) $1 }
+
+forall :: { [RdrNameHsTyVar] }
+       : 'forall' tyvars '.'           { $2 }
+       | {- empty -}                   { [] }
+
+context :: { RdrNameContext }
+       : btype '=>'                    {% checkContext $1 }
+
+constr_stuff :: { (RdrName, RdrNameConDetails) }
+       : scontype                      { (fst $1, VanillaCon (snd $1)) }
+       | sbtype conop sbtype           { ($2, InfixCon $1 $3) }
+       | con '{' fielddecls '}'        { ($1, RecCon (reverse $3)) }
 
 newconstr :: { RdrNameConDecl }
-       : srcloc conid atype    { ConDecl $2 [] [] (NewCon $3 Nothing) $1 }
+       : srcloc conid atype    { mkConDecl $2 [] [] (NewCon $3 Nothing) $1 }
        | srcloc conid '{' var '::' type '}'
-                               { ConDecl $2 [] [] (NewCon $6 (Just $4)) $1 }
+                               { mkConDecl $2 [] [] (NewCon $6 (Just $4)) $1 }
 
 scontype :: { (RdrName, [RdrNameBangType]) }
        : btype                         {% splitForConApp $1 [] }
@@ -567,10 +607,10 @@ fielddecls :: { [([RdrName],RdrNameBangType)] }
        | fielddecl                     { [$1] }
 
 fielddecl :: { ([RdrName],RdrNameBangType) }
-       : vars '::' stype               { (reverse $1, $3) }
+       : sig_vars '::' stype           { (reverse $1, $3) }
 
 stype :: { RdrNameBangType }
-       : type                          { Unbanged $1 } 
+       : ctype                         { Unbanged $1 } 
        | '!' atype                     { Banged   $2 }
 
 deriving :: { Maybe [RdrName] }
@@ -586,9 +626,32 @@ dclasses :: { [RdrName] }
 -----------------------------------------------------------------------------
 -- Value definitions
 
-valdef :: { RdrNameMonoBinds }
-       : infixexp {-ToDo: opt_sig-} srcloc rhs 
-                                       {% checkValDef $1 Nothing $3 $2 }
+{- 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.
+-}
+
+valdef :: { RdrBinding }
+       : infixexp srcloc opt_sig rhs           {% checkValDef $1 $3 $4 $2 }
+       | infixexp srcloc '::' sigtype          {% checkValSig $1 $4 $2 }
+       | var ',' sig_vars srcloc '::' sigtype  { foldr1 RdrAndBindings 
+                                                        [ RdrSig (Sig n $6 $4) | n <- $1:$3 ]
+                                               }
 
 rhs    :: { RdrNameGRHSs }
        : '=' srcloc exp wherebinds     { GRHSs (unguardedRHS $3 $2) 
@@ -600,14 +663,14 @@ gdrhs :: { [RdrNameGRHS] }
        | gdrh                          { [$1] }
 
 gdrh :: { RdrNameGRHS }
-       : '|' srcloc quals '=' exp      { GRHS (reverse 
-                                                 (ExprStmt $5 $2 : $3)) $2 }
+       : '|' srcloc quals '=' exp      { GRHS (reverse (ExprStmt $5 $2 : $3)) $2 }
 
 -----------------------------------------------------------------------------
 -- Expressions
 
 exp   :: { RdrNameHsExpr }
        : infixexp '::' sigtype         { ExprWithTySig $1 $3 }
+       | infixexp 'with' dbinding      { HsWith $1 $3 }
        | infixexp                      { $1 }
 
 infixexp :: { RdrNameHsExpr }
@@ -626,14 +689,14 @@ exp10 :: { RdrNameHsExpr }
        | '-' fexp                              { NegApp $2 (error "NegApp") }
        | srcloc 'do' stmtlist                  { HsDo DoStmt $3 $1 }
 
-       | '_ccall_'    ccallid aexps0           { CCall $2 $3 False False cbot }
-       | '_ccall_GC_' ccallid aexps0           { CCall $2 $3 True  False cbot }
-       | '_casm_'     CLITLIT aexps0           { CCall $2 $3 False True  cbot }
-       | '_casm_GC_'  CLITLIT aexps0           { CCall $2 $3 True  True  cbot }
+       | '_ccall_'    ccallid aexps0           { HsCCall $2 $3 False False cbot }
+       | '_ccall_GC_' ccallid aexps0           { HsCCall $2 $3 True  False cbot }
+       | '_casm_'     CLITLIT aexps0           { HsCCall $2 $3 False True  cbot }
+       | '_casm_GC_'  CLITLIT aexps0           { HsCCall $2 $3 True  True  cbot }
 
         | '_scc_' STRING exp                   { if opt_SccProfilingOn
                                                        then HsSCC $2 $3
-                                                       else $3 }
+                                                       else HsPar $3 }
 
        | fexp                                  { $1 }
 
@@ -658,6 +721,7 @@ aexp        :: { RdrNameHsExpr }
 
 aexp1  :: { RdrNameHsExpr }
        : qvar                          { HsVar $1 }
+       | ipvar                         { HsIPVar $1 }
        | gcon                          { HsVar $1 }
        | literal                       { HsLit $1 }
        | '(' exp ')'                   { HsPar $2 }
@@ -718,12 +782,14 @@ altslist :: { [RdrNameMatch] }
        : '{'            alts '}'       { reverse $2 }
        |     layout_on  alts  close    { reverse $2 }
 
+alts    :: { [RdrNameMatch] }
+        : alts1                                { $1 }
+       | ';' alts                      { $2 }
 
-alts   :: { [RdrNameMatch] }
-       : alts ';' alt                  { $3 : $1 }
-       | alts ';'                      { $1 }
+alts1  :: { [RdrNameMatch] }
+       : alts1 ';' alt                 { $3 : $1 }
+       | alts1 ';'                     { $1 }
        | alt                           { [$1] }
-       | {- empty -}                   { [] }
 
 alt    :: { RdrNameMatch }
        : infixexp opt_sig ralt wherebinds
@@ -733,7 +799,7 @@ alt         :: { RdrNameMatch }
 
 opt_sig :: { Maybe RdrNameHsType }
        : {- empty -}                   { Nothing }
-       | '::' type                     { Just $2 }
+       | '::' sigtype                  { Just $2 }
 
 opt_asig :: { Maybe RdrNameHsType }
        : {- empty -}                   { Nothing }
@@ -754,14 +820,21 @@ gdpat     :: { RdrNameGRHS }
 -- Statement sequences
 
 stmtlist :: { [RdrNameStmt] }
-       : '{'            stmts '}'      { reverse $2 }
-       |     layout_on  stmts close    { reverse $2 }
+       : '{'                   stmts '}'       { reverse $2 }
+       |     layout_on_for_do  stmts close     { reverse $2 }
+
+-- Stmt list should really end in an expression, but it's not
+-- convenient to enforce this here, so we throw out erroneous
+-- statement sequences in the renamer instead.
 
 stmts :: { [RdrNameStmt] }
-       : stmts ';' stmt                { $3 : $1 }
-       | stmts ';'                     { $1 }
+       : ';' stmts1                    { $2 }
+       | stmts1                        { $1 }
+
+stmts1 :: { [RdrNameStmt] }
+       : stmts1 ';' stmt               { $3 : $1 }
+       | stmts1 ';'                    { $1 }
        | stmt                          { [$1] }
-       | {- empty -}                   { [] }
 
 stmt  :: { RdrNameStmt }
        : srcloc infixexp '<-' exp      {% checkPattern $2 `thenP` \p ->
@@ -782,6 +855,22 @@ fbind      :: { (RdrName, RdrNameHsExpr, Bool) }
        : qvar '=' exp                  { ($1,$3,False) }
 
 -----------------------------------------------------------------------------
+-- Implicit Parameter Bindings
+
+dbinding :: { [(RdrName, RdrNameHsExpr)] }
+       : '{' dbinds '}'                { $2 }
+       | layout_on dbinds close        { $2 }
+
+dbinds         :: { [(RdrName, RdrNameHsExpr)] }
+       : dbinds ';' dbind              { $3 : $1 }
+       | dbinds ';'                    { $1 }
+       | dbind                         { [$1] }
+       | {- empty -}                   { [] }
+
+dbind  :: { (RdrName, RdrNameHsExpr) }
+dbind  : ipvar '=' exp                 { ($1, $3) }
+
+-----------------------------------------------------------------------------
 -- Variables, Constructors and Operators.
 
 gcon   :: { RdrName }
@@ -796,7 +885,14 @@ var        :: { RdrName }
 
 qvar   :: { RdrName }
        : qvarid                { $1 }
-       | '(' qvarsym ')'       { $2 }
+       | '(' varsym ')'        { $2 }
+       | '(' qvarsym1 ')'      { $2 }
+-- We've inlined qvarsym here so that the decision about
+-- whether it's a qvar or a var can be postponed until
+-- *after* we see the close paren.
+
+ipvar  :: { RdrName }
+       : IPVARID               { (mkSrcUnqual ipName (tailFS $1)) }
 
 con    :: { RdrName }
        : conid                 { $1 }
@@ -859,6 +955,8 @@ varid :: { RdrName }
        | 'label'               { label_var_RDR }
        | 'dynamic'             { dynamic_var_RDR }
        | 'unsafe'              { unsafe_var_RDR }
+       | 'stdcall'             { stdcall_var_RDR }
+       | 'ccall'               { ccall_var_RDR }
 
 varid_no_unsafe :: { RdrName }
        : VARID                 { mkSrcUnqual varName $1 }
@@ -869,6 +967,8 @@ varid_no_unsafe :: { RdrName }
        | 'export'              { export_var_RDR }
        | 'label'               { label_var_RDR }
        | 'dynamic'             { dynamic_var_RDR }
+       | 'stdcall'             { stdcall_var_RDR }
+       | 'ccall'               { ccall_var_RDR }
 
 -----------------------------------------------------------------------------
 -- ConIds
@@ -940,7 +1040,8 @@ close :: { () }
        : vccurly               { () } -- context popped in lexer.
        | error                 {% popContext }
 
-layout_on  :: { () }   :       {% layoutOn  }
+layout_on        :: { () }     : {% layoutOn True{-strict-} }
+layout_on_for_do  :: { () }    : {% layoutOn False }
 
 -----------------------------------------------------------------------------
 -- Miscellaneous (mostly renamings)
@@ -964,10 +1065,12 @@ tyvar    :: { RdrName }
        | 'as'                  { as_tyvar_RDR }
        | 'qualified'           { qualified_tyvar_RDR }
        | 'hiding'              { hiding_tyvar_RDR }
-       | 'export'              { export_var_RDR }
-       | 'label'               { label_var_RDR }
-       | 'dynamic'             { dynamic_var_RDR }
-       | 'unsafe'              { unsafe_var_RDR }
+       | 'export'              { export_tyvar_RDR }
+       | 'label'               { label_tyvar_RDR }
+       | 'dynamic'             { dynamic_tyvar_RDR }
+       | 'unsafe'              { unsafe_tyvar_RDR }
+       | 'stdcall'             { stdcall_tyvar_RDR }
+       | 'ccall'               { ccall_tyvar_RDR }
        -- NOTE: no 'forall'
 
 -----------------------------------------------------------------------------