+parseFunDecl = liftM5 FunDecl
+ (parseIdent <* satTok BraceOpenToken)
+ (parseSepList CommaToken parseIdent <* satTok BraceCloseToken)
+ (optional parseFunType <* satTok CBraceOpenToken)
+ (many parseVarDecl)
+ (many parseStmt <* satTok CBraceCloseToken)
+
+parseStmt :: Parser Token Stmt
+parseStmt = parseIfStmt <|> parseWhileStmt <|>
+ parseSColon parseAssStmt <|> parseSColon parseReturnStmt <|>
+ (liftM FunStmt (parseSColon parseFunCall))
+ where
+ parseSColon :: (Parser Token a) -> Parser Token a
+ parseSColon p = p <* satTok SColonToken
+
+ parseReturnStmt :: Parser Token Stmt
+ parseReturnStmt =
+ satTok ReturnToken *> liftM ReturnStmt (optional parseExpr)
+
+ parseAssStmt :: Parser Token Stmt
+ parseAssStmt =
+ liftM2 AssStmt (parseVarDef <* satTok AssignmentToken) parseExpr
+
+ parseIfStmt :: Parser Token Stmt
+ parseIfStmt = liftM3 IfStmt
+ (satTok IfToken *> parseBBraces parseExpr)
+ (parseBlock <|> parseOneLine)
+ (liftM (fromMaybe [])
+ (optional (satTok ElseToken *> (parseBlock<|> parseOneLine))))
+
+
+ parseWhileStmt :: Parser Token Stmt
+ parseWhileStmt = satTok WhileToken *>
+ liftM2 WhileStmt (parseBBraces parseExpr) parseBlock
+
+ parseBlock :: Parser Token [Stmt]
+ parseBlock = parseBCBraces (many parseStmt)
+
+ parseOneLine :: Parser Token [Stmt]
+ //first pure makes singleton list from the statement
+ parseOneLine = liftM pure parseStmt
+
+parseFunType :: Parser Token FunType
+parseFunType = satTok DoubleColonToken *>
+ (parseInOutType <|> (liftM (FunType []) parseVoidOrType))
+ where
+ parseInOutType :: Parser Token FunType
+ parseInOutType = liftM2 FunType
+ (some parseType <* satTok ArrowToken) parseVoidOrType
+
+ parseVoidOrType :: Parser Token (Maybe Type)
+ parseVoidOrType = (satTok VoidToken *> pure Nothing) <|>
+ (liftM Just parseType) <|> pure Nothing