-- A simple test program for the Haskell parser,
-- originally written by Sven Panne.
module Main (main, mainArgs, testLexer) where
import Data.List
import Language.Haskell.Lexer (lexer, Token(EOF))
import Language.Haskell.ParseMonad (runParserWithMode)
import Language.Haskell.Parser
import Language.Haskell.Syntax
import Language.Haskell.Pretty
import System.Environment
import System.Console.GetOpt
data Flag
= LexOnlyLength -- print number of tokens only
| LexOnlyRev -- print tokens in reverse order
| LexOnly -- print tokens
| ParseLength -- print number of declarations only
| ParseInternal -- print abstract syntax in internal format
| ParsePretty PPLayout -- pretty print in this style
| Help -- give short usage info
title :: String
title = "A simple test program for the haskell-src package"
usage :: String
usage = "usage: hsparser [option] [filename]\n"
options :: [OptDescr Flag]
options =
[ Option ['n'] ["numtokens"] (NoArg LexOnlyLength) "print number of tokens only",
Option ['r'] ["revtokens"] (NoArg LexOnlyRev) "print tokens in reverse order",
Option ['t'] ["tokens"] (NoArg LexOnly) "print tokens",
Option ['d'] ["numdecls"] (NoArg ParseLength) "print number of declarations only",
Option ['a'] ["abstract"] (NoArg ParseInternal) "print abstract syntax in internal format",
Option ['p'] ["pretty"] (OptArg pStyle "STYLE") "pretty print in STYLE[(o)ffside|(s)emicolon|(i)nline|(n)one](default = offside)",
Option ['h','?'] ["help"] (NoArg Help) "display this help and exit"]
pStyle :: Maybe String -> Flag
pStyle Nothing = ParsePretty PPOffsideRule
pStyle (Just s) = ParsePretty $ case s of
"o" -> PPOffsideRule
"offside" -> PPOffsideRule
"s" -> PPSemiColon
"semicolon" -> PPSemiColon
"i" -> PPInLine
"inline" -> PPInLine
"n" -> PPNoLayout
"none" -> PPNoLayout
_ -> PPOffsideRule
main :: IO ()
main = do
args <- getArgs
mainArgs args
mainArgs :: [String] -> IO ()
mainArgs cmdline =
case getOpt Permute options cmdline of
(flags, args, []) -> do
inp <- case args of
[] -> getContents
[f] -> readFile f
_ -> error usage
let parse_mode = case args of
[] -> defaultParseMode
[f] -> defaultParseMode {parseFilename = f}
putStrLn (handleFlag (getFlag flags) parse_mode inp)
(_, _, errors) ->
error (concat errors ++ usageInfo usage options)
getFlag :: [Flag] -> Flag
getFlag [] = ParsePretty PPOffsideRule
getFlag [f] = f
getFlag _ = error usage
handleFlag :: Flag -> ParseMode -> String -> String
handleFlag LexOnlyLength parse_mode = show . length . testLexerRev parse_mode
handleFlag LexOnlyRev parse_mode =
concat . intersperse "\n" . map show . testLexerRev parse_mode
handleFlag LexOnly parse_mode =
concat . intersperse "\n" . map show . testLexer parse_mode
handleFlag ParseLength parse_mode =
show . modLength . testParser parse_mode
where modLength (HsModule _ _ _ imp d) = length imp + length d
handleFlag ParseInternal parse_mode = show . testParser parse_mode
handleFlag (ParsePretty l) parse_mode =
prettyPrintStyleMode style{lineLength=80} defaultMode{layout=l} .
testParser parse_mode
handleFlag Help _parse_mode = const $
usageInfo (title ++ "\n" ++ usage) options
testLexerRev :: ParseMode -> String -> [Token]
testLexerRev parse_mode = getResult . runParserWithMode parse_mode (loop [])
where loop toks = lexer $ \t -> case t of
EOF -> return toks
_ -> loop (t:toks)
testLexer :: ParseMode -> String -> [Token]
testLexer parse_mode = reverse . testLexerRev parse_mode
testParser :: ParseMode -> String -> HsModule
testParser parse_mode = getResult . parseModuleWithMode parse_mode
getResult :: ParseResult a -> a
getResult (ParseOk a) = a
getResult (ParseFailed loc err) =
error (srcFilename loc ++ ":" ++ show (srcLine loc) ++ ":" ++
show (srcColumn loc) ++ ": " ++ err)
|