1
1
mirror of https://github.com/github/semantic.git synced 2024-11-24 17:04:47 +03:00

Merge branch 'master' into list-parsers-independently

This commit is contained in:
Rob Rix 2019-10-02 20:27:30 -04:00 committed by GitHub
commit 54324a98a7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 14 deletions

View File

@ -60,13 +60,13 @@ runParser blob@Blob{..} parser = case parser of
time "parse.tree_sitter_ast_parse" languageTag $ do time "parse.tree_sitter_ast_parse" languageTag $ do
config <- asks config config <- asks config
parseToAST (configTreeSitterParseTimeout config) language blob parseToAST (configTreeSitterParseTimeout config) language blob
>>= either (trace >=> const (throwError (SomeException ParserTimedOut))) pure >>= either (\e -> trace (displayException e) *> throwError (SomeException e)) pure
UnmarshalParser language -> UnmarshalParser language ->
time "parse.tree_sitter_ast_parse" languageTag $ do time "parse.tree_sitter_ast_parse" languageTag $ do
config <- asks config config <- asks config
parseToPreciseAST (configTreeSitterParseTimeout config) language blob parseToPreciseAST (configTreeSitterParseTimeout config) language blob
>>= either (trace >=> const (throwError (SomeException ParserTimedOut))) pure >>= either (\e -> trace (displayException e) *> throwError (SomeException e)) pure
AssignmentParser parser assignment -> runAssignment Assignment.assign parser blob assignment AssignmentParser parser assignment -> runAssignment Assignment.assign parser blob assignment
DeterministicParser parser assignment -> runAssignment Deterministic.assign parser blob assignment DeterministicParser parser assignment -> runAssignment Deterministic.assign parser blob assignment

View File

@ -51,11 +51,11 @@ runParser
runParser timeout blob@Blob{..} parser = case parser of runParser timeout blob@Blob{..} parser = case parser of
ASTParser language -> ASTParser language ->
parseToAST timeout language blob parseToAST timeout language blob
>>= either (throwError . SomeException . ParseFailure) pure >>= either (throwError . SomeException) pure
UnmarshalParser language -> UnmarshalParser language ->
parseToPreciseAST timeout language blob parseToPreciseAST timeout language blob
>>= either (throwError . SomeException . ParseFailure) pure >>= either (throwError . SomeException) pure
AssignmentParser parser assignment -> AssignmentParser parser assignment ->
runParser timeout blob parser >>= either (throwError . toException) pure . Assignment.assign blobSource assignment runParser timeout blob parser >>= either (throwError . toException) pure . Assignment.assign blobSource assignment

View File

