Skip to content

Commit

Permalink
Parser support for var"" interpolation
Browse files Browse the repository at this point in the history
This is required so that interpolation of variables with var"" is
allowed in contexts where a plain symbol (or $-interpolation) is
expected.
  • Loading branch information
c42f committed Jul 6, 2019
1 parent b84a992 commit 947efbc
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 11 deletions.
44 changes: 33 additions & 11 deletions src/julia-parser.scm
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,17 @@
(define syntactic-op? (Set syntactic-operators))
(define syntactic-unary-op? (Set syntactic-unary-operators))

(define (var-interpolation? ex)
(and (pair? ex)
(eq? 'macrocall (car ex))
(pair? (cdr ex))
(eq? '|@var_str| (cadr ex))))

(define (symbol-or-interpolate? ex)
(or (symbol? ex)
(and (pair? ex)
(eq? '$ (car ex)))))
(eq? '$ (car ex)))
(var-interpolation? ex)))

(define (is-word-operator? op)
(every identifier-start-char? (string->list (symbol->string op))))
Expand Down Expand Up @@ -1112,15 +1119,21 @@

(define (parse-unary-prefix s)
(let ((op (peek-token s)))
(if (syntactic-unary-op? op)
(begin (take-token s)
(cond ((and (memq op '(& $))
(let ((next (peek-token s)))
(or (closing-token? next) (newline? next))))
op)
((memq op '(& |::|)) (list op (parse-where s parse-call)))
(else (list op (parse-unary-prefix s)))))
(parse-atom s))))
(cond ((syntactic-unary-op? op)
(begin (take-token s)
(cond ((and (memq op '(& $))
(let ((next (peek-token s)))
(or (closing-token? next) (newline? next))))
op)
((memq op '(& |::|)) (list op (parse-where s parse-call)))
(else (list op (parse-unary-prefix s))))))
((eq? op 'var)
(take-token s)
(if (and (eqv? (peek-token s) #\") (not (ts:space? s)))
(parse-call-chain s 'var #f)
'var))
(else (parse-atom s)))))


(define (parse-def s is-func anon)
(let* ((ex (parse-unary-prefix s))
Expand Down Expand Up @@ -1219,6 +1232,13 @@
(take-token s)
(let ((dollarex (parse-atom s)))
`(|.| ,ex (inert ($ ,dollarex)))))
((eq? (peek-token s) 'var)
(take-token s)
(let ((varex (if (and (eqv? (peek-token s) #\") (not (ts:space? s)))
;; expand var_str now as the result must be quoted
(symbol (cadddr (parse-call-chain s 'var #f)))
'var)))
`(|.| ,ex (quote ,varex))))
(else
(let ((name (parse-atom s #f)))
(if (and (pair? name) (eq? (car name) 'macrocall))
Expand Down Expand Up @@ -1486,6 +1506,7 @@
(var? (and (not nl) (or (and (symbol? var) (not (eq? var 'false))
(not (eq? var 'true)))
(and (length= var 2) (eq? (car var) '$))
(var-interpolation? var)
(error (string "invalid syntax \"catch " (deparse var) "\"")))))
(catch-block (if (eq? (require-token s) 'finally)
`(block ,(line-number-node s))
Expand Down Expand Up @@ -1555,7 +1576,8 @@
(expect-end s 'do)))))))

(define (macrocall-to-atsym e)
(if (and (pair? e) (eq? (car e) 'macrocall))
(if (and (pair? e) (eq? (car e) 'macrocall)
(not (and (eq? (cadr e) '|@var_str|) (length> e 3))))
(cadr e)
e))

Expand Down
10 changes: 10 additions & 0 deletions test/syntax.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1861,3 +1861,13 @@ let
a32325(x) = a32325()
end
@test a32325(0) === a32325()

# PR #32408
@test Meta.parse("try catch var\"##\" ; end") ==
Expr(:try,
Expr(:block),
Expr(:macrocall, Symbol("@var_str"), LineNumberNode(1,:none), "##"),
Expr(:block, LineNumberNode(1,:none)))
@test Meta.parse("function var\"#\" end") ==
Expr(:function,
Expr(:macrocall, Symbol("@var_str"), LineNumberNode(1,:none), "#"))

0 comments on commit 947efbc

Please sign in to comment.