{- --------------------------------------------------------------------------- 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 ---------------------------------------------------------}