Skip to content

Commit 1fdb84f

Browse files
JeffBezansonpkofod
authored andcommitted
preserve elseif syntax in parser
part of JuliaLang#21774
1 parent e44071d commit 1fdb84f

File tree

6 files changed

+82
-31
lines changed

6 files changed

+82
-31
lines changed

NEWS.md

+3
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ Language changes
3232
* `{ }` expressions now use `braces` and `bracescat` as expression heads instead
3333
of `cell1d` and `cell2d`, and parse similarly to `vect` and `vcat` ([#8470]).
3434

35+
* Nested `if` expressions that arise from the keyword `elseif` now use `elseif`
36+
as their expression head instead of `if` ([#21774]).
37+
3538
Breaking changes
3639
----------------
3740

base/show.jl

+15-7
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,11 @@ function show_block(io::IO, head, args::Vector, body, indent::Int)
556556
print(io, head)
557557
if !isempty(args)
558558
print(io, ' ')
559-
show_list(io, args, ", ", indent)
559+
if head === :elseif
560+
show_list(io, args, " ", indent)
561+
else
562+
show_list(io, args, ", ", indent)
563+
end
560564
end
561565

562566
ind = head === :module || head === :baremodule ? indent : indent + indent_width
@@ -879,10 +883,19 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int)
879883
print(io, "function ", args[1], " end")
880884

881885
# block with argument
882-
elseif head in (:for,:while,:function,:if) && nargs==2
886+
elseif head in (:for,:while,:function,:if,:elseif) && nargs==2
883887
show_block(io, head, args[1], args[2], indent)
884888
print(io, "end")
885889

890+
elseif (head === :if || head === :elseif) && nargs == 3
891+
show_block(io, head, args[1], args[2], indent)
892+
if isa(args[3],Expr) && args[3].head == :elseif
893+
show_unquoted(io, args[3], indent, prec)
894+
else
895+
show_block(io, "else", args[3], indent)
896+
print(io, "end")
897+
end
898+
886899
elseif head === :module && nargs==3 && isa(args[1],Bool)
887900
show_block(io, args[1] ? :module : :baremodule, args[2], args[3], indent)
888901
print(io, "end")
@@ -944,11 +957,6 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int)
944957
elseif head === :line && 1 <= nargs <= 2
945958
show_linenumber(io, args...)
946959

947-
elseif head === :if && nargs == 3 # if/else
948-
show_block(io, "if", args[1], args[2], indent)
949-
show_block(io, "else", args[3], indent)
950-
print(io, "end")
951-
952960
elseif head === :try && 3 <= nargs <= 4
953961
show_block(io, "try", args[1], indent)
954962
if is_expr(args[3], :block)

doc/src/devdocs/ast.md

+4-5
Original file line numberDiff line numberDiff line change
@@ -466,18 +466,17 @@ if a
466466
b
467467
elseif c
468468
d
469-
else e
470-
f
469+
else
470+
e
471471
end
472472
```
473473

474474
parses as:
475475

476476
```
477477
(if a (block (line 2) b)
478-
(block (line 3) (if c (block (line 4) d)
479-
(block (line 5) e
480-
(line 6) f))))
478+
(elseif (block (line 3) c) (block (line 4) d)
479+
(block (line 5 e))))
481480
```
482481

483482
A `while` loop parses as `(while condition body)`.

src/julia-parser.scm

+11-9
Original file line numberDiff line numberDiff line change
@@ -1291,31 +1291,33 @@
12911291
`(for ,(if (length= ranges 1) (car ranges) (cons 'block ranges))
12921292
,body)))
12931293

1294-
((if)
1294+
((if elseif)
12951295
(if (newline? (peek-token s))
12961296
(error (string "missing condition in \"if\" at " current-filename
12971297
":" (- (input-port-line (ts:port s)) 1))))
1298-
(let* ((test (parse-cond s))
1298+
(let* ((lno (line-number-node s)) ;; line number for elseif condition
1299+
(test (parse-cond s))
1300+
(test (if (eq? word 'elseif)
1301+
`(block ,lno ,test)
1302+
test))
12991303
(then (if (memq (require-token s) '(else elseif))
13001304
'(block)
13011305
(parse-block s)))
13021306
(nxt (require-token s)))
13031307
(take-token s)
13041308
(case nxt
1305-
((end) (list 'if test then))
1309+
((end) (list word test then))
13061310
((elseif)
13071311
(if (newline? (peek-token s))
13081312
(error (string "missing condition in \"elseif\" at " current-filename
13091313
":" (- (input-port-line (ts:port s)) 1))))
1310-
`(if ,test ,then
1311-
;; line number for elseif condition
1312-
(block ,(line-number-node s)
1313-
,(parse-resword s 'if))))
1314+
`(,word ,test ,then
1315+
,(parse-resword s 'elseif)))
13141316
((else)
13151317
(if (eq? (peek-token s) 'if)
13161318
(error "use \"elseif\" instead of \"else if\""))
1317-
(begin0 (list 'if test then (parse-block s))
1318-
(expect-end s word)))
1319+
(begin0 (list word test then (parse-block s))
1320+
(expect-end s 'if)))
13191321
(else (error (string "unexpected \"" nxt "\""))))))
13201322
((let)
13211323
(let ((binds (if (memv (peek-token s) '(#\newline #\;))

src/julia-syntax.scm

+10-10
Original file line numberDiff line numberDiff line change
@@ -1669,15 +1669,6 @@
16691669
(if ,g ,g
16701670
,(loop (cdr tail)))))))))))
16711671

1672-
(define (expand-forms e)
1673-
(if (or (atom? e) (memq (car e) '(quote inert top core globalref outerref line module toplevel ssavalue null meta)))
1674-
e
1675-
(let ((ex (get expand-table (car e) #f)))
1676-
(if ex
1677-
(ex e)
1678-
(cons (car e)
1679-
(map expand-forms (cdr e)))))))
1680-
16811672
(define (expand-for while lhs X body)
16821673
;; (for (= lhs X) body)
16831674
(let ((coll (make-ssavalue))
@@ -1884,6 +1875,15 @@
18841875
(extract (cdr params) (cons p newparams) whereparams)))))
18851876
(extract (cddr e) '() '()))
18861877

1878+
(define (expand-forms e)
1879+
(if (or (atom? e) (memq (car e) '(quote inert top core globalref outerref line module toplevel ssavalue null meta)))
1880+
e
1881+
(let ((ex (get expand-table (car e) #f)))
1882+
(if ex
1883+
(ex e)
1884+
(cons (car e)
1885+
(map expand-forms (cdr e)))))))
1886+
18871887
;; table mapping expression head to a function expanding that form
18881888
(define expand-table
18891889
(table
@@ -3502,7 +3502,7 @@ f(x) = yt(x)
35023502
(if value
35033503
(compile (cadr e) break-labels value tail)
35043504
#f))
3505-
((if)
3505+
((if elseif)
35063506
(let ((test `(gotoifnot ,(compile-cond (cadr e) break-labels) _))
35073507
(end-jump `(goto _))
35083508
(val (if (and value (not tail)) (new-mutable-var) #f)))

test/show.jl

+39
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,45 @@ end"""
236236
return
237237
end"""
238238

239+
@test_repr """if a
240+
# line meta
241+
b
242+
end
243+
"""
244+
245+
@test_repr """if a
246+
# line meta
247+
b
248+
elseif c
249+
# line meta
250+
d
251+
end
252+
"""
253+
254+
@test_repr """if a
255+
# line meta
256+
b
257+
elseif c
258+
# line meta
259+
d
260+
else
261+
# line meta
262+
e
263+
end
264+
"""
265+
266+
@test_repr """if a
267+
# line meta
268+
b
269+
elseif c
270+
# line meta
271+
d
272+
elseif e
273+
# line meta
274+
f
275+
end
276+
"""
277+
239278
# issue #7188
240279
@test sprint(show, :foo) == ":foo"
241280
@test sprint(show, Symbol("foo bar")) == "Symbol(\"foo bar\")"

0 commit comments

Comments
 (0)