From 4d6f70f617a28271e3a5bc8e4c7dae7196b8e003 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 4 Jan 2017 18:28:56 -0500 Subject: [PATCH] fix #7669, always parse assignments the same inside macro calls --- NEWS.md | 3 +++ src/julia-parser.scm | 45 +++++++++++++++++++++++++++----------------- test/parse.jl | 3 +++ 3 files changed, 34 insertions(+), 17 deletions(-) diff --git a/NEWS.md b/NEWS.md index c03c787dd7f5a5..85b279221d5a4d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -75,6 +75,9 @@ This section lists changes that do not have deprecation warnings. * `quadgk` has been moved from Base into a separate package. ([#19741]) + * In macro calls with parentheses, e.g. `@m(a=1)`, assignments are now parsed as + `=` expressions, instead of as `kw` expressions. ([#7669]) + Library improvements -------------------- diff --git a/src/julia-parser.scm b/src/julia-parser.scm index afbf8b04cf1ff6..dce974d5253750 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -984,7 +984,7 @@ ((#\") '_str) ((#\`) '_cmd))) -(define (parse-call-chain s ex one-call) +(define (parse-call-chain s ex macrocall?) (let loop ((ex ex)) (let ((t (peek-token s))) (if (or (and space-sensitive (ts:space? s) @@ -997,20 +997,27 @@ ((#\( ) (if (ts:space? s) (disallowed-space ex t)) (take-token s) - (let ((c (let ((al (parse-arglist s #\) ))) - (receive - (params args) (separate (lambda (x) - (and (pair? x) - (eq? (car x) 'parameters))) - al) - (if (eq? (peek-token s) 'do) - (begin - (take-token s) - `(call ,ex ,@params ,(parse-do s) ,@args)) - `(call ,ex ,@al)))))) - (if one-call - c - (loop c)))) + (if macrocall? + (let ((args (if (eqv? (require-token s) #\) ) + (begin (take-token s) '()) + (begin0 (with-normal-ops + (with-whitespace-newline + (parse-comma-separated s parse-eq* #t))) + (if (not (eqv? (require-token s) #\) )) + (error "missing ) in argument list")) + (take-token s))))) + `(call ,ex ,@args)) + (loop (let ((al (parse-arglist s #\) ))) + (receive + (params args) (separate (lambda (x) + (and (pair? x) + (eq? (car x) 'parameters))) + al) + (if (eq? (peek-token s) 'do) + (begin + (take-token s) + `(call ,ex ,@params ,(parse-do s) ,@args)) + `(call ,ex ,@al))))))) ((#\[ ) (if (ts:space? s) (disallowed-space ex t)) (take-token s) @@ -1400,11 +1407,15 @@ `(,word ,@(reverse path))))))) ;; parse comma-separated assignments, like "i=1:n,j=1:m,..." -(define (parse-comma-separated s what) +(define (parse-comma-separated s what (in-parens #f)) (let loop ((exprs '())) (let ((r (what s))) (case (peek-token s) - ((#\,) (take-token s) (loop (cons r exprs))) + ((#\,) + (take-token s) + (if (and in-parens (eqv? (require-token s) #\) )) + (reverse! (cons r exprs)) + (loop (cons r exprs)))) (else (reverse! (cons r exprs))))))) (define (parse-comma-separated-assignments s) diff --git a/test/parse.jl b/test/parse.jl index bb0ffb4a28d9ff..2159fc5628e50e 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -868,6 +868,9 @@ let ..(x,y) = x + y @test 3 .. 4 === 7 end +# issue #7669 +@test parse("@a(b=1, c=2)") == Expr(:macrocall, Symbol("@a"), :(b=1), :(c=2)) + # issue #19685 let f = function (x; kw...) return (x, kw)