2019-10-02 00:01:50 +03:00
{- # LANGUAGE TypeApplications # -}
2019-11-19 23:39:37 +03:00
2019-10-10 21:59:56 +03:00
module Main ( main ) where
2019-10-01 18:25:14 +03:00
2019-10-02 00:03:37 +03:00
import TreeSitter.Unmarshal
2019-10-22 20:09:13 +03:00
import qualified TreeSitter.Python.AST as AST
2019-10-22 20:40:27 +03:00
import qualified TreeSitter.Python as Python
2019-10-02 00:03:18 +03:00
import Source.Range
import Source.Span
2020-01-07 21:22:08 +03:00
import Data.Aeson ( toJSON )
2019-10-10 21:09:35 +03:00
import Data.ByteString.Char8
2019-11-19 23:39:45 +03:00
import Data.ByteString ( readFile )
2019-10-02 21:34:58 +03:00
import Options.Applicative hiding ( style )
2019-10-19 00:19:11 +03:00
import Text.Pretty.Simple ( pPrint , pPrintNoColor )
2019-10-22 22:29:23 +03:00
import Data.Foldable ( traverse_ )
2019-10-24 18:51:09 +03:00
import Control.Monad ( ( >=> ) )
2019-12-19 18:08:18 +03:00
import Marshal.JSON ( marshal )
2020-01-07 21:38:27 +03:00
import Data.ByteString.Lazy.Char8 ( putStrLn )
2019-12-19 21:31:18 +03:00
import Data.Aeson.Encode.Pretty ( encodePretty )
2019-10-01 18:25:14 +03:00
2019-10-10 20:14:15 +03:00
data SemanticAST = SemanticAST
2019-10-17 01:18:11 +03:00
{ format :: Format
2019-10-24 18:55:47 +03:00
, noColor :: Bool
2019-10-22 20:09:13 +03:00
, source :: Either [ FilePath ] String
2019-10-16 22:15:55 +03:00
}
2019-10-10 20:14:15 +03:00
2019-10-22 20:40:35 +03:00
-- Usage: semantic-ast --format ARG [--no-color] (--sourceString STRING | FILEPATHS…)
2019-10-10 20:14:15 +03:00
parseAST :: Parser SemanticAST
parseAST = SemanticAST
2019-10-16 21:17:07 +03:00
<$> option auto
( long " format "
<> help " Specify desired output: show, json, sexpression " )
2019-10-18 20:43:54 +03:00
<*> switch
2019-10-19 00:19:52 +03:00
( long " no-color "
2019-10-18 20:43:54 +03:00
<> help " Print with color: --color "
)
2019-10-21 19:57:31 +03:00
<*> ( Left <$> some
( Options . Applicative . argument str ( metavar " FILEPATH(S) " ) )
2019-10-16 21:17:07 +03:00
<|> Right <$> strOption
( long " sourceString "
<> metavar " STRING "
<> help " Specify source input to parse "
) )
2019-10-10 20:14:15 +03:00
2019-10-23 18:58:51 +03:00
2019-10-04 01:11:28 +03:00
main :: IO ()
main = generateAST =<< execParser opts
2019-10-23 18:58:51 +03:00
2019-10-10 20:14:15 +03:00
generateAST :: SemanticAST -> IO ()
2019-10-24 18:45:43 +03:00
generateAST ( SemanticAST format noColor source ) =
2019-10-22 22:28:27 +03:00
getByteStrings >>= traverse_ go
2019-10-23 19:01:55 +03:00
where getByteStrings = case source of
Left filePaths -> traverse Data . ByteString . readFile filePaths
Right source -> pure [ Data . ByteString . Char8 . pack source ]
2019-10-24 18:51:09 +03:00
go = ast >=> display
2020-01-16 22:00:16 +03:00
ast = parseByteString @ AST . Module @ ( Range , Span ) Python . tree_sitter_python -- TODO: generalize for all languages
2019-10-24 18:45:43 +03:00
display = case format of
2020-01-07 21:38:27 +03:00
Json -> Data . ByteString . Lazy . Char8 . putStrLn . encodePretty . either toJSON ( marshal . fmap ( const () ) ) -- TODO: replacing range and span annotations with () for which there is a ToJSON instance for now, deal with this later
2019-10-24 18:45:43 +03:00
Show -> print
Pretty | noColor -> pPrintNoColor
| otherwise -> pPrint
2019-10-22 20:53:09 +03:00
2019-10-10 20:14:15 +03:00
2019-10-04 01:11:28 +03:00
opts :: ParserInfo SemanticAST
opts = info ( parseAST <**> helper )
( fullDesc
2019-10-10 20:14:15 +03:00
<> progDesc " Parse source code and produce an AST "
<> header " semantic-ast is a package used to parse source code " )
2019-10-04 01:56:58 +03:00
2019-10-04 01:12:04 +03:00
-- TODO: Define formats for json, sexpression, etc.
2019-10-24 18:31:29 +03:00
data Format = Show
| Pretty
2019-11-19 18:08:45 +03:00
| Json
2019-10-10 20:13:51 +03:00
deriving ( Read )