{- ---------------------------------------------------------------------------
Parser for Haskell 98 Syntax
-}
module Parse.Parse(parseProg) where
import Util.Extra(pair,noPos,strace,strPos,mergePos)
import Parse.Lex
import Parse.Lexical(PosToken)
import Syntax
import MkSyntax ( mkAppExp, mkCase, mkDeclClass
, mkDeclFun, mkDeclPat, mkDeclPatFun
-- , mkEnumFrom, mkEnumThenFrom, mkEnumToFrom, mkEnumToThenFrom
-- , mkExpListComp
, mkSweetListEnum, mkSweetListComp
, mkIf, mkInfixList, mkExpList
, mkLambda, mkLet, mkDo, mkFieldExp
, mkParExp, mkPatNplusK -- , mkParLhs
)
import Parse.Parse2
import Parse.ParseLib
import Parse.ParseLex
import SyntaxPos
import TokenId (t_nplusk,t_Arrow)
optSemi = () `parseChk` semi
`orelse`
parse ()
parseProg :: Parser (Module TokenId) [PosToken] a
parseProg = {- many parsePragma `revChk` -} (parseModule `chkCut` eof)
parseModule :: Parser (Module TokenId) [PosToken] a
parseModule =
(uncurry Module) `parseChk` lit L_module `apCut` bigModId `ap` parseExports
`chk` lit L_where `chk` lcurl
`apCut` parseImpDecls
`apCut` parseFixDecls
`apCut` parseTopDecls
`chk` optSemi `chk` rcurl
parseTopDecls :: Parser (Decls TokenId) [PosToken] a
parseTopDecls =
semi `revChk` parseTopDecls
`orelse`
DeclsParse `parseAp` manysSep semi parseTopDecl
parseTopDecl :: Parser (Decl TokenId) [PosToken] a
parseTopDecl =
cases [
(L_type, \pos -> DeclType `parseAp` parseSimple `chk` equal `ap` parseType),
(L_newtype, \pos ->
DeclData Nothing `parseAp` parseContexts `ap` parseSimple `chk`
equal `apCut` ( (:[]) `parseAp` parseConstr) `apCut` parseDeriving),
(L_data, \pos ->
(\ (pos,conid) size -> DeclDataPrim pos conid size) `parseChk`
k_primitive `ap` conid `chk` equal `apCut` intPrim
`orelse`
(DeclData . Just) `parseAp` unboxed `ap` parseContexts `ap`
parseSimple `chk` equal `apCut`
someSep pipe parseConstr `apCut` parseDeriving
`orelse`
(\ simpl -> DeclData (Just False) [] simpl [] []) `parseAp` parseSimple ),
(L_class, \pos ->
mkDeclClass `parseAp` parseContexts `ap` aconid `ap` some avarid `ap`
parseFunDeps `ap`
(id `parseChk` lit L_where `chk` lcurl `ap` parseCDecls `chk` rcurl
`orelse`
parse (DeclsParse [])
)),
(L_instance, \pos->
(\ctx (pos',cls) -> DeclInstance pos' ctx cls) `parseAp`
parseContexts `ap` aconid `ap` some parseInst `ap`
(lit L_where `revChk` lcurl `revChk` parseValdefs `chk` rcurl
`orelse`
parse (DeclsParse [])
)),
(L_default, \pos ->
DeclDefault `parseChk` lpar `apCut`
manySep comma parseType `chk` rpar
`orelse`
(\x->DeclDefault [x]) `parseAp` parseType)
]
(uncurry DeclPrimitive `parseAp` varid `chk` k_primitive `apCut`
intPrim `chk` coloncolon `ap` parseType
`orelse`
parseForeign
`orelse`
parseDecl)
parseFunDeps :: Parser [FunDep TokenId] [PosToken] a
parseFunDeps =
pipe `revChk` someSep comma parseFunDep
`orelse`
parse []
parseFunDep :: Parser (FunDep TokenId) [PosToken] a
parseFunDep =
(:->:) `parseAp` parseTyVars `chk` rarrow `ap` parseTyVars
where
parseTyVars :: Parser [TokenId] [PosToken] a
parseTyVars =
map snd `parseAp` some avarid
-- map snd `parseAp` (lpar `revChk` someSep comma avarid `chk` rpar)
-- `orelse`
-- ((:[]) . snd) `parseAp` varid
parseForeign :: Parser (Decl TokenId) [PosToken] a
parseForeign =
k_foreign `revAp`
((k_import `revChk`
((\(_,conv) (_,tf) (_,LitString _ str) (_,v) t p ->
DeclForeignImp (mergePos p (getPos t)) conv str v
(calcArity t) tf t v)
`parseAp` callconv `ap` safety `ap` entity `ap` varid `chk`
coloncolon `apCut` parseType))
`orelse`
(k_export `revChk`
((\(_,conv) (_,LitString _ str) (_,v) t p->
DeclForeignExp (mergePos p (getPos t)) conv str v t)
`parseAp` callconv `ap` entity `apCut` varid `chk` coloncolon
`ap` parseType))
`orelse`
(k_import `revChk` -- old syntax, will be removed in the future
((\(_,conv) (_,LitString _ str) (_,tf) (_,v) t p ->
let p' = mergePos p (getPos t) in
strace ("Deprecated FFI syntax used at "++strPos p') $
DeclForeignImp p' conv str v (calcArity t) tf t v)
`parseAp` (callconv `orelse` is C) `ap` entity `ap`
safety `apCut` varid `chk` coloncolon `ap` parseType))
-- `orelse`
-- (k_cast `revChk`
-- ((\(p,v) t-> DeclForeignImp p Cast "" v (calcArity t) Safe t v)
-- `parseAp` varid `chk` coloncolon `ap` parseType))
)
where
callconv = (k_ccall `revChk` is C)
`orelse`
(k_cast `revChk` is Cast)
`orelse`
(k_noproto `revChk` is Noproto)
`orelse`
(k_haskellcall `revChk` is Haskell)
`orelse`
(k_stdcall `revChk` is (Other "stdcall"))
`orelse`
(k_primitive `revChk` is (Other "primitive"))
`orelse`
(k_fastccall `revChk` is (Other "fastccall"))
`orelse`
(k_faststdcall `revChk` is (Other "faststdcall"))
`orelse`
(k_builtin `revChk` is (Other "builtin"))
`orelse`
(k_cplusplus `revChk` is (Other "cplusplus"))
`orelse`
(k_dotnet `revChk` is (Other "dotnet"))
`orelse`
(k_jvm `revChk` is (Other "jvm"))
`orelse`
(parseAp (\(p,tok) -> (p,Other (show tok))) varid)
-- `orelse`
-- (is C) -- previously the default, now the name is mandatory
is v = parse (noPos,v)
entity = string `orelse` is (LitString UnBoxed "")
safety = (k_unsafe `revChk` is Unsafe)
`orelse`
(k_safe `revChk` is Safe)
`orelse`
(is Safe) -- default is Safe
calcArity (TypeCons p c ts) | c == t_Arrow = 1 + calcArity (ts!!1)
calcArity _ | otherwise = 0
parseVarsType :: Parser (Decl TokenId) [PosToken] a
parseVarsType =
DeclVarsType `parseAp` someSep comma varid `chk` coloncolon `ap`
parseContexts `ap` parseType
{-
parseNewConstr =
(\ (pos,op) a -> [Constr pos op [(Nothing,a)]]) `parseAp` conid `ap` parseInst
-}
-- parseCSigns = DeclsParse `parseAp` manySep semi parseCSign
-- parseCSign = parseVarsType
parseCDecls :: Parser (Decls TokenId) [PosToken] a
parseCDecls = DeclsParse `parseAp` (manysSep semi parseCDecl) -- H98 added
parseCDecl :: Parser (Decl TokenId) [PosToken] a
parseCDecl = parseVarsType `orelse` parseValdef
`orelse` (DeclFixity `parseAp` parseFixDecl)
parseValdefs :: Parser (Decls TokenId) [PosToken] a
parseValdefs =
semi `revChk` parseValdefs
`orelse`
DeclsParse `parseAp` manysSep semi parseValdef
parseValdef :: Parser (Decl TokenId) [PosToken] a
parseValdef =
mkDeclPat `parseAp` varid `ap` anyop `ap` parsePat `ap`
parseRhs equal `apCut` parseWhere
`orelse`
mkDeclFun `parseAp` varid `ap` parsePats `ap` parseRhs equal `apCut`
parseWhere
`orelse`
mkDeclPatFun `parseAp` parseAlt equal
parseWhere :: Parser (Decls TokenId) [PosToken] a
parseWhere =
lit L_where `revChk` lcurl `revChk` parseDecls `chk` rcurl
`orelse`
parse (DeclsParse [])
parseDecls = DeclsParse `parseAp` (manysSep semi parseDecl)
parseDecl =
parseVarsType
`orelse`
parseValdef
`orelse` -- added in H98
DeclFixity `parseAp` parseFixDecl -- added in H98
{- `orelse`
parsePragma -- added by MW, Sept 2000
-}
parseExp :: Parser (Exp TokenId) [PosToken] a
parseExp =
parseExp0 `revAp` parseExpType
parseExpType :: Parser (Exp TokenId -> Exp TokenId) [PosToken] a
parseExpType =
(\pos ctx t e-> ExpType (mergePos pos (getPos t)) e ctx t)
`parseAp` coloncolon `apCut`
parseContexts `ap` parseType
`orelse`
parse id
parseExp0 :: Parser (Exp TokenId) [PosToken] a
parseExp0 = mkInfixList `parseAp` some (anyop `orelse` parseExp10)
parseStmt =
(lit L_let `into` \_-> lcurl `into` \_-> parseDecls `into`
\decls-> rcurl `into` \_->
((lit L_in `into` \_-> parseExp `into`
\exp-> parse (StmtExp (ExpLet
(mergePos (getPos decls) (getPos exp)) decls exp)))
`orelse`
parse (StmtLet decls)))
`orelse`
StmtBind `parseAp` parsePat `chk` larrow `apCut` parseExp
`orelse`
StmtExp `parseAp` parseExp
parseExp10 =
cases
[(L_Lambda,\pos -> (mkLambda pos)
`parseAp` parsePats `chk` rarrow `apCut` parseExp),
(L_let, \pos -> (mkLet pos)
`parseChk` lcurl `ap` parseDecls
`chk` optSemi `chk` rcurl
`chk` lit L_in `ap` parseExp),
(L_do, \pos -> (mkDo pos)
`parseChk` lcurl `ap` somesSep semi parseStmt
`chk` optSemi `chk` rcurl),
(L_if, \pos -> (mkIf pos)
`parseAp` parseExp
`chk` lit L_then `ap` parseExp
`chk` lit L_else `ap` parseExp),
(L_case, \pos -> (mkCase pos)
`parseAp` parseExp `chk` lit L_of
`chk` lcurl `ap` (somesSep semi (parseAlt rarrow))
`chk` optSemi `chk` rcurl)]
parseFExp
parseFExp = mkAppExp `parseAp` some parseAExpR1
parseAExpR1 =
parseAExp `into` parseAExpR
parseAExpR exp =
(ExpRecord exp `parseChk` lcurl `ap` manySep comma parseFieldExp `chk` rcurl) `into` parseAExpR
`orelse`
parse exp
parseAExp =
aanyid
`orelse`
cases
[(L_LBRACK, \pos -> parseBrackExp0 pos),
(L_LPAR, \pos -> (mkParExp pos) `parseAp` manySep comma parseExp
`ap` rpar)]
(uncurry ExpLit `parseAp`
(integer `orelse` rational `orelse` char `orelse` string))
parseFieldExp =
varid `into` (\(pos,ident)-> (mkFieldExp pos ident `parseChk` equal
`ap` parseExp)
`orelse` -- H98 removes
parse (FieldPun pos ident) -- H98 removes
)
parseBrackExp0 pos = -- found '['
(mkExpList pos []) `parseAp` rbrack
`orelse`
parseExp `revAp` parseBrackExp1 pos
-- keeping list comprehensions and list enumerations in sugared form
parseBrackExp1 pos = -- found '[e'
(\posr e -> mkExpList pos [e] posr) `parseAp` rbrack
`orelse`
(\posr ef -> mkSweetListEnum pos ef Nothing Nothing posr)
`parseChk` dotdot
`ap` rbrack
`orelse`
(\qs posr e -> mkSweetListComp pos e qs posr)
`parseChk` pipe
`ap` somesSep comma parseQual
`ap` rbrack
`orelse`
(\eto posr ef -> mkSweetListEnum pos ef Nothing (Just eto) posr)
`parseChk` dotdot
`ap` parseExp
`ap` rbrack
`orelse`
comma `revChk` (parseExp `revAp` parseBrackExp2 pos)
parseBrackExp2 pos = -- found '[e,e'
(\posr e2 e1 -> mkExpList pos [e1,e2] posr) `parseAp` rbrack
`orelse`
(\posr eth ef -> mkSweetListEnum pos ef (Just eth) Nothing posr)
`parseChk` dotdot
`ap` rbrack
`orelse`
(\eto posr eth ef -> mkSweetListEnum pos ef (Just eth) (Just eto) posr)
`parseChk` dotdot
`ap` parseExp
`ap` rbrack
`orelse`
(\es posr e2 e1 -> mkExpList pos (e1:e2:es) posr)
`parseChk` comma
`ap` manySep comma parseExp
`ap` rbrack
{-
-- de-sugared version of list comprehensions and list enumerations
--
parseBrackExp1 pos = -- found '[e'
(\posr e -> mkExpList pos [e] posr) `parseAp` rbrack
`orelse`
mkEnumFrom pos `parseChk` dotdot `chk` rbrack
`orelse`
mkExpListComp pos `parseChk` pipe `ap` somesSep comma parseQual `chk` rbrack
`orelse`
mkEnumToFrom pos `parseChk` dotdot `ap` parseExp `chk` rbrack
`orelse`
comma `revChk` (parseExp `revAp` parseBrackExp2 pos)
parseBrackExp2 pos = -- found '[e,e'
(\posr e2 e1 -> mkExpList pos [e1,e2] posr) `parseAp` rbrack
`orelse`
mkEnumThenFrom pos `parseChk` dotdot `chk` rbrack
`orelse`
mkEnumToThenFrom pos `parseChk` dotdot `ap` parseExp `chk` rbrack
`orelse`
(\es posr e2 e1 -> mkExpList pos (e1:e2:es) posr) `parseChk` comma
`ap` manySep comma parseExp
`ap` rbrack
-}
parseQual =
(lit L_let `into` \_-> lcurl `into` \_-> parseDecls `into`
\decls-> rcurl `into` \ _ ->
((lit L_in `into` \_-> parseExp `into` \exp->
parse (QualExp (ExpLet (getPos decls) decls exp)))
`orelse`
parse (QualLet decls)))
`orelse`
QualPatExp `parseAp` parsePat `chk` larrow `apCut` parseExp
`orelse`
QualExp `parseAp` parseExp
parseAlt del =
Alt `parseAp` parsePat `ap` parseRhs del `apCut` parseWhere
parseRhs :: Parser Pos [PosToken] a -> Parser (Rhs TokenId) [PosToken] a
parseRhs del =
Unguarded `parseChk` del `apCut` parseExp
`orelse`
PatGuard `parseAp` some (parsePatGdExp del)
parsePatGdExp :: Parser Pos [PosToken] a
-> Parser ([Qual TokenId], Exp TokenId) [PosToken] a
parsePatGdExp del =
pair `parseChk` pipe `apCut` somesSep comma parseQual
`chk` del `apCut` parseExp
parsePats = some parseAPat
-- Pat can not contain cut! It brakes parseStmt if it does.
manySafe p = someSafe p `orelse` parse []
someSafe p = (:) `parseAp` p `ap` manySafe p
manySepSafe' s p = s `revChk` someSepSafe s p
`orelse`
parse []
manySepSafe s p = someSepSafe s p `orelse` parse []
someSepSafe s p = (:) `parseAp` p `apCut` manySepSafe' s p
parsePat =
mkPatNplusK `parseAp` varid `chk` literal (L_AVAROP t_nplusk) `ap` integer
`orelse`
parsePat0
parsePat0 = mkInfixList `parseAp` someSafe (parseOpPat `orelse` parseFPat)
parseOpPat = anyop
parseFPat =
(\(pos,c) args -> mkAppExp (ExpCon pos c:args))
`parseAp` conid `ap` some parseAPat
`orelse`
parseAPat
parseAPat = parseAPat2 `into` parseAPat1
parseFieldPat =
varid `into` (\(pos,ident)-> mkFieldExp pos ident `parseChk` equal
`ap` parsePat
`orelse` -- H98 removes
parse (FieldPun pos ident) -- H98 removes
)
parseAPat1 exp =
(ExpRecord exp `parseChk` lcurl `ap` manySepSafe comma parseFieldPat
`chk` rcurl) `into` parseAPat1
`orelse`
parse exp
parseAPat2 =
varid `revAp` ((\e (pos,i) -> let p = mergePos pos (getPos e)
in p `seq` PatAs pos i e)
`parseChk` lit L_At `ap` parseAPat
`orelse`
parse (\ (pos,e) -> ExpVar pos e)
)
`orelse`
(\(pos,e) -> ExpCon pos e) `parseAp` aconid
`orelse`
PatWildcard `parseAp` lit L_Underscore
`orelse`
mkParExp `parseAp` lpar `ap` manySepSafe comma parsePat `ap` rpar
`orelse`
mkExpList `parseAp` lbrack `ap` manySepSafe comma parsePat `ap` rbrack
`orelse`
PatIrrefutable `parseAp` lit L_Tidle `ap` parseAPat
`orelse`
(uncurry ExpLit `parseAp`
(integer `orelse` rational `orelse` char `orelse` string))
-- `orelse`
-- mkParLhs `parseAp` lpar `ap` parsePat0 `chk` rpar `ap` someSafe parseAPat
{- End Module Parse ---------------------------------------------------------}
|