mirror of
https://github.com/github/semantic.git
synced 2024-11-24 08:54:07 +03:00
Update Python
This commit is contained in:
parent
2be6e5eef6
commit
bf4300e5eb
@ -60,6 +60,7 @@ library
|
|||||||
, Language.TypeScript
|
, Language.TypeScript
|
||||||
, Language.TypeScript.Grammar
|
, Language.TypeScript.Grammar
|
||||||
, Language.TypeScript.Syntax
|
, Language.TypeScript.Syntax
|
||||||
|
, Language.Python.Assignment
|
||||||
, Language.Python.Grammar
|
, Language.Python.Grammar
|
||||||
, Language.Python.Syntax
|
, Language.Python.Syntax
|
||||||
, Parser
|
, Parser
|
||||||
|
481
src/Language/Python/Assignment.hs
Normal file
481
src/Language/Python/Assignment.hs
Normal file
@ -0,0 +1,481 @@
|
|||||||
|
{-# LANGUAGE DataKinds, RankNTypes, TypeOperators #-}
|
||||||
|
module Language.Python.Assignment
|
||||||
|
( assignment
|
||||||
|
, Syntax
|
||||||
|
, Grammar
|
||||||
|
, Term
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Data.Functor (void)
|
||||||
|
import Data.List.NonEmpty (some1)
|
||||||
|
import Data.Maybe (fromMaybe)
|
||||||
|
import Data.Record
|
||||||
|
import Data.Syntax (contextualize, emptyTerm, handleError, infixContext, makeTerm, makeTerm', makeTerm1, parseError, postContextualize)
|
||||||
|
import qualified Data.Syntax as Syntax
|
||||||
|
import Data.Syntax.Assignment hiding (Assignment, Error)
|
||||||
|
import qualified Data.Syntax.Assignment as Assignment
|
||||||
|
import qualified Data.Syntax.Comment as Comment
|
||||||
|
import qualified Data.Syntax.Declaration as Declaration
|
||||||
|
import qualified Data.Syntax.Expression as Expression
|
||||||
|
import qualified Data.Syntax.Literal as Literal
|
||||||
|
import qualified Data.Syntax.Statement as Statement
|
||||||
|
import qualified Data.Syntax.Type as Type
|
||||||
|
import qualified Data.Term as Term
|
||||||
|
import Data.Union
|
||||||
|
import GHC.Stack
|
||||||
|
import Language.Python.Syntax as Python.Syntax
|
||||||
|
import Language.Python.Grammar as Grammar
|
||||||
|
|
||||||
|
type Syntax =
|
||||||
|
'[ Comment.Comment
|
||||||
|
, Declaration.Class
|
||||||
|
, Declaration.Comprehension
|
||||||
|
, Declaration.Decorator
|
||||||
|
, Declaration.Function
|
||||||
|
, Declaration.Import
|
||||||
|
, Declaration.Variable
|
||||||
|
, Expression.Arithmetic
|
||||||
|
, Expression.Boolean
|
||||||
|
, Expression.Bitwise
|
||||||
|
, Expression.Call
|
||||||
|
, Expression.Comparison
|
||||||
|
, Expression.Enumeration
|
||||||
|
, Expression.ScopeResolution
|
||||||
|
, Expression.MemberAccess
|
||||||
|
, Expression.Subscript
|
||||||
|
, Literal.Array
|
||||||
|
, Literal.Boolean
|
||||||
|
, Literal.Float
|
||||||
|
, Literal.Hash
|
||||||
|
, Literal.Integer
|
||||||
|
, Literal.KeyValue
|
||||||
|
, Literal.Null
|
||||||
|
, Literal.Set
|
||||||
|
, Literal.String
|
||||||
|
, Literal.TextElement
|
||||||
|
, Literal.Tuple
|
||||||
|
, Python.Syntax.Redirect
|
||||||
|
, Statement.Assignment
|
||||||
|
, Statement.Break
|
||||||
|
, Statement.Catch
|
||||||
|
, Statement.Continue
|
||||||
|
, Statement.Else
|
||||||
|
, Statement.Finally
|
||||||
|
, Statement.ForEach
|
||||||
|
, Statement.If
|
||||||
|
, Statement.Let
|
||||||
|
, Statement.NoOp
|
||||||
|
, Statement.Return
|
||||||
|
, Statement.Throw
|
||||||
|
, Statement.Try
|
||||||
|
, Statement.While
|
||||||
|
, Statement.Yield
|
||||||
|
, Python.Syntax.Ellipsis
|
||||||
|
, Syntax.Context
|
||||||
|
, Syntax.Empty
|
||||||
|
, Syntax.Error
|
||||||
|
, Syntax.Identifier
|
||||||
|
, Syntax.Program
|
||||||
|
, Type.Annotation
|
||||||
|
, []
|
||||||
|
]
|
||||||
|
|
||||||
|
type Term = Term.Term (Union Syntax) (Record Location)
|
||||||
|
type Assignment = HasCallStack => Assignment.Assignment [] Grammar Term
|
||||||
|
|
||||||
|
-- | Assignment from AST in Python's grammar onto a program in Python's syntax.
|
||||||
|
assignment :: Assignment
|
||||||
|
assignment = handleError $ makeTerm <$> symbol Module <*> children (Syntax.Program <$> many expression) <|> parseError
|
||||||
|
|
||||||
|
expression :: Assignment
|
||||||
|
expression = term (handleError (choice expressionChoices))
|
||||||
|
|
||||||
|
expressionChoices :: [Assignment.Assignment [] Grammar Term]
|
||||||
|
expressionChoices =
|
||||||
|
-- Long-term, can we de/serialize assignments and avoid paying the cost of construction altogether?
|
||||||
|
[ argumentList
|
||||||
|
, assertStatement
|
||||||
|
, assignment'
|
||||||
|
, await
|
||||||
|
, binaryOperator
|
||||||
|
, boolean
|
||||||
|
, booleanOperator
|
||||||
|
, breakStatement
|
||||||
|
, call
|
||||||
|
, classDefinition
|
||||||
|
, comparisonOperator
|
||||||
|
, comprehension
|
||||||
|
, concatenatedString
|
||||||
|
, conditionalExpression
|
||||||
|
, continueStatement
|
||||||
|
, decoratedDefinition
|
||||||
|
, deleteStatement
|
||||||
|
, dictionary
|
||||||
|
, dictionarySplat
|
||||||
|
, dottedName
|
||||||
|
, ellipsis
|
||||||
|
, exceptClause
|
||||||
|
, execStatement
|
||||||
|
, expressionList
|
||||||
|
, expressionStatement
|
||||||
|
, finallyClause
|
||||||
|
, float
|
||||||
|
, forInClause
|
||||||
|
, forStatement
|
||||||
|
, functionDefinition
|
||||||
|
, globalStatement
|
||||||
|
, identifier
|
||||||
|
, ifClause
|
||||||
|
, ifStatement
|
||||||
|
, import'
|
||||||
|
, integer
|
||||||
|
, keywordArgument
|
||||||
|
, list'
|
||||||
|
, listSplat
|
||||||
|
, memberAccess
|
||||||
|
, none
|
||||||
|
, nonlocalStatement
|
||||||
|
, notOperator
|
||||||
|
, pair
|
||||||
|
, parameter
|
||||||
|
, parenthesizedExpression
|
||||||
|
, parseError
|
||||||
|
, passStatement
|
||||||
|
, printStatement
|
||||||
|
, raiseStatement
|
||||||
|
, returnStatement
|
||||||
|
, set
|
||||||
|
, slice
|
||||||
|
, string
|
||||||
|
, subscript
|
||||||
|
, tryStatement
|
||||||
|
, tuple
|
||||||
|
, type'
|
||||||
|
, unaryOperator
|
||||||
|
, variables
|
||||||
|
, whileStatement
|
||||||
|
, withStatement
|
||||||
|
, yield
|
||||||
|
]
|
||||||
|
|
||||||
|
expressions :: Assignment
|
||||||
|
expressions = makeTerm <$> location <*> many expression
|
||||||
|
|
||||||
|
expressionStatement :: Assignment
|
||||||
|
expressionStatement = mk <$> symbol ExpressionStatement <*> children (some expression)
|
||||||
|
where mk _ [child] = child
|
||||||
|
mk location children = makeTerm location children
|
||||||
|
|
||||||
|
expressionList :: Assignment
|
||||||
|
expressionList = mk <$> symbol ExpressionList <*> children (some expression)
|
||||||
|
where mk _ [child] = child
|
||||||
|
mk location children = makeTerm location children
|
||||||
|
|
||||||
|
listSplat :: Assignment
|
||||||
|
listSplat = makeTerm <$> symbol ListSplat <*> (Syntax.Identifier <$> source)
|
||||||
|
|
||||||
|
dictionarySplat :: Assignment
|
||||||
|
dictionarySplat = makeTerm <$> symbol DictionarySplat <*> (Syntax.Identifier <$> source)
|
||||||
|
|
||||||
|
keywordArgument :: Assignment
|
||||||
|
keywordArgument = makeTerm <$> symbol KeywordArgument <*> children (Statement.Assignment [] <$> expression <*> expression)
|
||||||
|
|
||||||
|
parenthesizedExpression :: Assignment
|
||||||
|
parenthesizedExpression = symbol ParenthesizedExpression *> children expressions
|
||||||
|
|
||||||
|
parameter :: Assignment
|
||||||
|
parameter = makeTerm <$> symbol DefaultParameter <*> children (Statement.Assignment [] <$> expression <*> expression)
|
||||||
|
<|> makeTerm <$> symbol TypedParameter <*> children (Type.Annotation <$> expression <*> type')
|
||||||
|
<|> makeAnnotation <$> symbol TypedDefaultParameter <*> children ((,,) <$> expression <*> expression <*> expression)
|
||||||
|
where
|
||||||
|
makeAnnotation loc (identifier', type', value') = makeTerm loc (Type.Annotation (makeAssignment loc identifier' value') type')
|
||||||
|
makeAssignment loc identifier' value' = makeTerm loc (Statement.Assignment [] identifier' value')
|
||||||
|
|
||||||
|
decoratedDefinition :: Assignment
|
||||||
|
decoratedDefinition = symbol DecoratedDefinition *> children (term decorator)
|
||||||
|
where
|
||||||
|
decorator = makeTerm <$> symbol Decorator <*> (children (Declaration.Decorator <$> expression <*> many expression) <*> term (decorator <|> functionDefinition <|> classDefinition))
|
||||||
|
|
||||||
|
argumentList :: Assignment
|
||||||
|
argumentList = symbol ArgumentList *> children expressions
|
||||||
|
|
||||||
|
withStatement :: Assignment
|
||||||
|
withStatement = mk <$> symbol WithStatement <*> children (some with)
|
||||||
|
where
|
||||||
|
mk _ [child] = child
|
||||||
|
mk l children = makeTerm l children
|
||||||
|
with = makeTerm <$> location <*> (withItem <*> (makeTerm <$> location <*> manyTermsTill expression (void (symbol WithItem) <|> eof)))
|
||||||
|
withItem = symbol WithItem *> children (flip Statement.Let <$> expression <*> (expression <|> emptyTerm))
|
||||||
|
<|> flip Statement.Let <$> expression <*> emptyTerm
|
||||||
|
|
||||||
|
forStatement :: Assignment
|
||||||
|
forStatement = symbol ForStatement >>= \ loc -> children (make loc <$> (symbol Variables *> children expressions) <*> expressionList <*> (makeTerm <$> location <*> manyTermsTill expression (void (symbol ElseClause) <|> eof)) <*> optional (symbol ElseClause *> children expressions))
|
||||||
|
where
|
||||||
|
make loc binding subject body forElseClause = case forElseClause of
|
||||||
|
Nothing -> makeTerm loc (Statement.ForEach binding subject body)
|
||||||
|
Just a -> makeTerm loc (Statement.Else (makeTerm loc $ Statement.ForEach binding subject body) a)
|
||||||
|
|
||||||
|
whileStatement :: Assignment
|
||||||
|
whileStatement = symbol WhileStatement >>= \ loc -> children (make loc <$> expression <*> (makeTerm <$> location <*> manyTermsTill expression (void (symbol ElseClause) <|> eof)) <*> optional (symbol ElseClause *> children expressions))
|
||||||
|
where
|
||||||
|
make loc whileCondition whileBody whileElseClause = case whileElseClause of
|
||||||
|
Nothing -> makeTerm loc (Statement.While whileCondition whileBody)
|
||||||
|
Just a -> makeTerm loc (Statement.Else (makeTerm loc $ Statement.While whileCondition whileBody) a)
|
||||||
|
|
||||||
|
tryStatement :: Assignment
|
||||||
|
tryStatement = makeTerm <$> symbol TryStatement <*> children (Statement.Try <$> expression <*> many (expression <|> elseClause))
|
||||||
|
where elseClause = makeTerm <$> symbol ElseClause <*> children (Statement.Else <$> emptyTerm <*> expressions)
|
||||||
|
|
||||||
|
exceptClause :: Assignment
|
||||||
|
exceptClause = makeTerm <$> symbol ExceptClause <*> children
|
||||||
|
(Statement.Catch <$> ((makeTerm <$> location <*> (uncurry (flip Statement.Let) <$> ((,) <$> expression <* symbol AnonAs <*> expression) <*> emptyTerm))
|
||||||
|
<|> expressions)
|
||||||
|
<*> expressions)
|
||||||
|
|
||||||
|
functionDefinition :: Assignment
|
||||||
|
functionDefinition
|
||||||
|
= makeFunctionDeclaration <$> symbol FunctionDefinition <*> children ((,,,) <$> expression <* symbol Parameters <*> children (many expression) <*> optional (symbol Type *> children expression) <*> expressions)
|
||||||
|
<|> makeAsyncFunctionDeclaration <$> symbol AsyncFunctionDefinition <*> children ((,,,,) <$> async' <*> expression <* symbol Parameters <*> children (many expression) <*> optional (symbol Type *> children expression) <*> expressions)
|
||||||
|
<|> makeFunctionDeclaration <$> (symbol Lambda' <|> symbol Lambda) <*> children ((,,,) <$ token AnonLambda <*> emptyTerm <*> (symbol LambdaParameters *> children (many expression) <|> pure []) <*> optional (symbol Type *> children expression) <*> expressions)
|
||||||
|
where
|
||||||
|
makeFunctionDeclaration loc (functionName', functionParameters, ty, functionBody) = makeTerm loc $ Type.Annotation (makeTerm loc $ Declaration.Function [] functionName' functionParameters functionBody) (fromMaybe (makeTerm loc Syntax.Empty) ty)
|
||||||
|
makeAsyncFunctionDeclaration loc (async', functionName', functionParameters, ty, functionBody) = makeTerm loc $ Type.Annotation (makeTerm loc $ Type.Annotation (makeTerm loc $ Declaration.Function [] functionName' functionParameters functionBody) (maybe (makeTerm loc Syntax.Empty) id ty)) async'
|
||||||
|
|
||||||
|
async' :: Assignment
|
||||||
|
async' = makeTerm <$> symbol AnonAsync <*> (Syntax.Identifier <$> source)
|
||||||
|
|
||||||
|
classDefinition :: Assignment
|
||||||
|
classDefinition = makeTerm <$> symbol ClassDefinition <*> children (Declaration.Class <$> pure [] <*> expression <*> argumentList <*> many expression)
|
||||||
|
where argumentList = symbol ArgumentList *> children (many expression)
|
||||||
|
<|> pure []
|
||||||
|
|
||||||
|
type' :: Assignment
|
||||||
|
type' = symbol Type *> children expression
|
||||||
|
|
||||||
|
finallyClause :: Assignment
|
||||||
|
finallyClause = makeTerm <$> symbol FinallyClause <*> children (Statement.Finally <$> expressions)
|
||||||
|
|
||||||
|
dottedName :: Assignment
|
||||||
|
dottedName = makeTerm <$> symbol DottedName <*> children (Expression.ScopeResolution <$> many expression)
|
||||||
|
|
||||||
|
ellipsis :: Assignment
|
||||||
|
ellipsis = makeTerm <$> token Grammar.Ellipsis <*> pure Python.Syntax.Ellipsis
|
||||||
|
|
||||||
|
comparisonOperator :: Assignment
|
||||||
|
comparisonOperator = symbol ComparisonOperator *> children (expression `chainl1Term` choice
|
||||||
|
[ (makeTerm1 .) . Expression.LessThan <$ symbol AnonLAngle
|
||||||
|
, (makeTerm1 .) . Expression.LessThanEqual <$ symbol AnonLAngleEqual
|
||||||
|
, (makeTerm1 .) . Expression.GreaterThan <$ symbol AnonRAngle
|
||||||
|
, (makeTerm1 .) . Expression.GreaterThanEqual <$ symbol AnonRAngleEqual
|
||||||
|
, (makeTerm1 .) . Expression.Equal <$ symbol AnonEqualEqual
|
||||||
|
, (makeTerm1 .) . invert Expression.Equal <$ symbol AnonBangEqual
|
||||||
|
, (makeTerm1 .) . invert Expression.Equal <$ symbol AnonLAngleRAngle
|
||||||
|
, (makeTerm1 .) . invert Expression.Member <$ symbol AnonNot
|
||||||
|
, (makeTerm1 .) . Expression.Member <$ symbol AnonIn
|
||||||
|
, token AnonIs *> ((makeTerm1 .) . invert Expression.Equal <$ symbol AnonNot <|> pure ((makeTerm1 .) . Expression.Equal))
|
||||||
|
])
|
||||||
|
where invert cons a b = Expression.Not (makeTerm1 (cons a b))
|
||||||
|
|
||||||
|
notOperator :: Assignment
|
||||||
|
notOperator = makeTerm <$> symbol NotOperator <*> children (Expression.Not <$> expression)
|
||||||
|
|
||||||
|
tuple :: Assignment
|
||||||
|
tuple = makeTerm <$> symbol Tuple <*> children (Literal.Tuple <$> many expression)
|
||||||
|
|
||||||
|
unaryOperator :: Assignment
|
||||||
|
unaryOperator = symbol UnaryOperator >>= \ location -> arithmetic location <|> bitwise location <|> children ( symbol AnonPlus *> expression )
|
||||||
|
where
|
||||||
|
arithmetic location = makeTerm location . Expression.Negate <$> children ( symbol AnonMinus *> expression )
|
||||||
|
bitwise location = makeTerm location . Expression.Complement <$> children ( symbol AnonTilde *> expression )
|
||||||
|
|
||||||
|
binaryOperator :: Assignment
|
||||||
|
binaryOperator = makeTerm' <$> symbol BinaryOperator <*> children (infixTerm expression expression
|
||||||
|
[ (inj .) . Expression.Plus <$ symbol AnonPlus
|
||||||
|
, (inj .) . Expression.Minus <$ symbol AnonMinus
|
||||||
|
, (inj .) . Expression.Times <$ symbol AnonStar
|
||||||
|
, (inj .) . Expression.DividedBy <$ symbol AnonSlash
|
||||||
|
, (inj .) . Expression.DividedBy <$ symbol AnonSlashSlash
|
||||||
|
, (inj .) . Expression.Modulo <$ symbol AnonPercent
|
||||||
|
, (inj .) . Expression.Power <$ symbol AnonStarStar
|
||||||
|
, (inj .) . Expression.BOr <$ symbol AnonPipe
|
||||||
|
, (inj .) . Expression.BAnd <$ symbol AnonAmpersand
|
||||||
|
, (inj .) . Expression.BXOr <$ symbol AnonCaret
|
||||||
|
, (inj .) . Expression.LShift <$ symbol AnonLAngleLAngle
|
||||||
|
, (inj .) . Expression.RShift <$ symbol AnonRAngleRAngle
|
||||||
|
])
|
||||||
|
|
||||||
|
booleanOperator :: Assignment
|
||||||
|
booleanOperator = makeTerm' <$> symbol BooleanOperator <*> children (infixTerm expression expression
|
||||||
|
[ (inj .) . Expression.And <$ symbol AnonAnd
|
||||||
|
, (inj .) . Expression.Or <$ symbol AnonOr
|
||||||
|
])
|
||||||
|
|
||||||
|
assignment' :: Assignment
|
||||||
|
assignment' = makeTerm <$> symbol Assignment <*> children (Statement.Assignment [] <$> expressionList <*> rvalue)
|
||||||
|
<|> makeTerm' <$> symbol AugmentedAssignment <*> children (infixTerm expressionList rvalue
|
||||||
|
[ assign Expression.Plus <$ symbol AnonPlusEqual
|
||||||
|
, assign Expression.Minus <$ symbol AnonMinusEqual
|
||||||
|
, assign Expression.Times <$ symbol AnonStarEqual
|
||||||
|
, assign Expression.Power <$ symbol AnonStarStarEqual
|
||||||
|
, assign Expression.DividedBy <$ symbol AnonSlashEqual
|
||||||
|
, assign Expression.DividedBy <$ symbol AnonSlashSlashEqual
|
||||||
|
, assign Expression.BOr <$ symbol AnonPipeEqual
|
||||||
|
, assign Expression.BAnd <$ symbol AnonAmpersandEqual
|
||||||
|
, assign Expression.Modulo <$ symbol AnonPercentEqual
|
||||||
|
, assign Expression.RShift <$ symbol AnonRAngleRAngleEqual
|
||||||
|
, assign Expression.LShift <$ symbol AnonLAngleLAngleEqual
|
||||||
|
, assign Expression.BXOr <$ symbol AnonCaretEqual
|
||||||
|
])
|
||||||
|
where rvalue = expressionList <|> assignment' <|> yield
|
||||||
|
assign :: f :< Syntax => (Term -> Term -> f Term) -> Term -> Term -> Union Syntax Term
|
||||||
|
assign c l r = inj (Statement.Assignment [] l (makeTerm1 (c l r)))
|
||||||
|
|
||||||
|
yield :: Assignment
|
||||||
|
yield = makeTerm <$> symbol Yield <*> (Statement.Yield <$> children ( expression <|> emptyTerm ))
|
||||||
|
|
||||||
|
identifier :: Assignment
|
||||||
|
identifier = makeTerm <$> (symbol Identifier <|> symbol Identifier') <*> (Syntax.Identifier <$> source)
|
||||||
|
|
||||||
|
set :: Assignment
|
||||||
|
set = makeTerm <$> symbol Set <*> children (Literal.Set <$> many expression)
|
||||||
|
|
||||||
|
dictionary :: Assignment
|
||||||
|
dictionary = makeTerm <$> symbol Dictionary <*> children (Literal.Hash <$> many expression)
|
||||||
|
|
||||||
|
pair :: Assignment
|
||||||
|
pair = makeTerm' <$> symbol Pair <*> children (infixTerm expression expression [ (inj .) . Literal.KeyValue <$ symbol AnonColon ])
|
||||||
|
|
||||||
|
list' :: Assignment
|
||||||
|
list' = makeTerm <$> symbol List <*> children (Literal.Array <$> many expression)
|
||||||
|
|
||||||
|
string :: Assignment
|
||||||
|
string = makeTerm <$> symbol String <*> (Literal.TextElement <$> source)
|
||||||
|
|
||||||
|
concatenatedString :: Assignment
|
||||||
|
concatenatedString = makeTerm <$> symbol ConcatenatedString <*> children (many (term (makeTerm <$> symbol String <*> (Literal.TextElement <$> source))))
|
||||||
|
|
||||||
|
float :: Assignment
|
||||||
|
float = makeTerm <$> symbol Float <*> (Literal.Float <$> source)
|
||||||
|
|
||||||
|
integer :: Assignment
|
||||||
|
integer = makeTerm <$> symbol Integer <*> (Literal.Integer <$> source)
|
||||||
|
|
||||||
|
comment :: Assignment
|
||||||
|
comment = makeTerm <$> symbol Comment <*> (Comment.Comment <$> source)
|
||||||
|
|
||||||
|
import' :: Assignment
|
||||||
|
import' = makeTerm <$> symbol ImportStatement <*> children (Declaration.Import <$> many expression)
|
||||||
|
<|> makeTerm <$> symbol ImportFromStatement <*> children (Declaration.Import <$> many expression)
|
||||||
|
<|> makeTerm <$> symbol AliasedImport <*> children (flip Statement.Let <$> expression <*> expression <*> emptyTerm)
|
||||||
|
<|> makeTerm <$> symbol WildcardImport <*> (Syntax.Identifier <$> source)
|
||||||
|
|
||||||
|
assertStatement :: Assignment
|
||||||
|
assertStatement = makeTerm <$> symbol AssertStatement <*> children (Expression.Call <$> pure [] <*> (makeTerm <$> symbol AnonAssert <*> (Syntax.Identifier <$> source)) <*> many expression <*> emptyTerm)
|
||||||
|
|
||||||
|
printStatement :: Assignment
|
||||||
|
printStatement = do
|
||||||
|
location <- symbol PrintStatement
|
||||||
|
children $ do
|
||||||
|
print <- printKeyword
|
||||||
|
redirectCallTerm location print <|> printCallTerm location print
|
||||||
|
where
|
||||||
|
printKeyword = makeTerm <$> symbol AnonPrint <*> (Syntax.Identifier <$> source)
|
||||||
|
redirectCallTerm location identifier = makeTerm location <$ symbol Chevron <*> (flip Python.Syntax.Redirect <$> children expression <*> printCallTerm location identifier)
|
||||||
|
printCallTerm location identifier = makeTerm location <$> (Expression.Call [] identifier <$> many expression <*> emptyTerm)
|
||||||
|
|
||||||
|
nonlocalStatement :: Assignment
|
||||||
|
nonlocalStatement = makeTerm <$> symbol NonlocalStatement <*> children (Expression.Call <$> pure [] <*> (makeTerm <$> symbol AnonNonlocal <*> (Syntax.Identifier <$> source)) <*> many expression <*> emptyTerm)
|
||||||
|
|
||||||
|
globalStatement :: Assignment
|
||||||
|
globalStatement = makeTerm <$> symbol GlobalStatement <*> children (Expression.Call <$> pure [] <*> (makeTerm <$> symbol AnonGlobal <*> (Syntax.Identifier <$> source)) <*> many expression <*> emptyTerm)
|
||||||
|
|
||||||
|
await :: Assignment
|
||||||
|
await = makeTerm <$> symbol Await <*> children (Expression.Call <$> pure [] <*> (makeTerm <$> symbol AnonAwait <*> (Syntax.Identifier <$> source)) <*> many expression <*> emptyTerm)
|
||||||
|
|
||||||
|
returnStatement :: Assignment
|
||||||
|
returnStatement = makeTerm <$> symbol ReturnStatement <*> children (Statement.Return <$> (expressionList <|> emptyTerm))
|
||||||
|
|
||||||
|
deleteStatement :: Assignment
|
||||||
|
deleteStatement = makeTerm <$> symbol DeleteStatement <*> children (Expression.Call <$> pure [] <*> deleteIdentifier <* symbol ExpressionList <*> children (many expression) <*> emptyTerm)
|
||||||
|
where deleteIdentifier = makeTerm <$> symbol AnonDel <*> (Syntax.Identifier <$> source)
|
||||||
|
|
||||||
|
raiseStatement :: Assignment
|
||||||
|
raiseStatement = makeTerm <$> symbol RaiseStatement <*> children (Statement.Throw <$> expressions)
|
||||||
|
|
||||||
|
ifStatement :: Assignment
|
||||||
|
ifStatement = makeTerm <$> symbol IfStatement <*> children (Statement.If <$> expression <*> (makeTerm <$> location <*> manyTermsTill expression (void (symbol ElseClause) <|> void (symbol ElifClause) <|> eof)) <*> (flip (foldr makeElif) <$> many elifClause <*> (symbol ElseClause *> children expressions <|> emptyTerm)))
|
||||||
|
where elifClause = (,) <$> symbol ElifClause <*> children (Statement.If <$> expression <*> expressions)
|
||||||
|
makeElif (loc, makeIf) rest = makeTerm loc (makeIf rest)
|
||||||
|
|
||||||
|
execStatement :: Assignment
|
||||||
|
execStatement = makeTerm <$> symbol ExecStatement <*> children (Expression.Call <$> pure [] <*> (makeTerm <$> location <*> (Syntax.Identifier <$> source)) <*> many (string <|> expression) <*> emptyTerm)
|
||||||
|
|
||||||
|
passStatement :: Assignment
|
||||||
|
passStatement = makeTerm <$> symbol PassStatement <*> (Statement.NoOp <$> emptyTerm <* advance)
|
||||||
|
|
||||||
|
breakStatement :: Assignment
|
||||||
|
breakStatement = makeTerm <$> symbol BreakStatement <*> (Statement.Break <$> emptyTerm <* advance)
|
||||||
|
|
||||||
|
continueStatement :: Assignment
|
||||||
|
continueStatement = makeTerm <$> symbol ContinueStatement <*> (Statement.Continue <$> emptyTerm <* advance)
|
||||||
|
|
||||||
|
memberAccess :: Assignment
|
||||||
|
memberAccess = makeTerm <$> symbol Attribute <*> children (Expression.MemberAccess <$> expression <*> expression)
|
||||||
|
|
||||||
|
subscript :: Assignment
|
||||||
|
subscript = makeTerm <$> symbol Subscript <*> children (Expression.Subscript <$> expression <*> many expression)
|
||||||
|
|
||||||
|
slice :: Assignment
|
||||||
|
slice = makeTerm <$> symbol Slice <*> children
|
||||||
|
(Expression.Enumeration <$> ((emptyTerm <* token AnonColon) <|> (expression <* token AnonColon))
|
||||||
|
<*> ((emptyTerm <* token AnonColon) <|> (expression <* token AnonColon) <|> (expression <|> emptyTerm))
|
||||||
|
<*> (expression <|> emptyTerm))
|
||||||
|
|
||||||
|
call :: Assignment
|
||||||
|
call = makeTerm <$> symbol Call <*> children (Expression.Call <$> pure [] <*> expression <*> (symbol ArgumentList *> children (many expression)
|
||||||
|
<|> some comprehension) <*> emptyTerm)
|
||||||
|
|
||||||
|
boolean :: Assignment
|
||||||
|
boolean = makeTerm <$> token Grammar.True <*> pure Literal.true
|
||||||
|
<|> makeTerm <$> token Grammar.False <*> pure Literal.false
|
||||||
|
|
||||||
|
none :: Assignment
|
||||||
|
none = makeTerm <$> symbol None <*> (Literal.Null <$ source)
|
||||||
|
|
||||||
|
comprehension :: Assignment
|
||||||
|
comprehension = makeTerm <$> symbol ListComprehension <*> children (Declaration.Comprehension <$> expression <*> expressions)
|
||||||
|
<|> makeTerm <$> symbol GeneratorExpression <*> children (Declaration.Comprehension <$> expression <*> expressions)
|
||||||
|
<|> makeTerm <$> symbol SetComprehension <*> children (Declaration.Comprehension <$> expression <*> expressions)
|
||||||
|
<|> makeTerm <$> symbol DictionaryComprehension <*> children (Declaration.Comprehension <$> expression <*> expressions)
|
||||||
|
|
||||||
|
forInClause :: Assignment
|
||||||
|
forInClause = symbol ForInClause *> children expressions
|
||||||
|
|
||||||
|
variables :: Assignment
|
||||||
|
variables = symbol Variables *> children expressions
|
||||||
|
|
||||||
|
ifClause :: Assignment
|
||||||
|
ifClause = symbol IfClause *> children expressions
|
||||||
|
|
||||||
|
conditionalExpression :: Assignment
|
||||||
|
conditionalExpression = makeTerm <$> symbol ConditionalExpression <*> children (flip Statement.If <$> expression <*> expression <*> expressions)
|
||||||
|
|
||||||
|
-- | Match a term optionally preceded by comment(s), or a sequence of comments if the term is not present.
|
||||||
|
term :: Assignment -> Assignment
|
||||||
|
term term = contextualize comment term <|> makeTerm1 <$> (Syntax.Context <$> some1 comment <*> emptyTerm)
|
||||||
|
|
||||||
|
-- | Match a left-associated infix chain of terms, optionally followed by comments. Like 'chainl1' but assigning comment nodes automatically.
|
||||||
|
chainl1Term :: Assignment -> Assignment.Assignment [] Grammar (Term -> Term -> Term) -> Assignment
|
||||||
|
chainl1Term expr op = postContextualize (comment <|> symbol AnonLambda *> empty) expr `chainl1` op
|
||||||
|
|
||||||
|
-- | Match a series of terms or comments until a delimiter is matched.
|
||||||
|
manyTermsTill :: Show b => Assignment.Assignment [] Grammar Term -> Assignment.Assignment [] Grammar b -> Assignment.Assignment [] Grammar [Term]
|
||||||
|
manyTermsTill step end = manyTill (step <|> comment) end
|
||||||
|
|
||||||
|
-- | Match infix terms separated by any of a list of operators, assigning any comments following each operand.
|
||||||
|
infixTerm :: HasCallStack
|
||||||
|
=> Assignment
|
||||||
|
-> Assignment
|
||||||
|
-> [Assignment.Assignment [] Grammar (Term -> Term -> Union Syntax Term)]
|
||||||
|
-> Assignment.Assignment [] Grammar (Union Syntax Term)
|
||||||
|
infixTerm = infixContext comment
|
@ -1,93 +1,13 @@
|
|||||||
{-# LANGUAGE DataKinds, DeriveAnyClass, RankNTypes, TypeOperators #-}
|
{-# LANGUAGE DeriveAnyClass #-}
|
||||||
module Language.Python.Syntax
|
module Language.Python.Syntax where
|
||||||
( assignment
|
|
||||||
, Syntax
|
|
||||||
, Grammar
|
|
||||||
, Term
|
|
||||||
) where
|
|
||||||
|
|
||||||
import Algorithm
|
import Algorithm
|
||||||
import Data.Align.Generic
|
import Data.Align.Generic
|
||||||
import Data.Functor (void)
|
|
||||||
import Data.Functor.Classes.Eq.Generic
|
import Data.Functor.Classes.Eq.Generic
|
||||||
import Data.Functor.Classes.Ord.Generic
|
import Data.Functor.Classes.Ord.Generic
|
||||||
import Data.Functor.Classes.Show.Generic
|
import Data.Functor.Classes.Show.Generic
|
||||||
import Data.List.NonEmpty (some1)
|
|
||||||
import Data.Maybe (fromMaybe)
|
|
||||||
import Data.Mergeable
|
import Data.Mergeable
|
||||||
import Data.Record
|
|
||||||
import Data.Syntax (contextualize, emptyTerm, handleError, infixContext, makeTerm, makeTerm', makeTerm1, parseError, postContextualize)
|
|
||||||
import qualified Data.Syntax as Syntax
|
|
||||||
import Data.Syntax.Assignment hiding (Assignment, Error)
|
|
||||||
import qualified Data.Syntax.Assignment as Assignment
|
|
||||||
import qualified Data.Syntax.Comment as Comment
|
|
||||||
import qualified Data.Syntax.Declaration as Declaration
|
|
||||||
import qualified Data.Syntax.Expression as Expression
|
|
||||||
import qualified Data.Syntax.Literal as Literal
|
|
||||||
import qualified Data.Syntax.Statement as Statement
|
|
||||||
import qualified Data.Syntax.Type as Type
|
|
||||||
import qualified Data.Term as Term
|
|
||||||
import Data.Union
|
|
||||||
import GHC.Generics
|
import GHC.Generics
|
||||||
import GHC.Stack
|
|
||||||
import Language.Python.Grammar as Grammar
|
|
||||||
|
|
||||||
type Syntax =
|
|
||||||
'[ Comment.Comment
|
|
||||||
, Declaration.Class
|
|
||||||
, Declaration.Comprehension
|
|
||||||
, Declaration.Decorator
|
|
||||||
, Declaration.Function
|
|
||||||
, Declaration.Import
|
|
||||||
, Declaration.Variable
|
|
||||||
, Expression.Arithmetic
|
|
||||||
, Expression.Boolean
|
|
||||||
, Expression.Bitwise
|
|
||||||
, Expression.Call
|
|
||||||
, Expression.Comparison
|
|
||||||
, Expression.Enumeration
|
|
||||||
, Expression.ScopeResolution
|
|
||||||
, Expression.MemberAccess
|
|
||||||
, Expression.Subscript
|
|
||||||
, Literal.Array
|
|
||||||
, Literal.Boolean
|
|
||||||
, Literal.Float
|
|
||||||
, Literal.Hash
|
|
||||||
, Literal.Integer
|
|
||||||
, Literal.KeyValue
|
|
||||||
, Literal.Null
|
|
||||||
, Literal.Set
|
|
||||||
, Literal.String
|
|
||||||
, Literal.TextElement
|
|
||||||
, Literal.Tuple
|
|
||||||
, Redirect
|
|
||||||
, Statement.Assignment
|
|
||||||
, Statement.Break
|
|
||||||
, Statement.Catch
|
|
||||||
, Statement.Continue
|
|
||||||
, Statement.Else
|
|
||||||
, Statement.Finally
|
|
||||||
, Statement.ForEach
|
|
||||||
, Statement.If
|
|
||||||
, Statement.Let
|
|
||||||
, Statement.NoOp
|
|
||||||
, Statement.Return
|
|
||||||
, Statement.Throw
|
|
||||||
, Statement.Try
|
|
||||||
, Statement.While
|
|
||||||
, Statement.Yield
|
|
||||||
, Language.Python.Syntax.Ellipsis
|
|
||||||
, Syntax.Context
|
|
||||||
, Syntax.Empty
|
|
||||||
, Syntax.Error
|
|
||||||
, Syntax.Identifier
|
|
||||||
, Syntax.Program
|
|
||||||
, Type.Annotation
|
|
||||||
, []
|
|
||||||
]
|
|
||||||
|
|
||||||
type Term = Term.Term (Union Syntax) (Record Location)
|
|
||||||
type Assignment = HasCallStack => Assignment.Assignment [] Grammar Term
|
|
||||||
|
|
||||||
-- | Ellipsis (used in splice expressions and alternatively can be used as a fill in expression, like `undefined` in Haskell)
|
-- | Ellipsis (used in splice expressions and alternatively can be used as a fill in expression, like `undefined` in Haskell)
|
||||||
data Ellipsis a = Ellipsis
|
data Ellipsis a = Ellipsis
|
||||||
@ -104,400 +24,3 @@ data Redirect a = Redirect !a !a
|
|||||||
instance Eq1 Redirect where liftEq = genericLiftEq
|
instance Eq1 Redirect where liftEq = genericLiftEq
|
||||||
instance Ord1 Redirect where liftCompare = genericLiftCompare
|
instance Ord1 Redirect where liftCompare = genericLiftCompare
|
||||||
instance Show1 Redirect where liftShowsPrec = genericLiftShowsPrec
|
instance Show1 Redirect where liftShowsPrec = genericLiftShowsPrec
|
||||||
|
|
||||||
-- | Assignment from AST in Python's grammar onto a program in Python's syntax.
|
|
||||||
assignment :: Assignment
|
|
||||||
assignment = handleError $ makeTerm <$> symbol Module <*> children (Syntax.Program <$> many expression) <|> parseError
|
|
||||||
|
|
||||||
expression :: Assignment
|
|
||||||
expression = term (handleError (choice expressionChoices))
|
|
||||||
|
|
||||||
expressionChoices :: [Assignment.Assignment [] Grammar Term]
|
|
||||||
expressionChoices =
|
|
||||||
-- Long-term, can we de/serialize assignments and avoid paying the cost of construction altogether?
|
|
||||||
[ argumentList
|
|
||||||
, assertStatement
|
|
||||||
, assignment'
|
|
||||||
, await
|
|
||||||
, binaryOperator
|
|
||||||
, boolean
|
|
||||||
, booleanOperator
|
|
||||||
, breakStatement
|
|
||||||
, call
|
|
||||||
, classDefinition
|
|
||||||
, comparisonOperator
|
|
||||||
, comprehension
|
|
||||||
, concatenatedString
|
|
||||||
, conditionalExpression
|
|
||||||
, continueStatement
|
|
||||||
, decoratedDefinition
|
|
||||||
, deleteStatement
|
|
||||||
, dictionary
|
|
||||||
, dictionarySplat
|
|
||||||
, dottedName
|
|
||||||
, ellipsis
|
|
||||||
, exceptClause
|
|
||||||
, execStatement
|
|
||||||
, expressionList
|
|
||||||
, expressionStatement
|
|
||||||
, finallyClause
|
|
||||||
, float
|
|
||||||
, forInClause
|
|
||||||
, forStatement
|
|
||||||
, functionDefinition
|
|
||||||
, globalStatement
|
|
||||||
, identifier
|
|
||||||
, ifClause
|
|
||||||
, ifStatement
|
|
||||||
, import'
|
|
||||||
, integer
|
|
||||||
, keywordArgument
|
|
||||||
, list'
|
|
||||||
, listSplat
|
|
||||||
, memberAccess
|
|
||||||
, none
|
|
||||||
, nonlocalStatement
|
|
||||||
, notOperator
|
|
||||||
, pair
|
|
||||||
, parameter
|
|
||||||
, parenthesizedExpression
|
|
||||||
, parseError
|
|
||||||
, passStatement
|
|
||||||
, printStatement
|
|
||||||
, raiseStatement
|
|
||||||
, returnStatement
|
|
||||||
, set
|
|
||||||
, slice
|
|
||||||
, string
|
|
||||||
, subscript
|
|
||||||
, tryStatement
|
|
||||||
, tuple
|
|
||||||
, type'
|
|
||||||
, unaryOperator
|
|
||||||
, variables
|
|
||||||
, whileStatement
|
|
||||||
, withStatement
|
|
||||||
, yield
|
|
||||||
]
|
|
||||||
|
|
||||||
expressions :: Assignment
|
|
||||||
expressions = makeTerm <$> location <*> many expression
|
|
||||||
|
|
||||||
expressionStatement :: Assignment
|
|
||||||
expressionStatement = mk <$> symbol ExpressionStatement <*> children (some expression)
|
|
||||||
where mk _ [child] = child
|
|
||||||
mk location children = makeTerm location children
|
|
||||||
|
|
||||||
expressionList :: Assignment
|
|
||||||
expressionList = mk <$> symbol ExpressionList <*> children (some expression)
|
|
||||||
where mk _ [child] = child
|
|
||||||
mk location children = makeTerm location children
|
|
||||||
|
|
||||||
listSplat :: Assignment
|
|
||||||
listSplat = makeTerm <$> symbol ListSplat <*> (Syntax.Identifier <$> source)
|
|
||||||
|
|
||||||
dictionarySplat :: Assignment
|
|
||||||
dictionarySplat = makeTerm <$> symbol DictionarySplat <*> (Syntax.Identifier <$> source)
|
|
||||||
|
|
||||||
keywordArgument :: Assignment
|
|
||||||
keywordArgument = makeTerm <$> symbol KeywordArgument <*> children (Statement.Assignment [] <$> expression <*> expression)
|
|
||||||
|
|
||||||
parenthesizedExpression :: Assignment
|
|
||||||
parenthesizedExpression = symbol ParenthesizedExpression *> children expressions
|
|
||||||
|
|
||||||
parameter :: Assignment
|
|
||||||
parameter = makeTerm <$> symbol DefaultParameter <*> children (Statement.Assignment [] <$> expression <*> expression)
|
|
||||||
<|> makeTerm <$> symbol TypedParameter <*> children (Type.Annotation <$> expression <*> type')
|
|
||||||
<|> makeAnnotation <$> symbol TypedDefaultParameter <*> children ((,,) <$> expression <*> expression <*> expression)
|
|
||||||
where
|
|
||||||
makeAnnotation loc (identifier', type', value') = makeTerm loc (Type.Annotation (makeAssignment loc identifier' value') type')
|
|
||||||
makeAssignment loc identifier' value' = makeTerm loc (Statement.Assignment [] identifier' value')
|
|
||||||
|
|
||||||
decoratedDefinition :: Assignment
|
|
||||||
decoratedDefinition = symbol DecoratedDefinition *> children (term decorator)
|
|
||||||
where
|
|
||||||
decorator = makeTerm <$> symbol Decorator <*> (children (Declaration.Decorator <$> expression <*> many expression) <*> term (decorator <|> functionDefinition <|> classDefinition))
|
|
||||||
|
|
||||||
argumentList :: Assignment
|
|
||||||
argumentList = symbol ArgumentList *> children expressions
|
|
||||||
|
|
||||||
withStatement :: Assignment
|
|
||||||
withStatement = mk <$> symbol WithStatement <*> children (some with)
|
|
||||||
where
|
|
||||||
mk _ [child] = child
|
|
||||||
mk l children = makeTerm l children
|
|
||||||
with = makeTerm <$> location <*> (withItem <*> (makeTerm <$> location <*> manyTermsTill expression (void (symbol WithItem) <|> eof)))
|
|
||||||
withItem = symbol WithItem *> children (flip Statement.Let <$> expression <*> (expression <|> emptyTerm))
|
|
||||||
<|> flip Statement.Let <$> expression <*> emptyTerm
|
|
||||||
|
|
||||||
forStatement :: Assignment
|
|
||||||
forStatement = symbol ForStatement >>= \ loc -> children (make loc <$> (symbol Variables *> children expressions) <*> expressionList <*> (makeTerm <$> location <*> manyTermsTill expression (void (symbol ElseClause) <|> eof)) <*> optional (symbol ElseClause *> children expressions))
|
|
||||||
where
|
|
||||||
make loc binding subject body forElseClause = case forElseClause of
|
|
||||||
Nothing -> makeTerm loc (Statement.ForEach binding subject body)
|
|
||||||
Just a -> makeTerm loc (Statement.Else (makeTerm loc $ Statement.ForEach binding subject body) a)
|
|
||||||
|
|
||||||
whileStatement :: Assignment
|
|
||||||
whileStatement = symbol WhileStatement >>= \ loc -> children (make loc <$> expression <*> (makeTerm <$> location <*> manyTermsTill expression (void (symbol ElseClause) <|> eof)) <*> optional (symbol ElseClause *> children expressions))
|
|
||||||
where
|
|
||||||
make loc whileCondition whileBody whileElseClause = case whileElseClause of
|
|
||||||
Nothing -> makeTerm loc (Statement.While whileCondition whileBody)
|
|
||||||
Just a -> makeTerm loc (Statement.Else (makeTerm loc $ Statement.While whileCondition whileBody) a)
|
|
||||||
|
|
||||||
tryStatement :: Assignment
|
|
||||||
tryStatement = makeTerm <$> symbol TryStatement <*> children (Statement.Try <$> expression <*> many (expression <|> elseClause))
|
|
||||||
where elseClause = makeTerm <$> symbol ElseClause <*> children (Statement.Else <$> emptyTerm <*> expressions)
|
|
||||||
|
|
||||||
exceptClause :: Assignment
|
|
||||||
exceptClause = makeTerm <$> symbol ExceptClause <*> children
|
|
||||||
(Statement.Catch <$> ((makeTerm <$> location <*> (uncurry (flip Statement.Let) <$> ((,) <$> expression <* symbol AnonAs <*> expression) <*> emptyTerm))
|
|
||||||
<|> expressions)
|
|
||||||
<*> expressions)
|
|
||||||
|
|
||||||
functionDefinition :: Assignment
|
|
||||||
functionDefinition
|
|
||||||
= makeFunctionDeclaration <$> symbol FunctionDefinition <*> children ((,,,) <$> expression <* symbol Parameters <*> children (many expression) <*> optional (symbol Type *> children expression) <*> expressions)
|
|
||||||
<|> makeAsyncFunctionDeclaration <$> symbol AsyncFunctionDefinition <*> children ((,,,,) <$> async' <*> expression <* symbol Parameters <*> children (many expression) <*> optional (symbol Type *> children expression) <*> expressions)
|
|
||||||
<|> makeFunctionDeclaration <$> (symbol Lambda' <|> symbol Lambda) <*> children ((,,,) <$ token AnonLambda <*> emptyTerm <*> (symbol LambdaParameters *> children (many expression) <|> pure []) <*> optional (symbol Type *> children expression) <*> expressions)
|
|
||||||
where
|
|
||||||
makeFunctionDeclaration loc (functionName', functionParameters, ty, functionBody) = makeTerm loc $ Type.Annotation (makeTerm loc $ Declaration.Function [] functionName' functionParameters functionBody) (fromMaybe (makeTerm loc Syntax.Empty) ty)
|
|
||||||
makeAsyncFunctionDeclaration loc (async', functionName', functionParameters, ty, functionBody) = makeTerm loc $ Type.Annotation (makeTerm loc $ Type.Annotation (makeTerm loc $ Declaration.Function [] functionName' functionParameters functionBody) (maybe (makeTerm loc Syntax.Empty) id ty)) async'
|
|
||||||
|
|
||||||
async' :: Assignment
|
|
||||||
async' = makeTerm <$> symbol AnonAsync <*> (Syntax.Identifier <$> source)
|
|
||||||
|
|
||||||
classDefinition :: Assignment
|
|
||||||
classDefinition = makeTerm <$> symbol ClassDefinition <*> children (Declaration.Class <$> pure [] <*> expression <*> argumentList <*> many expression)
|
|
||||||
where argumentList = symbol ArgumentList *> children (many expression)
|
|
||||||
<|> pure []
|
|
||||||
|
|
||||||
type' :: Assignment
|
|
||||||
type' = symbol Type *> children expression
|
|
||||||
|
|
||||||
finallyClause :: Assignment
|
|
||||||
finallyClause = makeTerm <$> symbol FinallyClause <*> children (Statement.Finally <$> expressions)
|
|
||||||
|
|
||||||
dottedName :: Assignment
|
|
||||||
dottedName = makeTerm <$> symbol DottedName <*> children (Expression.ScopeResolution <$> many expression)
|
|
||||||
|
|
||||||
ellipsis :: Assignment
|
|
||||||
ellipsis = makeTerm <$> token Grammar.Ellipsis <*> pure Language.Python.Syntax.Ellipsis
|
|
||||||
|
|
||||||
comparisonOperator :: Assignment
|
|
||||||
comparisonOperator = symbol ComparisonOperator *> children (expression `chainl1Term` choice
|
|
||||||
[ (makeTerm1 .) . Expression.LessThan <$ symbol AnonLAngle
|
|
||||||
, (makeTerm1 .) . Expression.LessThanEqual <$ symbol AnonLAngleEqual
|
|
||||||
, (makeTerm1 .) . Expression.GreaterThan <$ symbol AnonRAngle
|
|
||||||
, (makeTerm1 .) . Expression.GreaterThanEqual <$ symbol AnonRAngleEqual
|
|
||||||
, (makeTerm1 .) . Expression.Equal <$ symbol AnonEqualEqual
|
|
||||||
, (makeTerm1 .) . invert Expression.Equal <$ symbol AnonBangEqual
|
|
||||||
, (makeTerm1 .) . invert Expression.Equal <$ symbol AnonLAngleRAngle
|
|
||||||
, (makeTerm1 .) . invert Expression.Member <$ symbol AnonNot
|
|
||||||
, (makeTerm1 .) . Expression.Member <$ symbol AnonIn
|
|
||||||
, token AnonIs *> ((makeTerm1 .) . invert Expression.Equal <$ symbol AnonNot <|> pure ((makeTerm1 .) . Expression.Equal))
|
|
||||||
])
|
|
||||||
where invert cons a b = Expression.Not (makeTerm1 (cons a b))
|
|
||||||
|
|
||||||
notOperator :: Assignment
|
|
||||||
notOperator = makeTerm <$> symbol NotOperator <*> children (Expression.Not <$> expression)
|
|
||||||
|
|
||||||
tuple :: Assignment
|
|
||||||
tuple = makeTerm <$> symbol Tuple <*> children (Literal.Tuple <$> many expression)
|
|
||||||
|
|
||||||
unaryOperator :: Assignment
|
|
||||||
unaryOperator = symbol UnaryOperator >>= \ location -> arithmetic location <|> bitwise location <|> children ( symbol AnonPlus *> expression )
|
|
||||||
where
|
|
||||||
arithmetic location = makeTerm location . Expression.Negate <$> children ( symbol AnonMinus *> expression )
|
|
||||||
bitwise location = makeTerm location . Expression.Complement <$> children ( symbol AnonTilde *> expression )
|
|
||||||
|
|
||||||
binaryOperator :: Assignment
|
|
||||||
binaryOperator = makeTerm' <$> symbol BinaryOperator <*> children (infixTerm expression expression
|
|
||||||
[ (inj .) . Expression.Plus <$ symbol AnonPlus
|
|
||||||
, (inj .) . Expression.Minus <$ symbol AnonMinus
|
|
||||||
, (inj .) . Expression.Times <$ symbol AnonStar
|
|
||||||
, (inj .) . Expression.DividedBy <$ symbol AnonSlash
|
|
||||||
, (inj .) . Expression.DividedBy <$ symbol AnonSlashSlash
|
|
||||||
, (inj .) . Expression.Modulo <$ symbol AnonPercent
|
|
||||||
, (inj .) . Expression.Power <$ symbol AnonStarStar
|
|
||||||
, (inj .) . Expression.BOr <$ symbol AnonPipe
|
|
||||||
, (inj .) . Expression.BAnd <$ symbol AnonAmpersand
|
|
||||||
, (inj .) . Expression.BXOr <$ symbol AnonCaret
|
|
||||||
, (inj .) . Expression.LShift <$ symbol AnonLAngleLAngle
|
|
||||||
, (inj .) . Expression.RShift <$ symbol AnonRAngleRAngle
|
|
||||||
])
|
|
||||||
|
|
||||||
booleanOperator :: Assignment
|
|
||||||
booleanOperator = makeTerm' <$> symbol BooleanOperator <*> children (infixTerm expression expression
|
|
||||||
[ (inj .) . Expression.And <$ symbol AnonAnd
|
|
||||||
, (inj .) . Expression.Or <$ symbol AnonOr
|
|
||||||
])
|
|
||||||
|
|
||||||
assignment' :: Assignment
|
|
||||||
assignment' = makeTerm <$> symbol Assignment <*> children (Statement.Assignment [] <$> expressionList <*> rvalue)
|
|
||||||
<|> makeTerm' <$> symbol AugmentedAssignment <*> children (infixTerm expressionList rvalue
|
|
||||||
[ assign Expression.Plus <$ symbol AnonPlusEqual
|
|
||||||
, assign Expression.Minus <$ symbol AnonMinusEqual
|
|
||||||
, assign Expression.Times <$ symbol AnonStarEqual
|
|
||||||
, assign Expression.Power <$ symbol AnonStarStarEqual
|
|
||||||
, assign Expression.DividedBy <$ symbol AnonSlashEqual
|
|
||||||
, assign Expression.DividedBy <$ symbol AnonSlashSlashEqual
|
|
||||||
, assign Expression.BOr <$ symbol AnonPipeEqual
|
|
||||||
, assign Expression.BAnd <$ symbol AnonAmpersandEqual
|
|
||||||
, assign Expression.Modulo <$ symbol AnonPercentEqual
|
|
||||||
, assign Expression.RShift <$ symbol AnonRAngleRAngleEqual
|
|
||||||
, assign Expression.LShift <$ symbol AnonLAngleLAngleEqual
|
|
||||||
, assign Expression.BXOr <$ symbol AnonCaretEqual
|
|
||||||
])
|
|
||||||
where rvalue = expressionList <|> assignment' <|> yield
|
|
||||||
assign :: f :< Syntax => (Term -> Term -> f Term) -> Term -> Term -> Union Syntax Term
|
|
||||||
assign c l r = inj (Statement.Assignment [] l (makeTerm1 (c l r)))
|
|
||||||
|
|
||||||
yield :: Assignment
|
|
||||||
yield = makeTerm <$> symbol Yield <*> (Statement.Yield <$> children ( expression <|> emptyTerm ))
|
|
||||||
|
|
||||||
identifier :: Assignment
|
|
||||||
identifier = makeTerm <$> (symbol Identifier <|> symbol Identifier') <*> (Syntax.Identifier <$> source)
|
|
||||||
|
|
||||||
set :: Assignment
|
|
||||||
set = makeTerm <$> symbol Set <*> children (Literal.Set <$> many expression)
|
|
||||||
|
|
||||||
dictionary :: Assignment
|
|
||||||
dictionary = makeTerm <$> symbol Dictionary <*> children (Literal.Hash <$> many expression)
|
|
||||||
|
|
||||||
pair :: Assignment
|
|
||||||
pair = makeTerm' <$> symbol Pair <*> children (infixTerm expression expression [ (inj .) . Literal.KeyValue <$ symbol AnonColon ])
|
|
||||||
|
|
||||||
list' :: Assignment
|
|
||||||
list' = makeTerm <$> symbol List <*> children (Literal.Array <$> many expression)
|
|
||||||
|
|
||||||
string :: Assignment
|
|
||||||
string = makeTerm <$> symbol String <*> (Literal.TextElement <$> source)
|
|
||||||
|
|
||||||
concatenatedString :: Assignment
|
|
||||||
concatenatedString = makeTerm <$> symbol ConcatenatedString <*> children (many (term (makeTerm <$> symbol String <*> (Literal.TextElement <$> source))))
|
|
||||||
|
|
||||||
float :: Assignment
|
|
||||||
float = makeTerm <$> symbol Float <*> (Literal.Float <$> source)
|
|
||||||
|
|
||||||
integer :: Assignment
|
|
||||||
integer = makeTerm <$> symbol Integer <*> (Literal.Integer <$> source)
|
|
||||||
|
|
||||||
comment :: Assignment
|
|
||||||
comment = makeTerm <$> symbol Comment <*> (Comment.Comment <$> source)
|
|
||||||
|
|
||||||
import' :: Assignment
|
|
||||||
import' = makeTerm <$> symbol ImportStatement <*> children (Declaration.Import <$> many expression)
|
|
||||||
<|> makeTerm <$> symbol ImportFromStatement <*> children (Declaration.Import <$> many expression)
|
|
||||||
<|> makeTerm <$> symbol AliasedImport <*> children (flip Statement.Let <$> expression <*> expression <*> emptyTerm)
|
|
||||||
<|> makeTerm <$> symbol WildcardImport <*> (Syntax.Identifier <$> source)
|
|
||||||
|
|
||||||
assertStatement :: Assignment
|
|
||||||
assertStatement = makeTerm <$> symbol AssertStatement <*> children (Expression.Call <$> pure [] <*> (makeTerm <$> symbol AnonAssert <*> (Syntax.Identifier <$> source)) <*> many expression <*> emptyTerm)
|
|
||||||
|
|
||||||
printStatement :: Assignment
|
|
||||||
printStatement = do
|
|
||||||
location <- symbol PrintStatement
|
|
||||||
children $ do
|
|
||||||
print <- printKeyword
|
|
||||||
redirectCallTerm location print <|> printCallTerm location print
|
|
||||||
where
|
|
||||||
printKeyword = makeTerm <$> symbol AnonPrint <*> (Syntax.Identifier <$> source)
|
|
||||||
redirectCallTerm location identifier = makeTerm location <$ symbol Chevron <*> (flip Redirect <$> children expression <*> printCallTerm location identifier)
|
|
||||||
printCallTerm location identifier = makeTerm location <$> (Expression.Call [] identifier <$> many expression <*> emptyTerm)
|
|
||||||
|
|
||||||
nonlocalStatement :: Assignment
|
|
||||||
nonlocalStatement = makeTerm <$> symbol NonlocalStatement <*> children (Expression.Call <$> pure [] <*> (makeTerm <$> symbol AnonNonlocal <*> (Syntax.Identifier <$> source)) <*> many expression <*> emptyTerm)
|
|
||||||
|
|
||||||
globalStatement :: Assignment
|
|
||||||
globalStatement = makeTerm <$> symbol GlobalStatement <*> children (Expression.Call <$> pure [] <*> (makeTerm <$> symbol AnonGlobal <*> (Syntax.Identifier <$> source)) <*> many expression <*> emptyTerm)
|
|
||||||
|
|
||||||
await :: Assignment
|
|
||||||
await = makeTerm <$> symbol Await <*> children (Expression.Call <$> pure [] <*> (makeTerm <$> symbol AnonAwait <*> (Syntax.Identifier <$> source)) <*> many expression <*> emptyTerm)
|
|
||||||
|
|
||||||
returnStatement :: Assignment
|
|
||||||
returnStatement = makeTerm <$> symbol ReturnStatement <*> children (Statement.Return <$> (expressionList <|> emptyTerm))
|
|
||||||
|
|
||||||
deleteStatement :: Assignment
|
|
||||||
deleteStatement = makeTerm <$> symbol DeleteStatement <*> children (Expression.Call <$> pure [] <*> deleteIdentifier <* symbol ExpressionList <*> children (many expression) <*> emptyTerm)
|
|
||||||
where deleteIdentifier = makeTerm <$> symbol AnonDel <*> (Syntax.Identifier <$> source)
|
|
||||||
|
|
||||||
raiseStatement :: Assignment
|
|
||||||
raiseStatement = makeTerm <$> symbol RaiseStatement <*> children (Statement.Throw <$> expressions)
|
|
||||||
|
|
||||||
ifStatement :: Assignment
|
|
||||||
ifStatement = makeTerm <$> symbol IfStatement <*> children (Statement.If <$> expression <*> (makeTerm <$> location <*> manyTermsTill expression (void (symbol ElseClause) <|> void (symbol ElifClause) <|> eof)) <*> (flip (foldr makeElif) <$> many elifClause <*> (symbol ElseClause *> children expressions <|> emptyTerm)))
|
|
||||||
where elifClause = (,) <$> symbol ElifClause <*> children (Statement.If <$> expression <*> expressions)
|
|
||||||
makeElif (loc, makeIf) rest = makeTerm loc (makeIf rest)
|
|
||||||
|
|
||||||
execStatement :: Assignment
|
|
||||||
execStatement = makeTerm <$> symbol ExecStatement <*> children (Expression.Call <$> pure [] <*> (makeTerm <$> location <*> (Syntax.Identifier <$> source)) <*> many (string <|> expression) <*> emptyTerm)
|
|
||||||
|
|
||||||
passStatement :: Assignment
|
|
||||||
passStatement = makeTerm <$> symbol PassStatement <*> (Statement.NoOp <$> emptyTerm <* advance)
|
|
||||||
|
|
||||||
breakStatement :: Assignment
|
|
||||||
breakStatement = makeTerm <$> symbol BreakStatement <*> (Statement.Break <$> emptyTerm <* advance)
|
|
||||||
|
|
||||||
continueStatement :: Assignment
|
|
||||||
continueStatement = makeTerm <$> symbol ContinueStatement <*> (Statement.Continue <$> emptyTerm <* advance)
|
|
||||||
|
|
||||||
memberAccess :: Assignment
|
|
||||||
memberAccess = makeTerm <$> symbol Attribute <*> children (Expression.MemberAccess <$> expression <*> expression)
|
|
||||||
|
|
||||||
subscript :: Assignment
|
|
||||||
subscript = makeTerm <$> symbol Subscript <*> children (Expression.Subscript <$> expression <*> many expression)
|
|
||||||
|
|
||||||
slice :: Assignment
|
|
||||||
slice = makeTerm <$> symbol Slice <*> children
|
|
||||||
(Expression.Enumeration <$> ((emptyTerm <* token AnonColon) <|> (expression <* token AnonColon))
|
|
||||||
<*> ((emptyTerm <* token AnonColon) <|> (expression <* token AnonColon) <|> (expression <|> emptyTerm))
|
|
||||||
<*> (expression <|> emptyTerm))
|
|
||||||
|
|
||||||
call :: Assignment
|
|
||||||
call = makeTerm <$> symbol Call <*> children (Expression.Call <$> pure [] <*> expression <*> (symbol ArgumentList *> children (many expression)
|
|
||||||
<|> some comprehension) <*> emptyTerm)
|
|
||||||
|
|
||||||
boolean :: Assignment
|
|
||||||
boolean = makeTerm <$> token Grammar.True <*> pure Literal.true
|
|
||||||
<|> makeTerm <$> token Grammar.False <*> pure Literal.false
|
|
||||||
|
|
||||||
none :: Assignment
|
|
||||||
none = makeTerm <$> symbol None <*> (Literal.Null <$ source)
|
|
||||||
|
|
||||||
comprehension :: Assignment
|
|
||||||
comprehension = makeTerm <$> symbol ListComprehension <*> children (Declaration.Comprehension <$> expression <*> expressions)
|
|
||||||
<|> makeTerm <$> symbol GeneratorExpression <*> children (Declaration.Comprehension <$> expression <*> expressions)
|
|
||||||
<|> makeTerm <$> symbol SetComprehension <*> children (Declaration.Comprehension <$> expression <*> expressions)
|
|
||||||
<|> makeTerm <$> symbol DictionaryComprehension <*> children (Declaration.Comprehension <$> expression <*> expressions)
|
|
||||||
|
|
||||||
forInClause :: Assignment
|
|
||||||
forInClause = symbol ForInClause *> children expressions
|
|
||||||
|
|
||||||
variables :: Assignment
|
|
||||||
variables = symbol Variables *> children expressions
|
|
||||||
|
|
||||||
ifClause :: Assignment
|
|
||||||
ifClause = symbol IfClause *> children expressions
|
|
||||||
|
|
||||||
conditionalExpression :: Assignment
|
|
||||||
conditionalExpression = makeTerm <$> symbol ConditionalExpression <*> children (flip Statement.If <$> expression <*> expression <*> expressions)
|
|
||||||
|
|
||||||
-- | Match a term optionally preceded by comment(s), or a sequence of comments if the term is not present.
|
|
||||||
term :: Assignment -> Assignment
|
|
||||||
term term = contextualize comment term <|> makeTerm1 <$> (Syntax.Context <$> some1 comment <*> emptyTerm)
|
|
||||||
|
|
||||||
-- | Match a left-associated infix chain of terms, optionally followed by comments. Like 'chainl1' but assigning comment nodes automatically.
|
|
||||||
chainl1Term :: Assignment -> Assignment.Assignment [] Grammar (Term -> Term -> Term) -> Assignment
|
|
||||||
chainl1Term expr op = postContextualize (comment <|> symbol AnonLambda *> empty) expr `chainl1` op
|
|
||||||
|
|
||||||
-- | Match a series of terms or comments until a delimiter is matched.
|
|
||||||
manyTermsTill :: Show b => Assignment.Assignment [] Grammar Term -> Assignment.Assignment [] Grammar b -> Assignment.Assignment [] Grammar [Term]
|
|
||||||
manyTermsTill step end = manyTill (step <|> comment) end
|
|
||||||
|
|
||||||
-- | Match infix terms separated by any of a list of operators, assigning any comments following each operand.
|
|
||||||
infixTerm :: HasCallStack
|
|
||||||
=> Assignment
|
|
||||||
-> Assignment
|
|
||||||
-> [Assignment.Assignment [] Grammar (Term -> Term -> Union Syntax Term)]
|
|
||||||
-> Assignment.Assignment [] Grammar (Union Syntax Term)
|
|
||||||
infixTerm = infixContext comment
|
|
||||||
|
Loading…
Reference in New Issue
Block a user