@ -1,6 +1,7 @@
{-# LANGUAGE DataKinds, GADTs, ScopedTypeVariables, TypeOperators #-} {-# LANGUAGE DataKinds, GADTs, LambdaCase, ScopedTypeVariables, TypeOperators #-}
module Parsing.TreeSitter module Parsing.TreeSitter
( Duration(..) ( TSParseException (..)
, Duration(..)
, parseToAST , parseToAST
, parseToPreciseAST , parseToPreciseAST
) where ) where
@ -10,6 +11,7 @@ import Prologue
import Control.Effect.Fail import Control.Effect.Fail
import Control.Effect.Lift import Control.Effect.Lift
import Control.Effect.Reader import Control.Effect.Reader
import qualified Control.Exception as Exc
import Foreign import Foreign
import Foreign.C.Types (CBool (..)) import Foreign.C.Types (CBool (..))
import Foreign.Marshal.Array (allocaArray) import Foreign.Marshal.Array (allocaArray)
@ -29,6 +31,12 @@ import qualified TreeSitter.Parser as TS
import qualified TreeSitter.Tree as TS import qualified TreeSitter.Tree as TS
import qualified TreeSitter.Unmarshal as TS import qualified TreeSitter.Unmarshal as TS
data TSParseException
= ParserTimedOut
| IncompatibleVersions
| UnmarshalFailure String
deriving (Eq, Show, Generic)
-- | Parse a 'Blob' with the given 'TS.Language' and return its AST. -- | Parse a 'Blob' with the given 'TS.Language' and return its AST.
-- Returns 'Nothing' if the operation timed out. -- Returns 'Nothing' if the operation timed out.
parseToAST :: ( Bounded grammar parseToAST :: ( Bounded grammar
@ -38,8 +46,8 @@ parseToAST :: ( Bounded grammar
=> Duration => Duration
-> Ptr TS.Language -> Ptr TS.Language
-> Blob -> Blob
-> m (Either String (AST [] grammar)) -> m (Either TSParseException (AST [] grammar))
parseToAST parseTimeout language blob = runParse parseTimeout language blob (fmap Right . anaM toAST <=< peek) parseToAST parseTimeout language blob = runParse parseTimeout language blob (anaM toAST <=< peek)
parseToPreciseAST parseToPreciseAST
:: ( MonadIO m :: ( MonadIO m
@ -48,20 +56,27 @@ parseToPreciseAST
=> Duration => Duration
-> Ptr TS.Language -> Ptr TS.Language
-> Blob -> Blob
-> m (Either String (t Loc)) -> m (Either TSParseException (t Loc))
parseToPreciseAST parseTimeout language blob = runParse parseTimeout language blob $ \ rootPtr -> parseToPreciseAST parseTimeout language blob = runParse parseTimeout language blob $ \ rootPtr ->
TS.withCursor (castPtr rootPtr) $ \ cursor -> TS.withCursor (castPtr rootPtr) $ \ cursor ->
runM (runFail (runReader cursor (runReader (Source.bytes (blobSource blob)) (TS.peekNode >>= TS.unmarshalNode)))) runM (runFail (runReader cursor (runReader (Source.bytes (blobSource blob)) (TS.peekNode >>= TS.unmarshalNode))))
>>= either (Exc.throw . UnmarshalFailure) pure
instance Exception TSParseException where
displayException = \case
ParserTimedOut -> "tree-sitter: parser timed out"
IncompatibleVersions -> "tree-sitter: incompatible versions"
UnmarshalFailure s -> "tree-sitter: unmarshal failure - " <> show s
runParse runParse
:: MonadIO m :: MonadIO m
=> Duration => Duration
-> Ptr TS.Language -> Ptr TS.Language
-> Blob -> Blob
-> (Ptr TS.Node -> IO (Either String a)) -> (Ptr TS.Node -> IO a)
-> m (Either String a) -> m (Either TSParseException a)
runParse parseTimeout language Blob{..} action = runParse parseTimeout language Blob{..} action =
liftIO . TS.withParser language $ \ parser -> do liftIO . Exc.tryJust fromException . TS.withParser language $ \ parser -> do
let timeoutMicros = fromIntegral $ toMicroseconds parseTimeout let timeoutMicros = fromIntegral $ toMicroseconds parseTimeout
TS.ts_parser_set_timeout_micros parser timeoutMicros TS.ts_parser_set_timeout_micros parser timeoutMicros
TS.ts_parser_halt_on_error parser (CBool 1) TS.ts_parser_halt_on_error parser (CBool 1)
@ -69,11 +84,11 @@ runParse parseTimeout language Blob{..} action =
if compatible then if compatible then
TS.withParseTree parser (Source.bytes blobSource) $ \ treePtr -> do TS.withParseTree parser (Source.bytes blobSource) $ \ treePtr -> do
if treePtr == nullPtr then if treePtr == nullPtr then
pure (Left "tree-sitter: null root node") Exc.throw ParserTimedOut
else else
TS.withRootNode treePtr action TS.withRootNode treePtr action
else else
pure (Left "tree-sitter: incompatible versions") Exc.throw IncompatibleVersions
toAST :: forall grammar . (Bounded grammar, Enum grammar) => TS.Node -> IO (Base (AST [] grammar) TS.Node) toAST :: forall grammar . (Bounded grammar, Enum grammar) => TS.Node -> IO (Base (AST [] grammar) TS.Node)
toAST node@TS.Node{..} = do toAST node@TS.Node{..} = do