-- Copyright © 2014 Garrison Jensen
-- License
-- This code and text are dedicated to the public domain.
-- You can copy, modify, distribute and perform the work,
-- even for commercial purposes, all without asking permission.

module Parser(parseString, parseFile) where

import Text.ParserCombinators.Parsec
import Text.ParserCombinators.Parsec.Language
import qualified Text.ParserCombinators.Parsec.Token as Token
import Data.Char()
import Data.Either()
import Nock

languageDef =
  emptyDef { Token.commentLine = "::" }

lexer = Token.makeTokenParser languageDef

integer    = Token.integer    lexer
whiteSpace = Token.whiteSpace lexer

brack :: Parser Noun -> Parser Noun
brack p = do
  whiteSpace
  char '['
  whiteSpace
  e <- p
  whiteSpace
  char ']'
  whiteSpace
  return e

cell :: Parser Noun
cell = do
  n <- sepBy noun spaces
  return $ foldr1 Cell n

atom :: Parser Noun
atom = do 
  whiteSpace
  n <- integer
  whiteSpace
  return $ Atom $ n

noun :: Parser Noun
noun = atom <|> brack cell

whileParser :: Parser Noun
whileParser = whiteSpace >> noun

parseString :: String -> Maybe Noun
parseString str =
  case parse whileParser "" str of
    Left _  -> Nothing
    Right r -> Just r

parseFile :: String -> IO Noun
parseFile file =
  do program  <- readFile file
     case parse whileParser "" program of
       Left e  -> print e >> fail "parse error"
       Right r -> return r
