packages feed

hjs-0.1: src/Main.hs

{-
  Haskell Javascript Parser
  (c) Mark Wassell 2007
  See LICENSE file for license details

-}
module Main(main,lexer,parseProgram,parseTest,parseFile) where


import Data.ByteString.Char8(split,pack,unpack,join,readInt)
import Data.List
import Data.Ord
import Data.Char

import System.Console.GetOpt
import Data.Maybe ( fromMaybe )

import Control.Monad.Identity
import Control.Monad.Error
import Control.Monad.State

import System.Directory
import System.Environment

import HJS.Parser.Lexer
import HJS.Parser.LexerM
import HJS.Parser.JavaScriptParser
import HJS.Parser.JavaScript
import HJS.Parser.ParserMonad

import HJS.Interpreter.Interp

data VFlag = Quiet | ShowProgress | ShowErrors | ShowAST deriving (Show,Eq)

-- Parse a JS program
parseProgram str =  runIdentity $ runErrorT $ runStateT jsprogram 
		    (startState str)

-- Parse primitive expression
parsePrimExpr str =  runIdentity $ runErrorT $ runStateT primexpr (startState str)

-- Parse a file with supplied flags
parseFile :: [VFlag] -> String -> IO ()
parseFile flags fname = do
                          ifM (elem ShowProgress flags) (putStr $ "Parsing \"" ++ fname) (return ())
                          s <- readFile fname
                          handleResult flags $ parseProgram s 

handleResult flags (Right r) | (elem ShowProgress flags) = putStrLn ("\"  ok")
                             | (elem ShowAST flags)      = putStrLn ("\" ok " ++ show r)
                             | otherwise = return ()
handleResult flags (Left r)  | (elem ShowProgress flags) = putStrLn ("\"  failed")
                             | (elem ShowErrors flags)   = putStrLn  ("\" failed" ++ r)
                             | otherwise = return ()

lexFile fname = do
                   s <- readFile fname
                   putStrLn $ show $ alexScanTokens s

runFile fname = do
               putStrLn $ "Running: " ++ fname
               s <- readFile fname
               case parseProgram s of 
                              Right (r,s) -> putStrLn $ show $ interp r
                              Left s -> putStrLn s


main = do
         s <- getArgs
	 main' s

main' args = do 
         (opt, files) <- interpOpts args
         case (foldr (\x s -> case x of Version -> (True || s); _ -> s) False opt) of 
             True -> putStrLn "HJS - JavaScript Parser - Version 0.1"
             _ -> return ()
         let vf = foldr (\x s -> case x of (Verbose f) -> (f:s);_ -> s) [] opt
         mapM_ (parseFile vf) files
	

parseTest = do 
	     testFiles "../test" (parseFile [])
	     testFiles "../test/parsingonly" (parseFile [])


runTest = testFiles "../test" runFile

testFiles dir action =   do fileList <- getTestFiles dir
			    mapM_ action  fileList


             
getTestFiles dirName  = do
          dirList <- getDirectoryContents dirName
          return $  map (\f -> dirName ++ "/" ++ f) $
                    map unpack $ 
	            map (Data.ByteString.Char8.join (pack "_"))  $ 
		    sortBy (comparing (readInt . head)) $ 
		    filter (\l -> (<=) 2 (length l)) $ 
		    map (split '_' . pack) $ 
	            filter (\x -> last x /= '~' || head x == '.' ) dirList



    
data Flag  = Verbose VFlag | Version  
		 deriving Show
    
options :: [OptDescr Flag]
options =
     [ Option ['v']     ["verbose"] (OptArg vflag "LEVEL" )       "=1 show progrss, =2 show errors =3 show AST"
     , Option ['V','?'] ["version"] (NoArg Version)       "show version number"
     ]
    
vflag :: Maybe String -> Flag
vflag Nothing = Verbose Quiet
vflag (Just s) = let s' = filter (\c -> not $ isSpace c) s
                 in case s' of 
                          "1" -> Verbose ShowProgress
   		          "2" -> Verbose ShowErrors
                          "3" -> Verbose ShowAST
                          _ -> error $ "Cannot parse verbosity option " ++ s'

--inp,outp :: Maybe String -> Flag
--outp = Output . fromMaybe "stdout"
--inp  = Input  . fromMaybe "stdin"
    
interpOpts :: [String] -> IO ([Flag], [String])
interpOpts argv = 
       case getOpt Permute options argv of
          (o,n,[]  ) -> return (o,n)
          (_,_,errs) -> ioError (userError (concat errs ++ usageInfo header options))
      where header = "Usage: hjs [OPTION...] files..."