module Data.Makefile.Parse.Internal where
import Control.Applicative ((<|>))
import Data.Attoparsec.ByteString
import Data.Makefile
import qualified Data.Attoparsec.ByteString.Char8 as Atto
import qualified Data.ByteString as B
parseMakefile :: IO (Either String Makefile)
parseMakefile = Atto.parseOnly makefile <$> B.readFile "Makefile"
parseAsMakefile :: FilePath -> IO (Either String Makefile)
parseAsMakefile f = Atto.parseOnly makefile <$> B.readFile f
makefile :: Parser Makefile
makefile = Makefile <$> many' entry
entry :: Parser Entry
entry = many' emptyLine *> (assignment <|> rule)
assignment :: Parser Entry
assignment = Assignment <$> (lazyVar <|> immVar)
<*> toLineEnd1
rule :: Parser Entry
rule = Rule <$> target
<*> (many' dependency <* nextLine)
<*> many' command
command :: Parser Command
command = Command <$> (many' emptyLine *> Atto.char8 '\t'
*> toLineEnd1
<* nextLine)
target :: Parser Target
target = Target <$> (Atto.takeWhile (/= ':') <* Atto.char8 ':')
dependency :: Parser Dependency
dependency = Dependency <$> (Atto.takeWhile isSpaceChar
*> Atto.takeWhile1 (`notElem` [' ', '\n', '#']))
lazyVar :: Parser B.ByteString
lazyVar = Atto.takeWhile1 (`notElem` ['=', '\n', '#']) <* Atto.char8 '='
immVar :: Parser B.ByteString
immVar = Atto.takeWhile1 (`notElem` [':', '\n', '#']) <* Atto.string ":="
comment :: Parser B.ByteString
comment = Atto.char8 '#' *> Atto.takeWhile (/= '\n')
nextLine :: Parser ()
nextLine = Atto.takeWhile (/= '\n') *> Atto.char8 '\n' *> pure ()
emptyLine :: Parser ()
emptyLine = Atto.takeWhile (`elem` ['\t', ' ']) *>
many' comment *>
Atto.char8 '\n' *>
pure ()
isSpaceChar :: Char -> Bool
isSpaceChar c = c == ' '
toLineEnd1 :: Parser B.ByteString
toLineEnd1 = Atto.takeWhile1 (`notElem` ['\n', '#'])