diff --git a/src/expr.jl b/src/expr.jl index 638e0b75..8bbebaa2 100644 --- a/src/expr.jl +++ b/src/expr.jl @@ -76,6 +76,10 @@ function _leaf_to_Expr(source, txtbuf, txtbuf_offset, head, srcrange, node) return k == K"error" ? Expr(:error) : Expr(:error, "$(_token_error_descriptions[k]): `$(source[srcrange])`") + elseif k == K"begin" # begin/end as firstindex/lastindex + return Expr(:begin) + elseif k == K"end" + return Expr(:end) else val = isnothing(node) ? parse_julia_literal(txtbuf, head, srcrange .+ txtbuf_offset) : diff --git a/src/parser.jl b/src/parser.jl index d1a91478..3d246677 100644 --- a/src/parser.jl +++ b/src/parser.jl @@ -15,7 +15,7 @@ struct ParseState space_sensitive::Bool # Seeing `for` stops parsing macro arguments and makes a generator for_generator::Bool - # Treat 'end' like a normal symbol instead of a reserved word + # Treat begin/end like special symbols instead of reserved words end_symbol::Bool # Treat newline like ordinary whitespace instead of as a potential separator whitespace_newline::Bool @@ -3627,6 +3627,10 @@ function parse_atom(ps::ParseState, check_identifiers=true, has_unary_prefix=fal elseif check_identifiers && is_closing_token(ps, leading_kind) # :(end) ==> (quote-: (error end)) bump(ps, error="invalid identifier") + elseif ps.end_symbol && leading_kind in KSet"begin end" && ps.stream.version >= (1, 13) + # https://github.com/JuliaLang/julia/issues/57269 + # Parse a[begin] differently from a[var"begin"] + bump(ps) else # Remap keywords to identifiers. # :end ==> (quote-: end) diff --git a/test/parser.jl b/test/parser.jl index f208e24c..37338335 100644 --- a/test/parser.jl +++ b/test/parser.jl @@ -410,6 +410,9 @@ tests = [ "(a=1)[]" => "(ref (parens (= a 1)))" "a[end]" => "(ref a end)" "a[begin]" => "(ref a begin)" + "a[var\"end\"]" => "(ref a (var end))" + "a[var\"begin\"]" => "(ref a (var begin))" + "a[var\"test\"]" => "(ref a (var test))" "a[:(end)]" => "(typed_hcat a (quote-: (parens (error-t))) (error-t))" "T[x y]" => "(typed_hcat T x y)" "T[x ; y]" => "(typed_vcat T x y)" @@ -1153,11 +1156,19 @@ parsestmt_with_kind_tests = [ "a >>= b" => "(op= a::Identifier >>::Identifier b::Identifier)" ":+=" => "(quote-: +=::op=)" ":.+=" => "(quote-: (. +=::op=))" + ((v=v"1.13",), "a[begin]") => "(ref a::Identifier begin::begin)" + ((v=v"1.13",), "a[end]") => "(ref a::Identifier end::end)" ] @testset "parser `Kind` remapping" begin @testset "$(repr(input))" for (input, output) in parsestmt_with_kind_tests - input = ((show_kind=true,), input) + if !(input isa AbstractString) + opts, input_s = input + else + opts = NamedTuple() + input_s = input + end + input = ((show_kind=true, opts...), input_s) test_parse(JuliaSyntax.parse_stmts, input, output) end end