+parseFunDecl = parseIdent <* satTok BraceOpenToken
+ >>= \ident->parseSepList CommaToken parseIdent <* satTok BraceCloseToken
+ >>= \args->parseFunType <* satTok CBraceOpenToken
+ >>= \funtype->many parseVarDecl
+ >>= \vardecls->many parseStmt
+ <* satTok CBraceCloseToken
+ >>= \stmts->pure $ FunDecl ident args funtype vardecls stmts
+
+parseStmt :: Parser Token Stmt
+parseStmt = parseIfStmt <|>
+ parseWhileStmt <|>
+ (parseAssStmt <* satTok SColonToken) <|>
+ (parseReturnStmt <* satTok SColonToken) <|>
+ (parseFunCall <* satTok SColonToken >>= \fc->pure $ FunStmt fc)
+ where
+ parseReturnStmt :: Parser Token Stmt
+ parseReturnStmt = satTok ReturnToken
+ *> optional parseExpr >>= \me->pure $ ReturnStmt me
+
+ parseAssStmt :: Parser Token Stmt
+ parseAssStmt = parseVarDef <* satTok AssignmentToken
+ >>= \var-> parseExpr >>= \expr->pure $ AssStmt var expr
+
+ parseIfStmt :: Parser Token Stmt
+ parseIfStmt = satTok IfToken
+ *> parseBBraces parseExpr
+ >>= \pred->parseBCBraces (many parseStmt)
+ >>= \thens->optional (
+ satTok ElseToken *> parseBCBraces (many parseStmt)
+ )>>= \elses->pure $ IfStmt pred thens (fromMaybe [] elses)
+
+ parseWhileStmt :: Parser Token Stmt
+ parseWhileStmt = satTok WhileToken *> parseBBraces parseExpr
+ >>= \pred->parseBCBraces (many parseStmt)
+ >>= \body->pure $ WhileStmt pred body
+
+parseBBraces :: (Parser Token a) -> Parser Token a
+parseBBraces p = satTok BraceOpenToken *> p <* satTok BraceCloseToken
+
+parseBCBraces :: (Parser Token a) -> Parser Token a
+parseBCBraces p = satTok CBraceOpenToken *> p <* satTok CBraceCloseToken
+
+parseFunType :: Parser Token FunType
+parseFunType = satTok DoubleColonToken *>
+ (parseInOutType <|> (parseVoidOrType >>= \t->pure $ FunType [] t))
+ where
+ parseInOutType :: Parser Token FunType
+ parseInOutType = some parseType <* satTok ArrowToken
+ >>= \intypes-> parseVoidOrType
+ >>= \outtypes->pure $ FunType intypes outtypes
+
+ parseVoidOrType :: Parser Token (Maybe Type)
+ parseVoidOrType = (satTok VoidToken *> pure Nothing) <|>
+ (parseType >>= \type->pure $ Just type)