diff --git a/NEWS.md b/NEWS.md index 4831de4a33064..4c2f4beae153e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -6,6 +6,7 @@ New language features * `(; a, b) = x` can now be used to destructure properties `a` and `b` of `x`. This syntax is equivalent to `a = getproperty(x, :a)` and similarly for `b`. ([#39285]) +* Implicit multiplication by juxtaposition is now allowed for radical symbols (e.g., `x√y` and `x∛y`). ([#40173]) Language changes ---------------- diff --git a/src/julia-parser.scm b/src/julia-parser.scm index 0b3f52ca61647..9e279fead3fd2 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -101,6 +101,8 @@ (define unary-op? (Set unary-ops)) +(define radical-op? (Set '(√ ∛ ∜))) + ; operators that are both unary and binary (define unary-and-binary-ops (append! '($ & ~) (add-dots '(+ - ⋆ ± ∓)))) @@ -973,7 +975,7 @@ (not (memv t '(#\( #\[ #\{)))) ) (not (ts:space? s)) - (not (operator? t)) + (or (not (operator? t)) (radical-op? t)) (not (closing-token? t)) (not (newline? t)) (or (and (not (string? expr)) (not (eqv? t #\"))) @@ -996,7 +998,7 @@ (begin #;(if (and (number? ex) (= ex 0)) (error "juxtaposition with literal \"0\"")) - (let ((next (parse-factor s))) + (let ((next (if (radical-op? next) (parse-unary s) (parse-factor s)))) (loop `(call * ,ex ,next) (cons next args)))) (if (length= args 1) diff --git a/test/syntax.jl b/test/syntax.jl index eb49a9dfddd60..bfd7beacb89c6 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -1357,7 +1357,6 @@ end @test Meta.parse("√3x^2") == Expr(:call, :*, Expr(:call, :√, 3), Expr(:call, :^, :x, 2)) @test Meta.parse("-3x^2") == Expr(:call, :*, -3, Expr(:call, :^, :x, 2)) @test_throws ParseError Meta.parse("2!3") -@test_throws ParseError Meta.parse("2√3") # issue #27914 @test Meta.parse("2f(x)") == Expr(:call, :*, 2, Expr(:call, :f, :x)) @@ -2752,6 +2751,11 @@ end @test_throws ErrorException("syntax: SSAValue objects should not occur in an AST") eval(:(x = $(Core.SSAValue(1)))) @test_throws ErrorException("syntax: Slot objects should not occur in an AST") eval(:(x = $(Core.SlotNumber(1)))) +# juxtaposition of radical symbols (#40094) +@test Meta.parse("2√3") == Expr(:call, :*, 2, Expr(:call, :√, 3)) +@test Meta.parse("2∛3") == Expr(:call, :*, 2, Expr(:call, :∛, 3)) +@test Meta.parse("2∜3") == Expr(:call, :*, 2, Expr(:call, :∜, 3)) + macro m_underscore_hygiene() return :(_ = 1) end