Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/Elm/Parser/Expression.elm
Original file line number Diff line number Diff line change
Expand Up @@ -944,6 +944,12 @@ negationOperation =
"," ->
negationAfterMinus

">" ->
negationAfterMinus

"=" ->
negationAfterMinus

-- TODO only for tests
"" ->
negationAfterMinus
Expand Down
21 changes: 21 additions & 0 deletions tests/Elm/Parser/DeclarationsTests.elm
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,27 @@ foo = bar"""
}
)
)
, test "function declaration with negation sign after =" <|
\() ->
"foo=-1"
|> expectAst
(Node { start = { row = 1, column = 1 }, end = { row = 1, column = 7 } }
(FunctionDeclaration
{ documentation = Nothing
, signature = Nothing
, declaration =
Node { start = { row = 1, column = 1 }, end = { row = 1, column = 7 } }
{ name = Node { start = { row = 1, column = 1 }, end = { row = 1, column = 4 } } "foo"
, arguments = []
, expression =
Node { start = { row = 1, column = 5 }, end = { row = 1, column = 7 } }
(Negation
(Node { start = { row = 1, column = 6 }, end = { row = 1, column = 7 } } (Integer 1))
)
}
}
)
)
, test "function with case in let" <|
\() ->
"""inc x =
Expand Down
195 changes: 194 additions & 1 deletion tests/Elm/Parser/ExpressionTests.elm
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module Elm.Parser.ExpressionTests exposing (all)
import Elm.Parser.Declarations
import Elm.Parser.Expression exposing (expression)
import Elm.Parser.ParserWithCommentsTestUtil as ParserWithCommentsUtil
import Elm.Syntax.Expression exposing (Expression(..))
import Elm.Syntax.Expression exposing (Expression(..), LetDeclaration(..))
import Elm.Syntax.Infix as Infix exposing (InfixDirection(..))
import Elm.Syntax.Node exposing (Node(..))
import Elm.Syntax.Pattern exposing (..)
Expand Down Expand Up @@ -566,6 +566,17 @@ all =
(Node { start = { row = 1, column = 3 }, end = { row = 1, column = 4 } } (Integer 1))
)
)
, test "subtraction without spaces with variables" <|
\() ->
"n-n"
|> expectAst
(Node { start = { row = 1, column = 1 }, end = { row = 1, column = 4 } }
(OperatorApplication "-"
Left
(Node { start = { row = 1, column = 1 }, end = { row = 1, column = 2 } } (FunctionOrValue [] "n"))
(Node { start = { row = 1, column = 3 }, end = { row = 1, column = 4 } } (FunctionOrValue [] "n"))
)
)
, test "negated expression for value" <|
\() ->
"-x"
Expand All @@ -590,6 +601,116 @@ all =
]
)
)
, test "negated expression after = in record" <|
\() ->
"{a=-x}"
|> expectAst
(Node { start = { row = 1, column = 1 }, end = { row = 1, column = 7 } }
(RecordExpr
[ Node { start = { row = 1, column = 2 }, end = { row = 1, column = 6 } }
( Node { start = { row = 1, column = 2 }, end = { row = 1, column = 3 } } "a"
, Node { start = { row = 1, column = 4 }, end = { row = 1, column = 6 } }
(Negation
(Node { start = { row = 1, column = 5 }, end = { row = 1, column = 6 } } (FunctionOrValue [] "x"))
)
)
]
)
)
, test "negated expression after ==" <|
\() ->
"a==-x"
Copy link
Copy Markdown
Contributor

@lue-bird lue-bird Feb 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in theory this one should not parse if we want to be that strict

-- UNKNOWN OPERATOR ------------------------------------------------------- REPL

I do not recognize the (==-) operator.

1|   a==-x
      ^^^
Is there an `import` and `exposing` entry for it? Maybe you want (==) or (-)
instead?

Also, the fact that the let...in-a test fails is bad. We probably either need

  • to check on "n" that the previous is "i" and the one before isn't alphanumeric
  • a different kind of negation parser for after in specifically.

