Skip to content

Commit f418f4a

Browse files
committed
support for for-else and while-else
companion to JuliaLang/julia#56153
1 parent 9483de8 commit f418f4a

File tree

4 files changed

+59
-11
lines changed

4 files changed

+59
-11
lines changed

src/expr.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ function _string_to_Expr(args)
138138
# """\n a\n b""" ==> "a\nb"
139139
return only(args2)
140140
else
141-
# This only happens when the kind is K"string" or when an error has occurred.
141+
# This only happens when the kind is K"string" or when an error has occurred.
142142
return Expr(:string, args2...)
143143
end
144144
end
@@ -157,7 +157,7 @@ function _fixup_Expr_children!(head, loc, args)
157157
arg = args[i]
158158
was_parens = @isexpr(arg, :parens)
159159
arg = _strip_parens(arg)
160-
if @isexpr(arg, :(=)) && eq_to_kw_in_call && i > 1
160+
if @isexpr(arg, :(=)) && eq_to_kw_in_call && i > 1
161161
arg = Expr(:kw, arg.args...)
162162
elseif k != K"parens" && @isexpr(arg, :., 1) && arg.args[1] isa Tuple
163163
h, a = arg.args[1]::Tuple{SyntaxHead,Any}
@@ -310,10 +310,10 @@ function _internal_node_to_Expr(source, srcrange, head, childranges, childheads,
310310
args[1] = length(iters) == 1 ? only(iters) : Expr(:block, iters...)
311311
# Add extra line number node for the `end` of the block. This may seem
312312
# useless but it affects code coverage.
313-
push!(args[2].args, endloc)
313+
push!(args[end].args, endloc)
314314
elseif k == K"while"
315315
# Line number node for the `end` of the block as in `for` loops.
316-
push!(args[2].args, endloc)
316+
push!(args[end].args, endloc)
317317
elseif k in KSet"tuple vect braces"
318318
# Move parameters blocks to args[1]
319319
_reorder_parameters!(args, 1)

src/parser.jl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1813,6 +1813,13 @@ function parse_resword(ps::ParseState)
18131813
bump(ps, TRIVIA_FLAG)
18141814
parse_cond(ps)
18151815
parse_block(ps)
1816+
bump_trivia(ps)
1817+
if peek(ps) == K"else"
1818+
else_mark = position(ps)
1819+
bump(ps, TRIVIA_FLAG)
1820+
parse_block(ps)
1821+
min_supported_version(v"1.12", ps, else_mark, "`else` after `for`")
1822+
end
18161823
bump_closing_token(ps, K"end")
18171824
emit(ps, mark, K"while")
18181825
elseif word == K"for"
@@ -1821,6 +1828,13 @@ function parse_resword(ps::ParseState)
18211828
bump(ps, TRIVIA_FLAG)
18221829
parse_iteration_specs(ps)
18231830
parse_block(ps)
1831+
bump_trivia(ps)
1832+
if peek(ps) == K"else"
1833+
else_mark = position(ps)
1834+
bump(ps, TRIVIA_FLAG)
1835+
parse_block(ps)
1836+
min_supported_version(v"1.12", ps, else_mark, "`else` after `for`")
1837+
end
18241838
bump_closing_token(ps, K"end")
18251839
emit(ps, mark, K"for")
18261840
elseif word == K"let"

test/expr.jl

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,21 @@
189189
LineNumberNode(3)
190190
)
191191
)
192+
if VERSION >= v"1.12-"
193+
@test parsestmt("for x=xs\ny\nelse\nz\nend") ==
194+
Expr(:for,
195+
Expr(:(=), :x, :xs),
196+
Expr(:block,
197+
LineNumberNode(2),
198+
:y,
199+
),
200+
Expr(:block,
201+
LineNumberNode(4),
202+
:z,
203+
LineNumberNode(5)
204+
)
205+
)
206+
end
192207
@test parsestmt("while cond\n\nend") ==
193208
Expr(:while,
194209
:cond,
@@ -206,6 +221,21 @@
206221
LineNumberNode(3)
207222
)
208223
)
224+
if VERSION >= v"1.12-"
225+
@test parsestmt("while cond\ny\nelse\nz\nend") ==
226+
Expr(:while,
227+
:cond,
228+
Expr(:block,
229+
LineNumberNode(2),
230+
:y,
231+
),
232+
Expr(:block,
233+
LineNumberNode(4),
234+
:z,
235+
LineNumberNode(5)
236+
)
237+
)
238+
end
209239
end
210240
end
211241

