module Fay.Compiler.Parse ( parseFay , defaultExtensions ) where import Language.Haskell.Exts hiding (name) -- | Parse some Fay code. parseFay :: Parseable ast => FilePath -> String -> ParseResult ast parseFay filepath = parseWithMode parseMode { parseFilename = filepath } . applyCPP -- | Apply incredibly simplistic CPP handling. It only recognizes the following: -- -- > #if FAY -- > #ifdef FAY -- > #ifndef FAY -- > #else -- > #endif -- -- Note that this implementation replaces all removed lines with blanks, so -- that line numbers remain accurate. applyCPP :: String -> String applyCPP = unlines . loop NoCPP . lines where loop _ [] = [] loop state' ("#if FAY":rest) = "" : loop (CPPIf True state') rest loop state' ("#ifdef FAY":rest) = "" : loop (CPPIf True state') rest loop state' ("#ifndef FAY":rest) = "" : loop (CPPIf False state') rest loop (CPPIf b oldState') ("#else":rest) = "" : loop (CPPElse (not b) oldState') rest loop (CPPIf _ oldState') ("#endif":rest) = "" : loop oldState' rest loop (CPPElse _ oldState') ("#endif":rest) = "" : loop oldState' rest loop state' (x:rest) = (if toInclude state' then x else "") : loop state' rest toInclude NoCPP = True toInclude (CPPIf x state') = x && toInclude state' toInclude (CPPElse x state') = x && toInclude state' -- | The CPP's parsing state. data CPPState = NoCPP | CPPIf Bool CPPState | CPPElse Bool CPPState -- | The parse mode for Fay. parseMode :: ParseMode parseMode = defaultParseMode { extensions = defaultExtensions , fixities = Just (preludeFixities ++ baseFixities) } defaultExtensions :: [Extension] defaultExtensions = map EnableExtension [EmptyDataDecls ,ExistentialQuantification ,FlexibleContexts ,FlexibleInstances ,GADTs ,ImplicitPrelude ,KindSignatures ,LambdaCase ,MultiWayIf ,NamedFieldPuns ,PackageImports ,RecordWildCards ,StandaloneDeriving ,TupleSections ,TypeFamilies ,TypeOperators ]