Currently I have passing tests with

if
    (String.slice (offset - 3) (offset - 2) source == "i")
        && Basics.not
            (String.all Char.Extra.isLatinAlphaNumOrUnderscoreFast
                (String.slice (offset - 4) (offset - 3) source)
            )
then
    negationAfterMinus

else
    ParserFast.problem

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, right.

And I agree that the current system is not enough for in.

|> expectAst
(Node { start = { row = 1, column = 1 }, end = { row = 1, column = 7 } }
(TupledExpression
[ Node { start = { row = 1, column = 2 }, end = { row = 1, column = 3 } }
(Integer 0)
, Node { start = { row = 1, column = 4 }, end = { row = 1, column = 6 } }
(Negation
(Node { start = { row = 1, column = 5 }, end = { row = 1, column = 6 } }
(FunctionOrValue [] "x")
)
)
]
)
)
, test "negated expression after -> in anonymous function" <|
\() ->
"\\a->-x"
|> expectAst
(Node { start = { row = 1, column = 1 }, end = { row = 1, column = 7 } }
(LambdaExpression
{ args = [ Node { start = { row = 1, column = 2 }, end = { row = 1, column = 3 } } (VarPattern "a") ]
, expression =
Node { start = { row = 1, column = 5 }, end = { row = 1, column = 7 } }
(Negation
(Node { start = { row = 1, column = 6 }, end = { row = 1, column = 7 } } (FunctionOrValue [] "x"))
)
}
)
)
, test "negated expression after list" <|
\() ->
"List.sum [a,b]-x"
|> expectAst
(Node { start = { row = 1, column = 1 }, end = { row = 1, column = 17 } }
(OperatorApplication "-"
Left
(Node { start = { row = 1, column = 1 }, end = { row = 1, column = 15 } }
(Application
[ Node { start = { row = 1, column = 1 }, end = { row = 1, column = 9 } }
(FunctionOrValue [ "List" ] "sum")
, Node { start = { row = 1, column = 10 }, end = { row = 1, column = 15 } }
(ListExpr
[ Node { start = { row = 1, column = 11 }, end = { row = 1, column = 12 } } (FunctionOrValue [] "a")
, Node { start = { row = 1, column = 13 }, end = { row = 1, column = 14 } } (FunctionOrValue [] "b")
]
)
]
)
)
(Node { start = { row = 1, column = 16 }, end = { row = 1, column = 17 } } (FunctionOrValue [] "x"))
)
)
, test "negated expression after = in let declaration" <|
\() ->
"let a=-x in a"
|> expectAst
(Node { start = { row = 1, column = 1 }, end = { row = 1, column = 14 } }
(LetExpression
{ declarations = [ Node { start = { row = 1, column = 5 }, end = { row = 1, column = 9 } } (LetFunction { documentation = Nothing, signature = Nothing, declaration = Node { start = { row = 1, column = 5 }, end = { row = 1, column = 9 } } { name = Node { start = { row = 1, column = 5 }, end = { row = 1, column = 6 } } "a", arguments = [], expression = Node { start = { row = 1, column = 7 }, end = { row = 1, column = 9 } } (Negation (Node { start = { row = 1, column = 8 }, end = { row = 1, column = 9 } } (FunctionOrValue [] "x"))) } }) ]
, expression = Node { start = { row = 1, column = 13 }, end = { row = 1, column = 14 } } (FunctionOrValue [] "a")
}
)
)
, test "negated expression after -> in case branch" <|
\() ->
"case 1 of\n _->-a"
|> expectAst
(Node { start = { row = 1, column = 1 }, end = { row = 2, column = 10 } }
(CaseExpression
{ expression = Node { start = { row = 1, column = 6 }, end = { row = 1, column = 7 } } (Integer 1)
, cases = [ ( Node { start = { row = 2, column = 5 }, end = { row = 2, column = 6 } } AllPattern, Node { start = { row = 2, column = 8 }, end = { row = 2, column = 10 } } (Negation (Node { start = { row = 2, column = 9 }, end = { row = 2, column = 10 } } (FunctionOrValue [] "a"))) ) ]
}
)
)
, test "negated expression after `in` in let body" <|
\() ->
"let a=-x in-a"
|> expectAst
(Node { start = { row = 1, column = 1 }, end = { row = 1, column = 7 } }
(TupledExpression
[ Node { start = { row = 1, column = 2 }, end = { row = 1, column = 3 } }
(Integer 0)
, Node { start = { row = 1, column = 4 }, end = { row = 1, column = 6 } }
(Negation
(Node { start = { row = 1, column = 5 }, end = { row = 1, column = 6 } }
(FunctionOrValue [] "x")
)
)
]
)
)
, test "negated expression in application" <|
\() ->
"toFloat -5"
Expand All @@ -602,6 +723,62 @@ all =
]
)
)
, test "negated expression after literal" <|
\() ->
"""String.length""-1"""
|> expectAst
(Node { start = { row = 1, column = 1 }, end = { row = 1, column = 18 } }
(OperatorApplication "-"
Left
(Node { start = { row = 1, column = 1 }, end = { row = 1, column = 16 } }
(Application
[ Node { start = { row = 1, column = 1 }, end = { row = 1, column = 14 } } (FunctionOrValue [ "String" ] "length")
, Node { start = { row = 1, column = 14 }, end = { row = 1, column = 16 } } (Literal "")
]
)
)
(Node { start = { row = 1, column = 17 }, end = { row = 1, column = 18 } } (Integer 1))
)
)
, test "negation after exponentiation should succeed when there is spacing after ^" <|
\() ->
"n ^ -x"
|> expectAst
(Node { start = { row = 1, column = 1 }, end = { row = 1, column = 7 } }
(OperatorApplication "^"
Right
(Node { start = { row = 1, column = 1 }, end = { row = 1, column = 2 } } (FunctionOrValue [] "n"))
(Node { start = { row = 1, column = 5 }, end = { row = 1, column = 7 } }
(Negation
(Node { start = { row = 1, column = 6 }, end = { row = 1, column = 7 } } (FunctionOrValue [] "x"))
)
)
)
)
, test "negation after <| should fail" <|
\() ->
"f<|-x"
|> expectInvalid
, test "negation after |> should fail" <|
\() ->
"f|>x"
|> expectInvalid
, test "negation after exponentiation should fail when there is no spacing after ^" <|
\() ->
"n ^-x"
|> expectInvalid
, test "negation after || should fail when there is no spacing" <|
\() ->
"condition||-x"
|> expectInvalid
, test "negation after && should fail when there is no spacing" <|
\() ->
"condition&&-x"
|> expectInvalid
, test "negation after :: should fail when there is no spacing" <|
\() ->
"x::-x :: []"
|> expectInvalid
, test "negated expression for parenthesized" <|
\() ->
"-(x - y)"
Expand Down Expand Up @@ -660,6 +837,17 @@ all =
)
)
)
, test ":: and list literal attached" <|
\() ->
"1::[]"
|> expectAst
(Node { start = { row = 1, column = 1 }, end = { row = 1, column = 6 } }
(OperatorApplication "::"
Right
(Node { start = { row = 1, column = 1 }, end = { row = 1, column = 2 } } (Integer 1))
(Node { start = { row = 1, column = 4 }, end = { row = 1, column = 6 } } (ListExpr []))
)
)
, test "plus and minus in the same expression" <|
\() ->
"1 + 2 - 3"
Expand Down Expand Up @@ -976,6 +1164,11 @@ expectAst =
ParserWithCommentsUtil.expectAst expression


expectInvalid : String -> Expect.Expectation
expectInvalid =
ParserWithCommentsUtil.expectInvalid expression


expectAstWithComments : { ast : Node Expression, comments : List (Node String) } -> String -> Expect.Expectation
expectAstWithComments =
ParserWithCommentsUtil.expectAstWithComments expression