Skip to content

Commit 244be72

Browse files
committed
Make low precedence comma a feature flag, off by default
Also enable it within concatenation syntax for consistency
1 parent e220819 commit 244be72

File tree

4 files changed

+42
-25
lines changed

4 files changed

+42
-25
lines changed

src/parse_stream.jl

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -236,12 +236,16 @@ mutable struct ParseStream
236236
diagnostics::Vector{Diagnostic}
237237
# Counter for number of peek()s we've done without making progress via a bump()
238238
peek_count::Int
239+
240+
# Feature flags
239241
# (major,minor) version of Julia we're parsing this code for.
240242
# May be different from VERSION!
241243
version::Tuple{Int,Int}
244+
# Comma binds looser than macrocall in bracketed expressions
245+
low_precedence_comma_in_brackets::Bool
242246

243-
function ParseStream(text_buf::Vector{UInt8}, text_root, next_byte::Integer,
244-
version::VersionNumber)
247+
function ParseStream(text_buf::Vector{UInt8}, text_root, next_byte::Integer;
248+
version=VERSION, low_precedence_comma_in_brackets=false)
245249
io = IOBuffer(text_buf)
246250
seek(io, next_byte-1)
247251
lexer = Tokenize.Lexer(io)
@@ -264,44 +268,45 @@ mutable struct ParseStream
264268
Vector{TaggedRange}(),
265269
Vector{Diagnostic}(),
266270
0,
267-
ver)
271+
ver,
272+
low_precedence_comma_in_brackets)
268273
end
269274
end
270275

271-
function ParseStream(text::Vector{UInt8}, index::Integer=1; version=VERSION)
272-
ParseStream(text, text, index, version)
276+
function ParseStream(text::Vector{UInt8}, index::Integer=1; kws...)
277+
ParseStream(text, text, index; kws...)
273278
end
274279

275280
# Buffer with unknown owner. Not exactly recommended, but good for C interop
276-
function ParseStream(ptr::Ptr{UInt8}, len::Integer, index::Integer=1; version=VERSION)
277-
ParseStream(unsafe_wrap(Vector{UInt8}, ptr, len), nothing, index, version)
281+
function ParseStream(ptr::Ptr{UInt8}, len::Integer, index::Integer=1; kws...)
282+
ParseStream(unsafe_wrap(Vector{UInt8}, ptr, len), nothing, index; kws...)
278283
end
279284

280285
# Buffers originating from strings
281-
function ParseStream(text::String, index::Integer=1; version=VERSION)
286+
function ParseStream(text::String, index::Integer=1; kws...)
282287
ParseStream(unsafe_wrap(Vector{UInt8}, text),
283-
text, index, version)
288+
text, index; kws...)
284289
end
285-
function ParseStream(text::SubString, index::Integer=1; version=VERSION)
290+
function ParseStream(text::SubString, index::Integer=1; kws...)
286291
# See also IOBuffer(SubString("x"))
287292
ParseStream(unsafe_wrap(Vector{UInt8}, pointer(text), sizeof(text)),
288-
text, index, version)
293+
text, index; kws...)
289294
end
290-
function ParseStream(text::AbstractString, index::Integer=1; version=VERSION)
291-
ParseStream(String(text), index; version=version)
295+
function ParseStream(text::AbstractString, index::Integer=1; kws...)
296+
ParseStream(String(text), index; kws...)
292297
end
293298

294299
# IO-based cases
295-
function ParseStream(io::IOBuffer; version=VERSION)
296-
ParseStream(io.data, io, position(io)+1, version)
300+
function ParseStream(io::IOBuffer; kws...)
301+
ParseStream(io.data, io, position(io)+1; kws...)
297302
end
298-
function ParseStream(io::Base.GenericIOBuffer; version=VERSION)
303+
function ParseStream(io::Base.GenericIOBuffer; kws...)
299304
textbuf = unsafe_wrap(Vector{UInt8}, pointer(io.data), length(io.data))
300-
ParseStream(textbuf, io, position(io)+1, version)
305+
ParseStream(textbuf, io, position(io)+1; kws...)
301306
end
302-
function ParseStream(io::IO; version=VERSION)
307+
function ParseStream(io::IO; kws...)
303308
textbuf = read(io)
304-
ParseStream(textbuf, textbuf, 1, version)
309+
ParseStream(textbuf, textbuf, 1; kws...)
305310
end
306311

