From 2c00461f23f230010e6bb3f529e9eb3b71a4de8e Mon Sep 17 00:00:00 2001 From: Timothy Clem Date: Thu, 20 Jul 2017 11:15:47 -0700 Subject: [PATCH 1/5] Allow assignment of <> operator in Python --- src/Language/Python/Syntax.hs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index 70c272bbe..ec95fb524 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -253,14 +253,15 @@ ellipsis = makeTerm <$> symbol Grammar.Ellipsis <*> (Language.Python.Syntax.Elli comparisonOperator :: Assignment comparisonOperator = symbol ComparisonOperator >>= \ loc -> children (expression >>= \ lexpression -> makeComparison loc lexpression) where - makeComparison loc lexpression = makeTerm loc <$ symbol AnonLAngle <*> (Expression.LessThan lexpression <$> expression) - <|> makeTerm loc <$ symbol AnonLAngleEqual <*> (Expression.LessThanEqual lexpression <$> expression) - <|> makeTerm loc <$ symbol AnonRAngle <*> (Expression.GreaterThan lexpression <$> expression) - <|> makeTerm loc <$ symbol AnonRAngleEqual <*> (Expression.GreaterThanEqual lexpression <$> expression) - <|> makeTerm loc <$ symbol AnonEqualEqual <*> (Expression.Equal lexpression <$> expression) - <|> makeTerm loc <$ symbol AnonBangEqual <*> (Expression.Not <$> (makeTerm <$> location <*> (Expression.Equal lexpression <$> expression))) - <|> makeTerm loc <$ symbol AnonNot <*> (Expression.Not <$> (makeTerm <$> location <*> (Expression.Member lexpression <$> expression))) - <|> makeTerm loc <$ symbol AnonIn <*> (Expression.Member lexpression <$> expression) + makeComparison loc lexpression = makeTerm loc <$ symbol AnonLAngle <*> (Expression.LessThan lexpression <$> expression) + <|> makeTerm loc <$ symbol AnonLAngleEqual <*> (Expression.LessThanEqual lexpression <$> expression) + <|> makeTerm loc <$ symbol AnonRAngle <*> (Expression.GreaterThan lexpression <$> expression) + <|> makeTerm loc <$ symbol AnonRAngleEqual <*> (Expression.GreaterThanEqual lexpression <$> expression) + <|> makeTerm loc <$ symbol AnonEqualEqual <*> (Expression.Equal lexpression <$> expression) + <|> makeTerm loc <$ symbol AnonBangEqual <*> (Expression.Not <$> (makeTerm <$> location <*> (Expression.Equal lexpression <$> expression))) + <|> makeTerm loc <$ symbol AnonLAngleRAngle <*> (Expression.Not <$> (makeTerm <$> location <*> (Expression.Equal lexpression <$> expression))) + <|> makeTerm loc <$ symbol AnonNot <*> (Expression.Not <$> (makeTerm <$> location <*> (Expression.Member lexpression <$> expression))) + <|> makeTerm loc <$ symbol AnonIn <*> (Expression.Member lexpression <$> expression) -- source is used here to push the cursor to the next node to enable matching against `AnonNot` <|> symbol AnonIs *> source *> (symbol AnonNot *> (makeTerm loc <$> Expression.Not <$> (makeTerm <$> location <*> (Expression.Equal lexpression <$> expression))) <|> (makeTerm loc <$> Expression.Equal lexpression <$> expression)) From 2ca5412769d369ff056ad2255774834f195ee6d1 Mon Sep 17 00:00:00 2001 From: Timothy Clem Date: Thu, 20 Jul 2017 11:26:26 -0700 Subject: [PATCH 2/5] Python ExpressionStatement can have one or more declarations --- src/Language/Python/Syntax.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index ec95fb524..cdf316b61 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -146,7 +146,7 @@ literal = boolean <|> parseError expressionStatement :: Assignment -expressionStatement = symbol ExpressionStatement *> children declaration +expressionStatement = makeTerm <$> symbol ExpressionStatement <*> children (some declaration) expression :: Assignment expression = argument From 996b8fbf30004d0fa4c79919a547e7253abda22d Mon Sep 17 00:00:00 2001 From: Timothy Clem Date: Thu, 20 Jul 2017 11:39:07 -0700 Subject: [PATCH 3/5] Fix python assignment for multiple statements in if body --- src/Language/Python/Syntax.hs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index cdf316b61..911a2eff0 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -133,6 +133,9 @@ statement = assertStatement <|> withStatement <|> parseError +statements :: Assignment +statements = makeTerm <$> location <*> many statement + literal :: Assignment literal = boolean <|> concatenatedString @@ -400,7 +403,7 @@ raiseStatement :: Assignment raiseStatement = makeTerm <$> symbol RaiseStatement <*> children (Statement.Throw <$> (makeTerm <$> location <*> many expression)) ifStatement :: Assignment -ifStatement = makeTerm <$> symbol IfStatement <*> children (Statement.If <$> expression <*> statement <*> (flip (foldr makeElif) <$> many elifClause <*> optionalElse)) +ifStatement = makeTerm <$> symbol IfStatement <*> children (Statement.If <$> expression <*> statements <*> (flip (foldr makeElif) <$> many elifClause <*> optionalElse)) where elseClause = symbol ElseClause *> children statement elifClause = (,) <$ symbol ElifClause <*> location <*> children (Statement.If <$> expression <*> statement) optionalElse = fromMaybe <$> emptyTerm <*> optional elseClause From 6bf440d2402a450040947f1c138e03eb02d801aa Mon Sep 17 00:00:00 2001 From: Timothy Clem Date: Thu, 20 Jul 2017 11:42:56 -0700 Subject: [PATCH 4/5] Python elif and else need to take multiple statements too --- src/Language/Python/Syntax.hs | 4 ++-- test/fixtures/python/if-statement.A.py | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index 911a2eff0..812054167 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -404,8 +404,8 @@ raiseStatement = makeTerm <$> symbol RaiseStatement <*> children (Statement.Thro ifStatement :: Assignment ifStatement = makeTerm <$> symbol IfStatement <*> children (Statement.If <$> expression <*> statements <*> (flip (foldr makeElif) <$> many elifClause <*> optionalElse)) - where elseClause = symbol ElseClause *> children statement - elifClause = (,) <$ symbol ElifClause <*> location <*> children (Statement.If <$> expression <*> statement) + where elseClause = symbol ElseClause *> children statements + elifClause = (,) <$ symbol ElifClause <*> location <*> children (Statement.If <$> expression <*> statements) optionalElse = fromMaybe <$> emptyTerm <*> optional elseClause makeElif (loc, makeIf) rest = makeTerm loc (makeIf rest) diff --git a/test/fixtures/python/if-statement.A.py b/test/fixtures/python/if-statement.A.py index 5a82ed280..609f4c22e 100644 --- a/test/fixtures/python/if-statement.A.py +++ b/test/fixtures/python/if-statement.A.py @@ -1,3 +1,9 @@ if a: b c +elif d: + a + b +else: + x + y From fc9851334f244d1655abd7642c222c7052107fcb Mon Sep 17 00:00:00 2001 From: Timothy Clem Date: Thu, 20 Jul 2017 11:54:41 -0700 Subject: [PATCH 5/5] Introduce expressions and declarations to Python assignment to cleanup code --- src/Language/Python/Syntax.hs | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index 812054167..0d3b36885 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -108,6 +108,9 @@ declaration = classDefinition <|> statement <|> parseError +declarations :: Assignment +declarations = makeTerm <$> location <*> many declaration + statement :: Assignment statement = assertStatement <|> assignment' @@ -176,6 +179,9 @@ expression = argument <|> unaryOperator <|> parseError +expressions :: Assignment +expressions = makeTerm <$> location <*> many expression + argument :: Assignment argument = makeTerm <$> symbol ListSplatArgument <*> (Syntax.Identifier <$> source) <|> makeTerm <$> symbol DictionarySplatArgument <*> (Syntax.Identifier <$> source) @@ -202,33 +208,33 @@ withStatement :: Assignment withStatement = makeTerm <$> symbol WithStatement <*> children (uncurry Statement.Let . swap <$> (symbol WithItem *> children ((,) <$> identifier <*> identifier)) <*> expression) forStatement :: Assignment -forStatement = symbol ForStatement >>= \ loc -> children (make loc <$> (makeTerm <$> symbol Variables <*> children (many expression)) <*> expressionList <*> (makeTerm <$> location <*> many expression) <*> (optional (makeTerm <$> symbol ElseClause <*> children (many declaration)))) +forStatement = symbol ForStatement >>= \ loc -> children (make loc <$> (makeTerm <$> symbol Variables <*> children (many expression)) <*> expressionList <*> expressions <*> optional (makeTerm <$> symbol ElseClause <*> children (many declaration))) where make loc variables expressionList forBody forElseClause = case forElseClause of Nothing -> makeTerm loc (Statement.ForEach variables expressionList forBody) Just a -> makeTerm loc (Statement.Else (makeTerm loc $ Statement.ForEach variables expressionList forBody) a) whileStatement :: Assignment -whileStatement = symbol WhileStatement >>= \ loc -> children (make loc <$> expression <*> (makeTerm <$> location <*> many expression) <*> (optional (makeTerm <$> symbol ElseClause <*> children (many declaration)))) +whileStatement = symbol WhileStatement >>= \ loc -> children (make loc <$> expression <*> expressions <*> optional (makeTerm <$> symbol ElseClause <*> children (many declaration))) 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 <*> (makeTerm <$> location <*> (many expression))) +tryStatement = makeTerm <$> symbol TryStatement <*> children (Statement.Try <$> expression <*> many (expression <|> elseClause)) + where elseClause = makeTerm <$> symbol ElseClause <*> children (Statement.Else <$> emptyTerm <*> (makeTerm <$> location <*> many expression)) exceptClause :: Assignment exceptClause = makeTerm <$> symbol ExceptClause <*> children (Statement.Catch <$> ((makeTerm <$> location <*> (uncurry Statement.Let . swap <$> ((,) <$> identifier <* symbol AnonAs <*> identifier) <*> emptyTerm)) - <|> (makeTerm <$> location <*> (many identifier))) - <*> (makeTerm <$> location <*> (many expression))) + <|> makeTerm <$> location <*> many identifier) + <*> expressions) functionDefinition :: Assignment -functionDefinition = (symbol FunctionDefinition >>= \ loc -> children (makeFunctionDeclaration loc <$> identifier <*> (symbol Parameters *> children (many expression)) <*> (optional (symbol Type *> children expression)) <*> (makeTerm <$> location <*> many declaration))) - <|> (symbol AsyncFunctionDefinition >>= \ loc -> children (makeAsyncFunctionDeclaration loc <$> async' <*> identifier <*> (symbol Parameters *> children (many expression)) <*> (optional (symbol Type *> children expression)) <*> (makeTerm <$> location <*> many declaration))) - <|> (symbol Lambda >>= \ loc -> children (makeFunctionDeclaration loc <$> (makeTerm <$> symbol AnonLambda <*> (Syntax.Identifier <$> source)) <*> ((symbol LambdaParameters *> children (many expression)) <|> (pure [])) <*> (optional (symbol Type *> children expression)) <*> (makeTerm <$> location <*> many declaration))) +functionDefinition = (symbol FunctionDefinition >>= \ loc -> children (makeFunctionDeclaration loc <$> identifier <*> (symbol Parameters *> children (many expression)) <*> optional (symbol Type *> children expression) <*> declarations)) + <|> (symbol AsyncFunctionDefinition >>= \ loc -> children (makeAsyncFunctionDeclaration loc <$> async' <*> identifier <*> (symbol Parameters *> children (many expression)) <*> optional (symbol Type *> children expression) <*> declarations)) + <|> (symbol Lambda >>= \ loc -> children (makeFunctionDeclaration loc <$> (makeTerm <$> symbol AnonLambda <*> (Syntax.Identifier <$> source)) <*> ((symbol LambdaParameters *> children (many expression)) <|> pure []) <*> optional (symbol Type *> children expression) <*> declarations)) where makeFunctionDeclaration loc functionName' functionParameters ty functionBody = makeTerm loc $ Type.Annotation (makeTerm loc $ Declaration.Function functionName' functionParameters functionBody) (maybe (makeTerm loc Syntax.Empty) identity 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) identity ty)) async' @@ -237,7 +243,7 @@ async' :: Assignment async' = makeTerm <$> symbol AnonAsync <*> (Syntax.Identifier <$> source) classDefinition :: Assignment -classDefinition = makeTerm <$> symbol ClassDefinition <*> children (Declaration.Class <$> identifier <*> argumentList <*> (many declaration)) +classDefinition = makeTerm <$> symbol ClassDefinition <*> children (Declaration.Class <$> identifier <*> argumentList <*> many declaration) where argumentList = symbol ArgumentList *> children (many expression) <|> pure [] @@ -276,7 +282,7 @@ keyword :: Assignment keyword = makeTerm <$> symbol KeywordIdentifier <*> children (Syntax.Identifier <$> source) tuple :: Assignment -tuple = makeTerm <$> symbol Tuple <*> children (Literal.Tuple <$> (many expression)) +tuple = makeTerm <$> symbol Tuple <*> children (Literal.Tuple <$> many expression) -- TODO: Consider flattening single element lists expressionList :: Assignment @@ -400,7 +406,7 @@ deleteStatement = makeTerm <$> symbol DeleteStatement <*> children (Expression.C where deleteIdentifier = makeTerm <$> symbol AnonDel <*> (Syntax.Identifier <$> source) raiseStatement :: Assignment -raiseStatement = makeTerm <$> symbol RaiseStatement <*> children (Statement.Throw <$> (makeTerm <$> location <*> many expression)) +raiseStatement = makeTerm <$> symbol RaiseStatement <*> children (Statement.Throw <$> expressions) ifStatement :: Assignment ifStatement = makeTerm <$> symbol IfStatement <*> children (Statement.If <$> expression <*> statements <*> (flip (foldr makeElif) <$> many elifClause <*> optionalElse))