-- ----------------------------------------------------------------------------- -- -- Alex.hs, part of Alex -- -- (c) Chris Dornan 1995-2000, Simon Marlow 2003 -- -- ----------------------------------------------------------------------------} module Text.Alex ( runAlex , CLIFlags(..) , alex , optsToInject , importsToInject , parseScript, Target(..) ) where import AbsSyn import CharSet import DFA import Info import Map ( Map ) import qualified Map hiding ( Map ) import Output import ParseMonad ( runP ) import Parser import Scan import Data.Char ( chr ) runAlex :: [CLIFlags] -> Maybe FilePath -> String -> (String,String) runAlex cli file prg = let script = parseScript file prg in alex cli script parseScript :: Maybe FilePath -> String -> (Maybe (AlexPosn,Code), [Directive], Scanner, Maybe (AlexPosn,Code)) parseScript maybeFile prg = let file = maybe "" id maybeFile in case runP prg initialParserEnv parse of Left (Just (AlexPn _ line col),err) -> error (file ++ ":" ++ show line ++ ":" ++ show col ++ ": " ++ err ++ "\n") Left (Nothing, err) -> error (file ++ ": " ++ err ++ "\n") Right script -> script alex :: [CLIFlags] -> (Maybe (AlexPosn, Code), [Directive], Scanner, Maybe (AlexPosn, Code)) -> (String,String) alex cli script = let target | OptGhcTarget `elem` cli = GhcTarget | otherwise = HaskellTarget (maybe_header, directives, scanner1, maybe_footer) = script (scanner2, scs, sc_hdr) = encodeStartCodes scanner1 (scanner_final, actions) = extractActions scanner2 dfa = scanner2dfa scanner_final scs nm = scannerName scanner_final in (maybe id ((++) . snd) (maybe_header) $ maybe id (flip (++) . snd) (maybe_footer) $ outputDFA target 1 nm dfa "" ++ (actions "") ++ (sc_hdr "") ,(infoDFA 1 nm dfa "")) optsToInject :: Target -> [CLIFlags] -> String optsToInject GhcTarget _ = "{-# OPTIONS -fglasgow-exts -cpp #-}\n" optsToInject _ _ = "{-# OPTIONS -cpp #-}\n" importsToInject :: Target -> [CLIFlags] -> String importsToInject _ cli = always_imports ++ debug_imports ++ glaexts_import where glaexts_import | OptGhcTarget `elem` cli = import_glaexts | otherwise = "" debug_imports | OptDebugParser `elem` cli = import_debug | otherwise = "" -- CPP is turned on for -fglasogw-exts, so we can use conditional -- compilation. We need to #include "config.h" to get hold of -- WORDS_BIGENDIAN (see GenericTemplate.hs). always_imports :: String always_imports = "#if __GLASGOW_HASKELL__ >= 603\n" ++ "#include \"ghcconfig.h\"\n" ++ "#elif defined(__GLASGOW_HASKELL__)\n" ++ "#include \"config.h\"\n" ++ "#endif\n" ++ "#if __GLASGOW_HASKELL__ >= 503\n" ++ "import Data.Array\n" ++ "import Data.Char (ord)\n" ++ "import Data.Array.Base (unsafeAt)\n" ++ "#else\n" ++ "import Array\n" ++ "import Char (ord)\n" ++ "#endif\n" import_glaexts :: String import_glaexts = "#if __GLASGOW_HASKELL__ >= 503\n" ++ "import GHC.Exts\n" ++ "#else\n" ++ "import GlaExts\n" ++ "#endif\n" import_debug :: String import_debug = "#if __GLASGOW_HASKELL__ >= 503\n" ++ "import System.IO\n" ++ "import System.IO.Unsafe\n" ++ "import Debug.Trace\n" ++ "#else\n" ++ "import IO\n" ++ "import IOExts\n" ++ "#endif\n" initialParserEnv :: (Map String CharSet, Map String RExp) initialParserEnv = (initSetEnv, initREEnv) initSetEnv :: Map String CharSet initSetEnv = Map.fromList [("white", charSet " \t\n\v\f\r"), ("printable", charSet [chr 32 .. chr 126]), (".", charSetComplement emptyCharSet `charSetMinus` charSetSingleton '\n')] initREEnv :: Map String RExp initREEnv = Map.empty -- ----------------------------------------------------------------------------- -- Command-line flags data CLIFlags = OptDebugParser | OptGhcTarget | OptOutputFile FilePath | OptInfoFile (Maybe FilePath) | OptTemplateDir FilePath | DumpHelp | DumpVersion deriving Eq