{- -*-haskell-*-
-----------------------------------------------------------------------------
-$Id: Parser.y,v 1.84 2002/02/11 08:20:44 chak Exp $
+$Id: Parser.y,v 1.90 2002/02/15 22:13:33 sof Exp $
Haskell grammar.
import PrelNames ( mAIN_Name, unitTyCon_RDR, funTyCon_RDR,
listTyCon_RDR, parrTyCon_RDR, tupleTyCon_RDR,
unitCon_RDR, nilCon_RDR, tupleCon_RDR )
-import ForeignCall ( Safety(..), CExportSpec(..), CCallSpec(..),
+import ForeignCall ( Safety(..), CExportSpec(..),
CCallConv(..), CCallTarget(..), defaultCCallConv,
- DNCallSpec(..) )
+ )
import OccName ( UserFS, varName, tcName, dataName, tcClsName, tvName )
+import TyCon ( DataConDetails(..) )
import SrcLoc ( SrcLoc )
import Module
import CmdLineOpts ( opt_SccProfilingOn )
+import Type ( Kind, mkArrowKind, liftedTypeKind )
import BasicTypes ( Boxity(..), Fixity(..), FixityDirection(..), IPName(..),
NewOrData(..), StrictnessMark(..), Activation(..) )
import Panic
-----------------------------------------------------------------------------
Conflicts: 21 shift/reduce, -=chak[4Feb2]
-8 for abiguity in 'if x then y else z + 1'
+9 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)
+ 8 because op might be: - ! * . `x` VARSYM CONSYM QVARSYM QCONSYM
1 for ambiguity in 'if x then y else z :: T'
(shift parses as 'if x then y else (z :: T)', as per longest-parse rule)
+1 for ambiguity in 'if x then y else z with ?x=3'
+ (shift parses as 'if x then y else (z with ?x=3)'
+
3 for ambiguity in 'case x of y :: a -> b'
(don't know whether to reduce 'a' as a btype or shift the '->'.
conclusion: bogus expression anyway, doesn't matter)
'label' { ITlabel }
'dynamic' { ITdynamic }
'safe' { ITsafe }
+ 'threadsafe' { ITthreadsafe }
'unsafe' { ITunsafe }
'with' { ITwith }
'stdcall' { ITstdcallconv }
'ccall' { ITccallconv }
'dotnet' { ITdotnet }
'_ccall_' { ITccall (False, False, PlayRisky) }
- '_ccall_GC_' { ITccall (False, False, PlaySafe) }
+ '_ccall_GC_' { ITccall (False, False, PlaySafe False) }
'_casm_' { ITccall (False, True, PlayRisky) }
- '_casm_GC_' { ITccall (False, True, PlaySafe) }
+ '_casm_GC_' { ITccall (False, True, PlaySafe False) }
'{-# SPECIALISE' { ITspecialise_prag }
'{-# SOURCE' { ITsource_prag }
'=>' { ITdarrow }
'-' { ITminus }
'!' { ITbang }
+ '*' { ITstar }
'.' { ITdot }
'{' { ITocurly } -- special symbols
| topdecl { [$1] }
topdecl :: { RdrBinding }
- : srcloc 'type' simpletype '=' ctype
+ : srcloc 'type' tycon tv_bndrs '=' ctype
-- Note ctype, not sigtype.
-- 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
- { RdrHsDecl (TyClD (TySynonym (fst $3) (snd $3) $5 $1)) }
+ { RdrHsDecl (TyClD (TySynonym $3 $4 $6 $1)) }
+
- | srcloc 'data' ctype constrs deriving
- {% checkDataHeader "data" $3 `thenP` \(cs,c,ts) ->
- returnP (RdrHsDecl (TyClD
- (mkTyData DataType cs c ts (reverse $4) (length $4) $5 $1))) }
+ | srcloc 'data' tycl_hdr constrs deriving
+ {% returnP (RdrHsDecl (TyClD
+ (mkTyData DataType $3 (DataCons (reverse $4)) $5 $1))) }
- | srcloc 'newtype' ctype '=' newconstr deriving
- {% checkDataHeader "newtype" $3 `thenP` \(cs,c,ts) ->
- returnP (RdrHsDecl (TyClD
- (mkTyData NewType cs c ts [$5] 1 $6 $1))) }
+ | srcloc 'newtype' tycl_hdr '=' newconstr deriving
+ {% returnP (RdrHsDecl (TyClD
+ (mkTyData NewType $3 (DataCons [$5]) $6 $1))) }
- | srcloc 'class' ctype fds where
- {% checkDataHeader "class" $3 `thenP` \(cs,c,ts) ->
- let
+ | srcloc 'class' tycl_hdr fds where
+ {% let
(binds,sigs) = cvMonoBindsAndSigs cvClassOpSig (groupBindings $5)
in
returnP (RdrHsDecl (TyClD
- (mkClassDecl cs c ts $4 sigs (Just binds) $1))) }
+ (mkClassDecl $3 $4 sigs (Just binds) $1))) }
| srcloc 'instance' inst_type where
{ let (binds,sigs)
(groupBindings $4)
in RdrHsDecl (InstD (InstDecl $3 binds sigs Nothing $1)) }
- | srcloc 'default' '(' types0 ')' { RdrHsDecl (DefD (DefaultDecl $4 $1)) }
+ | srcloc 'default' '(' comma_types0 ')' { RdrHsDecl (DefD (DefaultDecl $4 $1)) }
| 'foreign' fdecl { RdrHsDecl $2 }
| '{-# DEPRECATED' deprecations '#-}' { $2 }
| '{-# RULES' rules '#-}' { $2 }
| decl { $1 }
+-- tycl_hdr parses the header of a type or class decl,
+-- which takes the form
+-- T a b
+-- Eq a => T a
+-- (Eq a, Ord b) => T a b
+-- Rather a lot of inlining here, else we get reduce/reduce errors
+tycl_hdr :: { (RdrNameContext, RdrName, [RdrNameHsTyVar]) }
+ : '(' comma_types1 ')' '=>' gtycon tv_bndrs {% mapP checkPred $2 `thenP` \ cxt ->
+ returnP (cxt, $5, $6) }
+ -- qtycon for the class below name would lead to many s/r conflicts
+ -- FIXME: does the renamer pick up all wrong forms and raise an
+ -- error
+ | gtycon atypes1 '=>' gtycon atypes0 {% checkTyVars $5 `thenP` \ tvs ->
+ returnP ([HsClassP $1 $2], $4, tvs) }
+ | gtycon atypes0 {% checkTyVars $2 `thenP` \ tvs ->
+ returnP ([], $1, tvs) }
+ -- We have to have qtycon in this production to avoid s/r
+ -- conflicts with the previous one. The renamer will complain
+ -- if we use a qualified tycon.
+ --
+ -- Using a `gtycon' throughout. This enables special syntax,
+ -- such as "[]" for tycons as well as tycon ops in
+ -- parentheses. This is beyond H98, but used repeatedly in
+ -- the Prelude modules. (So, it would be a good idea to raise
+ -- an error in the renamer if some non-H98 form is used and
+ -- -fglasgow-exts is not given.) -=chak
+
+decls :: { [RdrBinding] }
+ : decls ';' decl { $3 : $1 }
+ | decls ';' { $1 }
+ | decl { [$1] }
+ | {- empty -} { [] }
+
+decl :: { RdrBinding }
+ : fixdecl { $1 }
+ | valdef { $1 }
+ | '{-# INLINE' srcloc activation qvar '#-}' { RdrSig (InlineSig True $4 $3 $2) }
+ | '{-# NOINLINE' srcloc inverse_activation qvar '#-}' { RdrSig (InlineSig False $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) }
+
+wherebinds :: { RdrNameHsBinds }
+ : where { cvBinds cvValSig (groupBindings $1) }
+
+where :: { [RdrBinding] }
+ : 'where' decllist { $2 }
+ | {- empty -} { [] }
+
+declbinds :: { RdrNameHsBinds }
+ : decllist { cvBinds cvValSig (groupBindings $1) }
+
+decllist :: { [RdrBinding] }
+ : '{' decls '}' { $2 }
+ | layout_on decls close { $2 }
+
+fixdecl :: { RdrBinding }
+ : srcloc infix prec ops { foldr1 RdrAndBindings
+ [ RdrSig (FixSig (FixitySig n
+ (Fixity $3 $2) $1))
+ | n <- $4 ] }
+
+-----------------------------------------------------------------------------
+-- Transformation Rules
+
+rules :: { RdrBinding }
+ : rules ';' rule { $1 `RdrAndBindings` $3 }
+ | rules ';' { $1 }
+ | rule { $1 }
+ | {- empty -} { RdrNullBind }
+
+rule :: { RdrBinding }
+ : STRING activation rule_forall infixexp '=' srcloc exp
+ { RdrHsDecl (RuleD (HsRule $1 $2 $3 $4 $7 $6)) }
+
+activation :: { Activation } -- Omitted means AlwaysActive
+ : {- empty -} { AlwaysActive }
+ | explicit_activation { $1 }
+
+inverse_activation :: { Activation } -- Omitted means NeverActive
+ : {- empty -} { NeverActive }
+ | explicit_activation { $1 }
+
+explicit_activation :: { Activation } -- In brackets
+ : '[' INTEGER ']' { ActiveAfter (fromInteger $2) }
+ | '[' '~' INTEGER ']' { ActiveBefore (fromInteger $3) }
+
+rule_forall :: { [RdrNameRuleBndr] }
+ : 'forall' rule_var_list '.' { $2 }
+ | {- empty -} { [] }
+
+rule_var_list :: { [RdrNameRuleBndr] }
+ : rule_var { [$1] }
+ | rule_var rule_var_list { $1 : $2 }
+
+rule_var :: { RdrNameRuleBndr }
+ : varid { RuleBndr $1 }
+ | '(' 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 depreclist STRING
+ { foldr RdrAndBindings RdrNullBind
+ [ RdrHsDecl (DeprecD (Deprecation n $3 $1)) | n <- $2 ] }
+
+
+-----------------------------------------------------------------------------
+-- Foreign import and export declarations
+
-- for the time being, the following accepts foreign declarations conforming
-- to the FFI Addendum, Version 1.0 as well as pre-standard declarations
--
--
fdecl :: { RdrNameHsDecl }
fdecl : srcloc 'import' callconv safety1 fspec {% mkImport $3 $4 $5 $1 }
- | srcloc 'import' callconv fspec {% mkImport $3 PlaySafe $4 $1 }
+ | srcloc 'import' callconv fspec {% mkImport $3 (PlaySafe False) $4 $1 }
| srcloc 'export' callconv fspec {% mkExport $3 $4 $1 }
-- the following syntax is DEPRECATED
| srcloc fdecl1DEPRECATED { ForD ($2 True $1) }
fdecl1DEPRECATED
----------- DEPRECATED label decls ------------
: 'label' ext_name varid '::' sigtype
- { ForeignImport $3 $5 (CImport defaultCCallConv PlaySafe _NIL_ _NIL_
+ { ForeignImport $3 $5 (CImport defaultCCallConv (PlaySafe False) _NIL_ _NIL_
(CLabel ($2 `orElse` mkExtName $3))) }
----------- DEPRECATED ccall/stdcall decls ------------
-- DEPRECATED variant #8: use of the special identifier `dynamic' without
-- an explicit calling convention (export)
| 'export' {-no callconv-} 'dynamic' varid '::' sigtype
- { ForeignImport $3 $5 (CImport defaultCCallConv PlaySafe _NIL_ _NIL_
+ { ForeignImport $3 $5 (CImport defaultCCallConv (PlaySafe False) _NIL_ _NIL_
CWrapper) }
-- DEPRECATED variant #9: use of the special identifier `dynamic' (export)
{% case $2 of
DNCall -> parseError "Illegal format of .NET foreign import"
CCall cconv -> returnP $
- ForeignImport $4 $6 (CImport cconv PlaySafe _NIL_ _NIL_ CWrapper) }
+ ForeignImport $4 $6 (CImport cconv (PlaySafe False) _NIL_ _NIL_ CWrapper) }
----------- DEPRECATED .NET decls ------------
-- NB: removed the .NET call declaration, as it is entirely subsumed
-- left this one unchanged for the moment as type imports are not
-- covered currently by the FFI standard -=chak
-decls :: { [RdrBinding] }
- : decls ';' decl { $3 : $1 }
- | decls ';' { $1 }
- | decl { [$1] }
- | {- empty -} { [] }
-
-decl :: { RdrBinding }
- : fixdecl { $1 }
- | valdef { $1 }
- | '{-# INLINE' srcloc activation qvar '#-}' { RdrSig (InlineSig True $4 $3 $2) }
- | '{-# NOINLINE' srcloc inverse_activation qvar '#-}' { RdrSig (InlineSig False $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) }
-
-wherebinds :: { RdrNameHsBinds }
- : where { cvBinds cvValSig (groupBindings $1) }
-
-where :: { [RdrBinding] }
- : 'where' decllist { $2 }
- | {- empty -} { [] }
-
-declbinds :: { RdrNameHsBinds }
- : decllist { cvBinds cvValSig (groupBindings $1) }
-
-decllist :: { [RdrBinding] }
- : '{' decls '}' { $2 }
- | layout_on decls close { $2 }
-
-fixdecl :: { RdrBinding }
- : srcloc infix prec ops { foldr1 RdrAndBindings
- [ RdrSig (FixSig (FixitySig n
- (Fixity $3 $2) $1))
- | n <- $4 ] }
-
------------------------------------------------------------------------------
--- Transformation Rules
-
-rules :: { RdrBinding }
- : rules ';' rule { $1 `RdrAndBindings` $3 }
- | rules ';' { $1 }
- | rule { $1 }
- | {- empty -} { RdrNullBind }
-
-rule :: { RdrBinding }
- : STRING activation rule_forall infixexp '=' srcloc exp
- { RdrHsDecl (RuleD (HsRule $1 $2 $3 $4 $7 $6)) }
-
-activation :: { Activation } -- Omitted means AlwaysActive
- : {- empty -} { AlwaysActive }
- | explicit_activation { $1 }
-
-inverse_activation :: { Activation } -- Omitted means NeverActive
- : {- empty -} { NeverActive }
- | explicit_activation { $1 }
-
-explicit_activation :: { Activation } -- In brackets
- : '[' INTEGER ']' { ActiveAfter (fromInteger $2) }
- | '[' '~' INTEGER ']' { ActiveBefore (fromInteger $3) }
-
-rule_forall :: { [RdrNameRuleBndr] }
- : 'forall' rule_var_list '.' { $2 }
- | {- empty -} { [] }
-
-rule_var_list :: { [RdrNameRuleBndr] }
- : rule_var { [$1] }
- | rule_var rule_var_list { $1 : $2 }
-
-rule_var :: { RdrNameRuleBndr }
- : varid { RuleBndr $1 }
- | '(' 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 depreclist STRING
- { foldr RdrAndBindings RdrNullBind
- [ RdrHsDecl (DeprecD (Deprecation n $3 $1)) | n <- $2 ] }
-
------------------------------------------------------------------------------
--- Foreign declarations
callconv :: { CallConv }
: 'stdcall' { CCall StdCallConv }
safety :: { Safety }
: 'unsafe' { PlayRisky }
- | 'safe' { PlaySafe }
- | {- empty -} { PlaySafe }
+ | 'safe' { PlaySafe False }
+ | 'threadsafe' { PlaySafe True }
+ | {- empty -} { PlaySafe False }
safety1 :: { Safety }
: 'unsafe' { PlayRisky }
- | 'safe' { PlaySafe }
+ | 'safe' { PlaySafe False }
+ | 'threadsafe' { PlaySafe True }
-- only needed to avoid conflicts with the DEPRECATED rules
fspec :: { (FAST_STRING, RdrName, RdrNameHsType) }
| sigtypes ',' sigtype { $3 : $1 }
sigtype :: { RdrNameHsType }
- : ctype { (mkHsForAllTy Nothing [] $1) }
+ : ctype { mkHsForAllTy Nothing [] $1 }
sig_vars :: { [RdrName] }
: sig_vars ',' var { $3 : $1 }
-- A ctype is a for-all type
ctype :: { RdrNameHsType }
- : 'forall' tyvars '.' ctype { mkHsForAllTy (Just $2) [] $4 }
+ : 'forall' tv_bndrs '.' ctype { mkHsForAllTy (Just $2) [] $4 }
| context '=>' type { mkHsForAllTy Nothing $1 $3 }
-- A type of form (context => type) is an *implicit* HsForAllTy
| type { $1 }
+-- We parse a context as a btype so that we don't get reduce/reduce
+-- errors in ctype. The basic problem is that
+-- (Eq a, Ord a)
+-- looks so much like a tuple type. We can't tell until we find the =>
+context :: { RdrNameContext }
+ : btype {% checkContext $1 }
+
type :: { RdrNameHsType }
: gentype '->' type { HsFunTy $1 $3 }
| ipvar '::' type { mkHsIParamTy $1 $3 }
| atype tyconop atype { HsOpTy $1 $2 $3 }
btype :: { RdrNameHsType }
- : btype atype { (HsAppTy $1 $2) }
+ : btype atype { HsAppTy $1 $2 }
| atype { $1 }
atype :: { RdrNameHsType }
: gtycon { HsTyVar $1 }
| tyvar { HsTyVar $1 }
- | '(' type ',' types ')' { HsTupleTy (mkHsTupCon tcName Boxed ($2:$4)) ($2 : reverse $4) }
- | '(#' types '#)' { HsTupleTy (mkHsTupCon tcName Unboxed $2) (reverse $2) }
+ | '(' type ',' comma_types1 ')' { HsTupleTy (mkHsTupCon tcName Boxed ($2:$4)) ($2:$4) }
+ | '(#' comma_types1 '#)' { HsTupleTy (mkHsTupCon tcName Unboxed $2) $2 }
| '[' type ']' { HsListTy $2 }
| '[:' type ':]' { HsPArrTy $2 }
| '(' ctype ')' { $2 }
+ | '(' ctype '::' kind ')' { HsKindSig $2 $4 }
-- Generics
| INTEGER { HsNumTy $1 }
inst_type :: { RdrNameHsType }
: ctype {% checkInstType $1 }
-types0 :: { [RdrNameHsType] }
- : types { reverse $1 }
+comma_types0 :: { [RdrNameHsType] }
+ : comma_types1 { $1 }
| {- empty -} { [] }
-types :: { [RdrNameHsType] }
+comma_types1 :: { [RdrNameHsType] }
: type { [$1] }
- | types ',' type { $3 : $1 }
+ | type ',' comma_types1 { $1 : $3 }
-simpletype :: { (RdrName, [RdrNameHsTyVar]) }
- : tycon tyvars { ($1, reverse $2) }
-
-tyvars :: { [RdrNameHsTyVar] }
- : tyvars tyvar { UserTyVar $2 : $1 }
+atypes0 :: { [RdrNameHsType] }
+ : atypes1 { $1 }
| {- empty -} { [] }
+atypes1 :: { [RdrNameHsType] }
+ : atype { [$1] }
+ | atype atypes1 { $1 : $2 }
+
+tv_bndrs :: { [RdrNameHsTyVar] }
+ : tv_bndr tv_bndrs { $1 : $2 }
+ | {- empty -} { [] }
+
+tv_bndr :: { RdrNameHsTyVar }
+ : tyvar { UserTyVar $1 }
+ | '(' tyvar '::' kind ')' { IfaceTyVar $2 $4 }
+
fds :: { [([RdrName], [RdrName])] }
: {- empty -} { [] }
| '|' fds1 { reverse $2 }
| varids0 tyvar { $2 : $1 }
-----------------------------------------------------------------------------
+-- Kinds
+
+kind :: { Kind }
+ : akind { $1 }
+ | akind '->' kind { mkArrowKind $1 $3 }
+
+akind :: { Kind }
+ : '*' { liftedTypeKind }
+ | '(' kind ')' { $2 }
+
+
+-----------------------------------------------------------------------------
-- Datatype declarations
newconstr :: { RdrNameConDecl }
{ mkConDecl (fst $3) $2 [] (snd $3) $1 }
forall :: { [RdrNameHsTyVar] }
- : 'forall' tyvars '.' { $2 }
+ : 'forall' tv_bndrs '.' { $2 }
| {- empty -} { [] }
-context :: { RdrNameContext }
- : btype {% checkContext $1 }
-
constr_stuff :: { (RdrName, RdrNameConDetails) }
: btype {% mkVanillaCon $1 [] }
| btype '!' atype satypes {% mkVanillaCon $1 (BangType MarkedUserStrict $3 : $4) }
returnP (HsDo DoExpr stmts $1) }
| '_ccall_' ccallid aexps0 { HsCCall $2 $3 PlayRisky False placeHolderType }
- | '_ccall_GC_' ccallid aexps0 { HsCCall $2 $3 PlaySafe False placeHolderType }
+ | '_ccall_GC_' ccallid aexps0 { HsCCall $2 $3 (PlaySafe False) False placeHolderType }
| '_casm_' CLITLIT aexps0 { HsCCall $2 $3 PlayRisky True placeHolderType }
- | '_casm_GC_' CLITLIT aexps0 { HsCCall $2 $3 PlaySafe True placeHolderType }
+ | '_casm_GC_' CLITLIT aexps0 { HsCCall $2 $3 (PlaySafe False) True placeHolderType }
| scc_annot exp { if opt_SccProfilingOn
then HsSCC $1 $2
| aexp { $1 }
aexps0 :: { [RdrNameHsExpr] }
- : aexps { (reverse $1) }
+ : aexps { reverse $1 }
aexps :: { [RdrNameHsExpr] }
: aexps aexp { $2 : $1 }
ralt :: { [RdrNameGRHS] }
: '->' srcloc exp { [GRHS [ResultStmt $3 $2] $2] }
- | gdpats { (reverse $1) }
+ | gdpats { reverse $1 }
gdpats :: { [RdrNameGRHS] }
: gdpats gdpat { $2 : $1 }
| '[:' ':]' { parrTyCon_RDR }
| '(' commas ')' { tupleTyCon_RDR $2 }
-gcon :: { RdrName }
+gcon :: { RdrName } -- Data constructor namespace
: '(' ')' { unitCon_RDR }
| '[' ']' { nilCon_RDR }
| '(' commas ')' { tupleCon_RDR $2 }
-----------------------------------------------------------------------------
-- ConIds
-qconid :: { RdrName }
+qconid :: { RdrName } -- Qualified or unqualifiedb
: conid { $1 }
| QCONID { mkQual dataName $1 }
-----------------------------------------------------------------------------
-- ConSyms
-qconsym :: { RdrName }
+qconsym :: { RdrName } -- Qualified or unqualifiedb
: consym { $1 }
| QCONSYM { mkQual dataName $1 }
special_sym :: { UserFS }
special_sym : '!' { SLIT("!") }
| '.' { SLIT(".") }
+ | '*' { SLIT("*") }
-----------------------------------------------------------------------------
-- Literals
tyconop :: { RdrName }
: CONSYM { mkUnqual tcClsName $1 }
-qtycon :: { RdrName }
- : tycon { $1 }
- | QCONID { mkQual tcClsName $1 }
+qtycon :: { RdrName } -- Qualified or unqualified
+ : QCONID { mkQual tcClsName $1 }
+ | tycon { $1 }
-qtyconop :: { RdrName }
- : tyconop { $1 }
- | QCONSYM { mkQual tcClsName $1 }
+qtyconop :: { RdrName } -- Qualified or unqualified
+ : QCONSYM { mkQual tcClsName $1 }
+ | tyconop { $1 }
commas :: { Int }
: commas ',' { $1 + 1 }