{-# LANGUAGE ScopedTypeVariables #-}
module Parser 
{-
( Language
, Word
, Transcription
, WordIdentity
, WordCard
, Section
, Row
, Parser
, ParseError
, runP
, file
) -}
where

import Data.Text as T (Text, strip, pack, unpack, concat, append)
import Prelude hiding (words, Word)
import Text.ParserCombinators.Parsec hiding (spaces, label)
import Control.Monad
import Text.Parsec.Prim

--- READ http://www.serpentine.com/blog/2007/01/31/parsing-a-simple-config-file-in-haskell/
--- YOU STUPID MORON TO FIGURE OUT WHETHER TO PARSE INTO MAP AT ONCE OR LATER

type Language = T.Text

type Word = T.Text
type Transcription = T.Text

skipSpaces = skipMany (char ' ')    

-- tries to match \\ and return the echoed character
tryMatchEcho :: GenParser Char st Char
tryMatchEcho = Text.ParserCombinators.Parsec.try $ string "\\" >> anyChar

type WordIdentity = (Word, Maybe Transcription)
 
lexemeWord :: GenParser Char st WordIdentity
lexemeWord = 
    do
        word <- many (tryMatchEcho <|> noneOf "[|,=\n")
        (transcription :: Maybe String) 
            <- optionMaybe . between (char '[') (char ']') . many $ 
                    tryMatchEcho <|> noneOf "]"
        skipSpaces
        return (T.strip . T.pack $ word, T.strip . T.pack <$> transcription)
    <?> "a word (spaces are allowed)" 

type WordCard = (Word, [WordIdentity])

lexemeWordKind :: GenParser Char st WordCard
lexemeWordKind = 
    do
        head@(wd, tr) <- lexemeWord 
        tail <- option [] (char '|' >> sepBy lexemeWord (char '|'))
        return (wd, head:tail)

words :: GenParser Char st [WordCard]
words = skipSpaces >> sepBy lexemeWordKind (char ',') <?> "a list of words delimited by ','"

type Section = (Language, [WordCard])
section :: GenParser Char st Section
section = 
    do skipSpaces
       lang <- many (noneOf " [|,=\n\r")  -- many1 generates error on case    parseTest line "= "
       ws <- words
       return (T.pack lang, ws)
    <?> "=lang"
        
type Row = [Section]
line :: GenParser Char st Row
line = 
    do skipSpaces
       result <- choice [ char '=' >> sepBy section (char '=')
                        , skipMany (noneOf "\n") >> return []
                        ]
--       char ('\n')
       return result

file :: GenParser Char st [Row]
file = 
    do 
        val <- sepBy line (char '\n')
        eof
        return val
                