diff --git a/NEWS.md b/NEWS.md index d718c34f335bb..7db3129379864 100644 --- a/NEWS.md +++ b/NEWS.md @@ -179,6 +179,8 @@ Language changes * The syntax `using A.B` can now only be used when `A.B` is a module, and the syntax `using A: B` can only be used for adding single bindings ([#8000]). + * `=>` now has its own precedence level, giving it strictly higher precedence than + `=` and `,` ([#25391]). Breaking changes ---------------- diff --git a/src/julia-parser.scm b/src/julia-parser.scm index 667854da2bd16..80ab7f33fa933 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -8,7 +8,9 @@ ;; be an operator. (define prec-assignment (append! (add-dots '(= += -= *= /= //= |\\=| ^= ÷= %= <<= >>= >>>= |\|=| &= ⊻=)) - '(:= => ~ $=))) + '(:= ~ $=))) +;; comma - higher than assignment outside parentheses, lower when inside +(define prec-pair '(=>)) (define prec-conditional '(?)) (define prec-arrow (append! '(-- -->) @@ -34,7 +36,7 @@ (define prec-dot '(|.|)) (define prec-names '(prec-assignment - prec-conditional prec-lazy-or prec-lazy-and prec-arrow prec-comparison + prec-pair prec-conditional prec-lazy-or prec-lazy-and prec-arrow prec-comparison prec-pipe< prec-pipe> prec-colon prec-plus prec-bitshift prec-times prec-rational prec-power prec-decl prec-dot)) @@ -714,8 +716,8 @@ (if (or (eqv? nxt #\,) (eqv? nxt #\) ) (eqv? nxt #\}) (eqv? nxt #\])) t (begin (ts:put-back! s t spc) - (parse-assignment s parse-cond))))) - (parse-assignment s parse-cond)))) + (parse-assignment s parse-pair))))) + (parse-assignment s parse-pair)))) (define (eventually-call? ex) (and (pair? ex) @@ -735,14 +737,12 @@ ex (begin (take-token s) - (cond ((eq? t '~) + (cond ((eq? t '~) ;; ~ is the only non-syntactic assignment-precedence operators (if (and space-sensitive (ts:space? s) (not (eqv? (peek-char (ts:port s)) #\ ))) (begin (ts:put-back! s t (ts:space? s)) ex) (list 'call t ex (parse-assignment s down)))) - ((eq? t '=>) ;; ~ and => are the only non-syntactic assignment-precedence operators - (list 'call t ex (parse-assignment s down))) ((eq? t '=) ;; insert line/file for short-form function defs, otherwise leave alone (let ((lno (input-port-line (ts:port s)))) @@ -753,7 +753,7 @@ ; parse-comma is needed for commas outside parens, for example a = b,c (define (parse-comma s) - (let loop ((ex (list (parse-cond s))) + (let loop ((ex (list (parse-pair s))) (first? #t) (t (peek-token s))) (if (not (eqv? t #\,)) @@ -767,7 +767,9 @@ (begin (take-token s) (if (or (eof-object? (peek-token s)) (eq? (peek-token s) '=)) (loop ex #f (peek-token s)) - (loop (cons (parse-cond s) ex) #f (peek-token s))))))) + (loop (cons (parse-pair s) ex) #f (peek-token s))))))) + +(define (parse-pair s) (parse-RtoL s parse-cond is-prec-pair? #f parse-pair)) (define (parse-cond s) (let ((ex (parse-arrow s))) diff --git a/test/syntax.jl b/test/syntax.jl index f38711da81ea3..5f05074809edc 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -1246,3 +1246,9 @@ function f25055() return x end @test f25055() !== f25055() + +# issue #25391 +@test Meta.parse("0:-1, \"\"=>\"\"") == Meta.parse("(0:-1, \"\"=>\"\")") == + Expr(:tuple, Expr(:(:), 0, -1), Expr(:call, :(=>), "", "")) +@test Meta.parse("a => b = c") == Expr(:(=), Expr(:call, :(=>), :a, :b), Expr(:block, LineNumberNode(1, :none), :c)) +@test Meta.parse("a = b => c") == Expr(:(=), :a, Expr(:call, :(=>), :b, :c))