@@ -361,7 +391,7 @@
361391
Expr(:call, :f, Expr(:parameters, Expr(:kw, :b, 2)))
362392
@test parsestmt("f(a=1; b=2)") ==
363393
Expr(:call, :f, Expr(:parameters, Expr(:kw, :b, 2)), Expr(:kw, :a, 1))
364-
@test parsestmt("f(a; b; c)") ==
394+
@test parsestmt("f(a; b; c)") ==
365395
Expr(:call, :f, Expr(:parameters, Expr(:parameters, :c), :b), :a)
366396
@test parsestmt("+(a=1,)") ==
367397
Expr(:call, :+, Expr(:kw, :a, 1))
@@ -371,11 +401,11 @@
371401
# Operator calls: = is not :kw
372402
@test parsestmt("(x=1) != 2") ==
373403
Expr(:call, :!=, Expr(:(=), :x, 1), 2)
374-
@test parsestmt("+(a=1)") ==
404+
@test parsestmt("+(a=1)") ==
375405
Expr(:call, :+, Expr(:(=), :a, 1))
376-
@test parsestmt("(a=1)'") ==
406+
@test parsestmt("(a=1)'") ==
377407
Expr(Symbol("'"), Expr(:(=), :a, 1))
378-
@test parsestmt("(a=1)'ᵀ") ==
408+
@test parsestmt("(a=1)'ᵀ") ==
379409
Expr(:call, Symbol("'ᵀ"), Expr(:(=), :a, 1))
380410

381411
# Dotcall
@@ -583,8 +613,8 @@
583613
Expr(:generator, :x,
584614
Expr(:filter, :z, Expr(:(=), :a, :as), Expr(:(=), :b, :bs)))
585615
@test parsestmt("(x for a in as, b in bs for c in cs, d in ds)") ==
586-
Expr(:flatten,
587-
Expr(:generator,
616+
Expr(:flatten,
617+
Expr(:generator,
588618
Expr(:generator, :x, Expr(:(=), :c, :cs), Expr(:(=), :d, :ds)),
589619
Expr(:(=), :a, :as), Expr(:(=), :b, :bs)))
590620
@test parsestmt("(x for a in as for b in bs if z)") ==
@@ -754,7 +784,7 @@
754784
@test parsestmt("global x ~ 1") == Expr(:global, Expr(:call, :~, :x, 1))
755785
@test parsestmt("global x += 1") == Expr(:global, Expr(:+=, :x, 1))
756786

757-
# Parsing of global/local with
787+
# Parsing of global/local with
758788
@test parsestmt("global (x,y)") == Expr(:global, :x, :y)
759789
@test parsestmt("local (x,y)") == Expr(:local, :x, :y)
760790
end

test/parser.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,9 +474,13 @@ tests = [
474474
# while
475475
"while cond body end" => "(while cond (block body))"
476476
"while x < y \n a \n b \n end" => "(while (call-i x < y) (block a b))"
477+
((v=v"1.12",), "while x < y \n a \n else \n b \n end") =>
478+
"(while (call-i x < y) (block a) (block b))"
477479
# for
478480
"for x in xs end" => "(for (iteration (in x xs)) (block))"
479481
"for x in xs, y in ys \n a \n end" => "(for (iteration (in x xs) (in y ys)) (block a))"
482+
((v=v"1.12",), "for x in xs \n a \n else \n b \n end") =>
483+
"(for (iteration (in x xs)) (block a) (block b))"
480484
# let
481485
"let x=1\n end" => "(let (block (= x 1)) (block))"
482486
"let x=1 ; end" => "(let (block (= x 1)) (block))"

0 commit comments

Comments
 (0)