+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 <|>
+ parseSColon parseAssStmt <|>
+ parseSColon parseReturnStmt <|>
+ (parseSColon parseFunCall >>= \fc->pure $ FunStmt fc)
+ where
+ parseSColon :: (Parser Token a) -> Parser Token a
+ parseSColon p = p <* satTok SColonToken
+
+ 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->(parseBlock <|> parseOneLine)
+ >>= \thens->optional (
+ satTok ElseToken *> (parseBlock <|> parseOneLine)
+ )>>= \elses->pure $ IfStmt pred thens (fromMaybe [] elses)
+
+ parseWhileStmt :: Parser Token Stmt
+ parseWhileStmt = satTok WhileToken *> parseBBraces parseExpr
+ >>= \pred->parseBlock >>= \body->pure $ WhileStmt pred body
+
+ parseBlock :: Parser Token [Stmt]
+ parseBlock = parseBCBraces (many parseStmt)
+
+ parseOneLine :: Parser Token [Stmt]
+ parseOneLine = parseStmt >>= \s->pure [s]
+
+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)