module Parser (
  Identifier,
  IntLit,
  CharLit,
  parseFile,
  prettyType,
  prettyArgTypes
) where

import Text.Parsec
import Text.Parsec.String
import Text.Parsec.Char

import Types
import Parser.Common
import Parser.Expression
import Parser.Statement

test :: Parser a -> String -> Either ParseError a
test p s = parse p "" s

-- FILE --

parseFile :: String -> String -> Either ParseError [TopLevel] 
parseFile fileName content = parse (many topLevel) fileName content

-- TOPLEVEL --


topLevel :: Parser TopLevel
topLevel = do 
  spaces
  tl <- (try func) <|> dataDecl
  spaces
  return tl

-- DATA TYPE --

dataDecl :: Parser TopLevel 
dataDecl = do
  pos <- getPosition
  string "data"
  spaces
  name <- identifier
  spaces
  openCurly
  fields <- dataDeclField `sepBy` (char ',')
  spaces
  closeCurly
  return $ TopLevelData $ Data pos name fields

dataDeclField :: Parser DataField
dataDeclField = do
  spaces
  pos <- getPosition
  t <- basicType
  spaces
  name <- identifier
  return $ DataField pos t name

-- FUNCTION --

funcArg :: Parser FuncArg
funcArg = do
  spaces
  argType <- basicType
  spaces
  name <- identifier
  return $ FuncArg argType name


func :: Parser TopLevel
func = do
  pos <- getPosition
  returnType <- basicType
  name <- identifier
  openParen
  args <- funcArg `sepBy` (char ',')
  closeParen
  openCurly
  body <- many (try stmt)
  spaces
  closeCurly
  return $ TopLevelFunc $ Func pos returnType name args body
