From 0e5c97038fc7880d8c5950cbb86804972dd0795f Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 4 Feb 2020 14:25:39 -0500 Subject: [PATCH] Add a semantic-parse package. --- cabal.project | 1 + cabal.project.ci | 1 + script/ghci-flags | 1 + semantic-parse/CHANGELOG.md | 5 ++ semantic-parse/LICENSE | 21 ++++++++ semantic-parse/Setup.hs | 2 + semantic-parse/app/Main.hs | 75 +++++++++++++++++++++++++++++ semantic-parse/semantic-parse.cabal | 57 ++++++++++++++++++++++ 8 files changed, 163 insertions(+) create mode 100644 semantic-parse/CHANGELOG.md create mode 100644 semantic-parse/LICENSE create mode 100644 semantic-parse/Setup.hs create mode 100644 semantic-parse/app/Main.hs create mode 100644 semantic-parse/semantic-parse.cabal diff --git a/cabal.project b/cabal.project index 3bba22f83..e39e01577 100644 --- a/cabal.project +++ b/cabal.project @@ -9,6 +9,7 @@ packages: . semantic-go semantic-java semantic-json + semantic-parse semantic-python semantic-ruby semantic-scope-graph diff --git a/cabal.project.ci b/cabal.project.ci index 4ce526d96..d8c29ef4a 100644 --- a/cabal.project.ci +++ b/cabal.project.ci @@ -9,6 +9,7 @@ packages: . semantic-go semantic-java semantic-json + semantic-parse semantic-python semantic-ruby semantic-scope-graph diff --git a/script/ghci-flags b/script/ghci-flags index 627c9f3e8..1d2842bb9 100755 --- a/script/ghci-flags +++ b/script/ghci-flags @@ -53,6 +53,7 @@ function flags { echo "-isemantic-go/src" echo "-isemantic-java/src" echo "-isemantic-json/src" + echo "-isemantic-parse/src" echo "-isemantic-python/src" echo "-isemantic-python/test" echo "-isemantic-ruby/src" diff --git a/semantic-parse/CHANGELOG.md b/semantic-parse/CHANGELOG.md new file mode 100644 index 000000000..ee89a5d7d --- /dev/null +++ b/semantic-parse/CHANGELOG.md @@ -0,0 +1,5 @@ +# Revision history for semantic-parse + +## 0.1.0.0 -- YYYY-mm-dd + +* First version. Released on an unsuspecting world. diff --git a/semantic-parse/LICENSE b/semantic-parse/LICENSE new file mode 100644 index 000000000..331b241b3 --- /dev/null +++ b/semantic-parse/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 GitHub + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/semantic-parse/Setup.hs b/semantic-parse/Setup.hs new file mode 100644 index 000000000..9a994af67 --- /dev/null +++ b/semantic-parse/Setup.hs @@ -0,0 +1,2 @@ +import Distribution.Simple +main = defaultMain diff --git a/semantic-parse/app/Main.hs b/semantic-parse/app/Main.hs new file mode 100644 index 000000000..9425b22a5 --- /dev/null +++ b/semantic-parse/app/Main.hs @@ -0,0 +1,75 @@ +{-# LANGUAGE TypeApplications #-} + +module Main (main) where + +import AST.Unmarshal +import qualified Language.Python.AST as AST +import qualified Language.Python.Grammar as Python +import Source.Range +import Source.Span +import Data.Aeson (toJSON) +import Data.ByteString.Char8 +import Data.ByteString (readFile) +import Options.Applicative hiding (style) +import Text.Pretty.Simple (pPrint, pPrintNoColor) +import Data.Foldable (traverse_) +import Control.Monad ((>=>)) +import Marshal.JSON (marshal) +import Data.ByteString.Lazy.Char8 (putStrLn) +import Data.Aeson.Encode.Pretty (encodePretty) + +data SemanticAST = SemanticAST + { _format :: Format + , _noColor :: Bool + , _source :: Either [FilePath] String + } + +-- Usage: semantic-ast --format ARG [--no-color] (--sourceString STRING | FILEPATHS…) +parseAST :: Parser SemanticAST +parseAST = SemanticAST + <$> option auto + ( long "format" + <> help "Specify desired output: show, json, sexpression" ) + <*> switch + ( long "no-color" + <> help "Print with color: --color" + ) + <*> (Left <$> some + (Options.Applicative.argument str (metavar "FILEPATH(S)")) + <|> Right <$> strOption + ( long "sourceString" + <> metavar "STRING" + <> help "Specify source input to parse" + )) + + +main :: IO () +main = generateAST =<< execParser opts + + +generateAST :: SemanticAST -> IO () +generateAST (SemanticAST format noColor source) = + getByteStrings >>= traverse_ go + where getByteStrings = case source of + Left filePaths -> traverse Data.ByteString.readFile filePaths + Right source -> pure [Data.ByteString.Char8.pack source] + go = ast >=> display + ast = parseByteString @AST.Module @(Range, Span) Python.tree_sitter_python -- TODO: generalize for all languages + display = case format of + 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 + Show -> print + Pretty | noColor -> pPrintNoColor + | otherwise -> pPrint + + +opts :: ParserInfo SemanticAST +opts = info (parseAST <**> helper) + ( fullDesc + <> progDesc "Parse source code and produce an AST" + <> header "semantic-ast is a package used to parse source code" ) + +-- TODO: Define formats for json, sexpression, etc. +data Format = Show + | Pretty + | Json + deriving (Read) diff --git a/semantic-parse/semantic-parse.cabal b/semantic-parse/semantic-parse.cabal new file mode 100644 index 000000000..9d428745c --- /dev/null +++ b/semantic-parse/semantic-parse.cabal @@ -0,0 +1,57 @@ +cabal-version: 2.4 +-- Initial package description 'semantic-ast.cabal' generated by 'cabal +-- init'. For further documentation, see +-- http://haskell.org/cabal/users-guide/ + +name: semantic-parse +version: 0.1.0.0 +-- synopsis: +-- description: +-- bug-reports: +license: MIT +license-file: LICENSE +author: The Semantic Authors +maintainer: opensource+semantic@github.com +copyright: (c) 2019 GitHub, Inc. +category: Language +extra-source-files: CHANGELOG.md + +tested-with: GHC == 8.6.5 + +common haskell + default-language: Haskell2010 + ghc-options: + -Weverything + -Wno-missing-local-signatures + -Wno-missing-import-lists + -Wno-implicit-prelude + -Wno-safe + -Wno-unsafe + -Wno-name-shadowing + -Wno-monomorphism-restriction + -Wno-missed-specialisations + -Wno-all-missed-specialisations + -Wno-star-is-type + if (impl(ghc >= 8.8)) + ghc-options: -Wno-missing-deriving-strategies + +executable semantic-parse + import: haskell + main-is: Main.hs + -- other-modules: + -- other-extensions: + build-depends: base + , semantic-ast + , tree-sitter + , semantic-source + , tree-sitter-python ^>= 0.8.1 + , bytestring + , optparse-applicative + , pretty-simple + , aeson + , bytestring + , aeson-pretty + , semantic-python + , text + hs-source-dirs: app + default-language: Haskell2010