|
460 | 460 |
|
461 | 461 | # Parse a block, but leave emitting the block up to the caller. |
462 | 462 | function parse_block_inner(ps::ParseState, down::F) where {F <: Function} |
463 | | - parse_Nary(ps, down, KSet"NewlineWs ;", KSet"end else elseif catch finally") |
| 463 | + parse_Nary(ps, down, KSet"NewlineWs ;", KSet"end else elseif catch finally then") |
464 | 464 | end |
465 | 465 |
|
466 | 466 | # ";" at the top level produces a sequence of top level expressions |
@@ -1889,17 +1889,33 @@ function parse_resword(ps::ParseState) |
1889 | 1889 | elseif word == K"while" |
1890 | 1890 | # while cond body end ==> (while cond (block body)) |
1891 | 1891 | # while x < y \n a \n b \n end ==> (while (call-i x < y) (block a b)) |
| 1892 | + # while cond body then else_body end ==> (while cond (block body) (then (block else_body))) |
1892 | 1893 | bump(ps, TRIVIA_FLAG) |
1893 | 1894 | parse_cond(ps) |
1894 | 1895 | parse_block(ps) |
| 1896 | + if peek(ps) == K"then" |
| 1897 | + min_supported_version(v"1.14", ps, mark, "loop then clause") |
| 1898 | + then_mark = position(ps) |
| 1899 | + bump(ps, TRIVIA_FLAG) # consume 'then' |
| 1900 | + parse_block(ps) |
| 1901 | + emit(ps, then_mark, K"then") |
| 1902 | + end |
1895 | 1903 | bump_closing_token(ps, K"end") |
1896 | 1904 | emit(ps, mark, K"while") |
1897 | 1905 | elseif word == K"for" |
1898 | 1906 | # for x in xs end ==> (for (iteration (in x xs)) (block)) |
1899 | 1907 | # for x in xs, y in ys \n a \n end ==> (for (iteration (in x xs) (in y ys)) (block a)) |
| 1908 | + # for x in xs body then else_body end ==> (for (iteration ...) (block body) (then (block else_body))) |
1900 | 1909 | bump(ps, TRIVIA_FLAG) |
1901 | 1910 | parse_iteration_specs(ps) |
1902 | 1911 | parse_block(ps) |
| 1912 | + if peek(ps) == K"then" |
| 1913 | + min_supported_version(v"1.14", ps, mark, "loop then clause") |
| 1914 | + then_mark = position(ps) |
| 1915 | + bump(ps, TRIVIA_FLAG) # consume 'then' |
| 1916 | + parse_block(ps) |
| 1917 | + emit(ps, then_mark, K"then") |
| 1918 | + end |
1903 | 1919 | bump_closing_token(ps, K"end") |
1904 | 1920 | emit(ps, mark, K"for") |
1905 | 1921 | elseif word == K"let" |
@@ -2058,15 +2074,44 @@ function parse_resword(ps::ParseState) |
2058 | 2074 | parse_eq(ps) |
2059 | 2075 | end |
2060 | 2076 | emit(ps, mark, K"return") |
2061 | | - elseif word in KSet"break continue" |
2062 | | - # break ==> (break) |
| 2077 | + elseif word == K"break" |
| 2078 | + # Extended break syntax (1.14+): |
| 2079 | + # break ==> (break) |
| 2080 | + # break x ==> (break x) |
| 2081 | + # break break ==> (break (break)) |
| 2082 | + # break break x ==> (break (break x)) |
| 2083 | + # break continue ==> (break (continue)) |
| 2084 | + bump(ps, TRIVIA_FLAG) |
| 2085 | + k = peek(ps) |
| 2086 | + if k == K"NewlineWs" || is_closing_token(ps, k) |
| 2087 | + # break\n ==> (break) |
| 2088 | + emit(ps, mark, K"break") |
| 2089 | + elseif k == K"break" |
| 2090 | + # break break ... ==> (break (break ...)) |
| 2091 | + min_supported_version(v"1.14", ps, mark, "multi-level break") |
| 2092 | + parse_resword(ps) # Recursive parse of inner break |
| 2093 | + emit(ps, mark, K"break") |
| 2094 | + elseif k == K"continue" |
| 2095 | + # break continue ==> (break (continue)) |
| 2096 | + min_supported_version(v"1.14", ps, mark, "break continue") |
| 2097 | + inner_mark = position(ps) |
| 2098 | + bump(ps, TRIVIA_FLAG) |
| 2099 | + emit(ps, inner_mark, K"continue") |
| 2100 | + emit(ps, mark, K"break") |
| 2101 | + else |
| 2102 | + # break x ==> (break x) |
| 2103 | + min_supported_version(v"1.14", ps, mark, "break with value") |
| 2104 | + parse_eq(ps) |
| 2105 | + emit(ps, mark, K"break") |
| 2106 | + end |
| 2107 | + elseif word == K"continue" |
2063 | 2108 | # continue ==> (continue) |
2064 | 2109 | bump(ps, TRIVIA_FLAG) |
2065 | | - emit(ps, mark, word) |
| 2110 | + emit(ps, mark, K"continue") |
2066 | 2111 | k = peek(ps) |
2067 | 2112 | if !(k in KSet"NewlineWs ; ) : EndMarker" || (k == K"end" && !ps.end_symbol)) |
2068 | 2113 | recover(is_closer_or_newline, ps, TRIVIA_FLAG, |
2069 | | - error="unexpected token after $(untokenize(word))") |
| 2114 | + error="unexpected token after continue") |
2070 | 2115 | end |
2071 | 2116 | elseif word in KSet"module baremodule" |
2072 | 2117 | # module A end ==> (module A (block)) |
|
0 commit comments