307312
function Base.show(io::IO, mime::MIME"text/plain", stream::ParseStream)

src/parser.jl

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ struct ParseState
2121
whitespace_newline::Bool
2222
# Enable parsing `where` with high precedence
2323
where_enabled::Bool
24-
# Comma special
24+
# Comma binds looser than macro calls (for use in brackets)
2525
low_precedence_comma::Bool
2626
end
2727

@@ -41,7 +41,8 @@ function ParseState(ps::ParseState; range_colon_enabled=nothing,
4141
end_symbol === nothing ? ps.end_symbol : end_symbol,
4242
whitespace_newline === nothing ? ps.whitespace_newline : whitespace_newline,
4343
where_enabled === nothing ? ps.where_enabled : where_enabled,
44-
low_precedence_comma === nothing ? ps.low_precedence_comma : low_precedence_comma)
44+
low_precedence_comma === nothing ? ps.low_precedence_comma :
45+
low_precedence_comma && ps.stream.low_precedence_comma_in_brackets)
4546
end
4647

4748
# Functions to change parse state
@@ -2937,7 +2938,8 @@ function parse_cat(ps::ParseState, closer, end_is_symbol)
29372938
space_sensitive=true,
29382939
where_enabled=true,
29392940
whitespace_newline=false,
2940-
for_generator=true)
2941+
for_generator=true,
2942+
low_precedence_comma=true)
29412943
k = peek(ps, skip_newlines=true)
29422944
mark = position(ps)
29432945
if k == closer

src/parser_api.jl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,12 @@ function parse!(::Type{TreeType}, io::IO;
7676
end
7777

7878
function _parse(rule::Symbol, need_eof::Bool, ::Type{T}, text, index=1; version=VERSION,
79+
low_precedence_comma_in_brackets=false,
7980
ignore_trivia=true, filename=nothing, first_line=1, ignore_errors=false,
8081
ignore_warnings=ignore_errors, kws...) where {T}
81-
stream = ParseStream(text, index; version=version)
82+
stream = ParseStream(text, index;
83+
version=version,
84+
low_precedence_comma_in_brackets=low_precedence_comma_in_brackets)
8285
if ignore_trivia && rule != :all
8386
bump_trivia(stream, skip_newlines=true)
8487
empty!(stream)

test/parser.jl

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
"""
22
Parse string to SyntaxNode tree and show as an sexpression
33
"""
4-
function parse_to_sexpr_str(production, code::AbstractString; v=v"1.6", expr=false)
5-
stream = ParseStream(code, version=v)
4+
function parse_to_sexpr_str(production, code::AbstractString; v=v"1.6", expr=false, kws...)
5+
stream = ParseStream(code; version=v, kws...)
66
production(ParseState(stream))
77
JuliaSyntax.validate_tokens(stream)
88
t = build_tree(GreenNode, stream, wrap_toplevel_as_kind=K"None")
@@ -430,6 +430,13 @@ tests = [
430430
"x\"s\"2" => """(macrocall @x_str (string-r "s") 2)"""
431431
"x\"s\"10.0" => """(macrocall @x_str (string-r "s") 10.0)"""
432432
#
433+
"f(@x a, b)" => "(call f (macrocall @x (tuple a b)))"
434+
((low_precedence_comma_in_brackets=true,), "f(@x a, b)") =>
435+
"(call f (macrocall @x a) b)"
436+
((low_precedence_comma_in_brackets=true,), "(@x a, b)") =>
437+
"(tuple-p (macrocall @x a) b)"
438+
((low_precedence_comma_in_brackets=true,), "[@x a, b]") =>
439+
"(vect (macrocall @x a) b)"
433440
],
434441
JuliaSyntax.parse_resword => [
435442
# In normal_context

0 commit comments

Comments
 (0)