{-# language DataKinds #-} {-# language FlexibleContexts #-} {-# language MultiParamTypeClasses, FlexibleInstances #-} {-| Module : Language.Python.Parse Copyright : (C) CSIRO 2017-2018 License : BSD3 Maintainer : Isaac Elliott Stability : experimental Portability : non-portable -} module Language.Python.Parse ( module Language.Python.Parse.Error , Parser , parseModule , parseStatement , parseExpr , parseExprList -- * Source Information , SrcInfo(..), initialSrcInfo ) where import Control.Applicative ((<|>)) import Data.Bifunctor (first) import Data.List.NonEmpty (NonEmpty) import Data.Text (Text) import Data.Validation (Validation, bindValidation, fromEither) import Text.Megaparsec (eof) import Language.Python.Internal.Lexer ( SrcInfo(..), initialSrcInfo, withSrcInfo , tokenize, insertTabs ) import Language.Python.Internal.Token (PyToken) import Language.Python.Internal.Parse ( Parser, runParser, level, module_, statement, exprOrStarList , expr, space ) import Language.Python.Internal.Syntax.IR (AsIRError) import Language.Python.Parse.Error import Language.Python.Syntax.Expr (Expr) import Language.Python.Syntax.Module (Module) import Language.Python.Syntax.Statement (Statement) import Language.Python.Syntax.Whitespace (Indents (..)) import qualified Language.Python.Internal.Syntax.IR as IR -- | Parse a module -- -- https://docs.python.org/3/reference/toplevel_components.html#file-input parseModule :: ( AsLexicalError e Char , AsTabError e SrcInfo , AsIncorrectDedent e SrcInfo , AsParseError e (PyToken SrcInfo) , AsIRError e SrcInfo ) => FilePath -- ^ File name -> Text -- ^ Input to parse -> Validation (NonEmpty e) (Module '[] SrcInfo) parseModule fp input = let si = initialSrcInfo fp ir = do tokens <- tokenize fp input tabbed <- insertTabs si tokens runParser fp module_ tabbed in fromEither (first pure ir) `bindValidation` IR.fromIR -- | Parse a statement -- -- https://docs.python.org/3/reference/compound_stmts.html#grammar-token-statement parseStatement :: ( AsLexicalError e Char , AsTabError e SrcInfo , AsIncorrectDedent e SrcInfo , AsParseError e (PyToken SrcInfo) , AsIRError e SrcInfo ) => FilePath -- ^ File name -> Text -- ^ Input to parse -> Validation (NonEmpty e) (Statement '[] SrcInfo) parseStatement fp input = let si = initialSrcInfo fp ir = do tokens <- tokenize fp input tabbed <- insertTabs si tokens runParser fp ((statement tlIndent =<< tlIndent) <* eof) tabbed in fromEither (first pure ir) `bindValidation` IR.fromIR_statement where tlIndent = level <|> withSrcInfo (pure $ Indents []) -- | Parse an expression list (unparenthesised tuple) -- -- https://docs.python.org/3.5/reference/expressions.html#grammar-token-expression_list parseExprList :: ( AsLexicalError e Char , AsTabError e SrcInfo , AsIncorrectDedent e SrcInfo , AsParseError e (PyToken SrcInfo) , AsIRError e SrcInfo ) => FilePath -- ^ File name -> Text -- ^ Input to parse -> Validation (NonEmpty e) (Expr '[] SrcInfo) parseExprList fp input = let si = initialSrcInfo fp ir = do tokens <- tokenize fp input tabbed <- insertTabs si tokens runParser fp (exprOrStarList space <* eof) tabbed in fromEither (first pure ir) `bindValidation` IR.fromIR_expr -- | Parse an expression -- -- https://docs.python.org/3.5/reference/expressions.html#grammar-token-expression parseExpr :: ( AsLexicalError e Char , AsTabError e SrcInfo , AsIncorrectDedent e SrcInfo , AsParseError e (PyToken SrcInfo) , AsIRError e SrcInfo ) => FilePath -- ^ File name -> Text -- ^ Input to parse -> Validation (NonEmpty e) (Expr '[] SrcInfo) parseExpr fp input = let si = initialSrcInfo fp ir = do tokens <- tokenize fp input tabbed <- insertTabs si tokens runParser fp (expr space <* eof) tabbed in fromEither (first pure ir) `bindValidation` IR.fromIR_expr