Skip to content

Commit 1515d8f

Browse files
authored
Fix for detecting call heads in function signatures (#247)
Discovered parsing packages in General
1 parent e55e238 commit 1515d8f

File tree

3 files changed

+22
-10
lines changed

3 files changed

+22
-10
lines changed

src/parse_stream.jl

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -527,20 +527,23 @@ Retroactively inspecting or modifying the parser's output can be confusing, so
527527
using this function should be avoided where possible.
528528
"""
529529
function peek_behind(stream::ParseStream, pos::ParseStreamPosition)
530-
if token_is_last(stream, pos) && !isempty(stream.tokens)
530+
if token_is_last(stream, pos) && pos.token_index > 0
531531
t = stream.tokens[pos.token_index]
532532
return (kind=kind(t),
533533
flags=flags(t),
534534
orig_kind=t.orig_kind,
535535
is_leaf=true)
536-
elseif !isempty(stream.ranges)
536+
elseif !isempty(stream.ranges) && pos.range_index > 0
537537
r = stream.ranges[pos.range_index]
538538
return (kind=kind(r),
539539
flags=flags(r),
540540
orig_kind=K"None",
541541
is_leaf=false)
542542
else
543-
internal_error("Can't peek behind at start of stream")
543+
return (kind=K"None",
544+
flags=EMPTY_FLAGS,
545+
orig_kind=K"None",
546+
is_leaf=true)
544547
end
545548
end
546549

@@ -585,7 +588,11 @@ function first_child_position(stream::ParseStream, pos::ParseStreamPosition)
585588
end
586589
end
587590

588-
function peek_behind(stream::ParseStream; skip_trivia::Bool=true)
591+
# Get last position in stream "of interest", skipping
592+
# * parens nodes
593+
# * deleted tokens (TOMBSTONE)
594+
# * whitespace (if skip_trivia=true)
595+
function peek_behind_pos(stream::ParseStream; skip_trivia::Bool=true)
589596
token_index = lastindex(stream.tokens)
590597
range_index = lastindex(stream.ranges)
591598
while range_index >= firstindex(stream.ranges) &&
@@ -601,11 +608,11 @@ function peek_behind(stream::ParseStream; skip_trivia::Bool=true)
601608
end
602609
token_index -= 1
603610
end
604-
if token_index > 0
605-
return peek_behind(stream, ParseStreamPosition(token_index, range_index))
606-
else
607-
internal_error("Can't peek behind at start of stream")
608-
end
611+
return ParseStreamPosition(token_index, range_index)
612+
end
613+
614+
function peek_behind(stream::ParseStream; skip_trivia::Bool=true)
615+
peek_behind(stream, peek_behind_pos(stream; skip_trivia=skip_trivia))
609616
end
610617

611618
#-------------------------------------------------------------------------------

src/parser.jl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ function peek_behind(ps::ParseState, args...; kws...)
8080
peek_behind(ps.stream, args...; kws...)
8181
end
8282

83+
function peek_behind_pos(ps::ParseState, args...; kws...)
84+
peek_behind_pos(ps.stream, args...; kws...)
85+
end
86+
8387
function bump(ps::ParseState, flags=EMPTY_FLAGS; skip_newlines=nothing, kws...)
8488
skip_nl = isnothing(skip_newlines) ? ps.whitespace_newline : skip_newlines
8589
bump(ps.stream, flags; skip_newlines=skip_nl, kws...)
@@ -306,7 +310,7 @@ end
306310
# The expression is a call after stripping `where` and `::`
307311
function was_eventually_call(ps::ParseState)
308312
stream = ps.stream
309-
p = position(ps)
313+
p = peek_behind_pos(ps)
310314
while true
311315
b = peek_behind(stream, p)
312316
if b.kind == K"call"

test/parser.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,7 @@ tests = [
589589
"function (f() where T) where U end" => "(function (where (parens (where (call f) T)) U) (block))"
590590
"function (f()::S) end"=> "(function (parens (::-i (call f) S)) (block))" => Expr(:function, Expr(:(::), Expr(:call, :f), :S), Expr(:block))
591591
"function ((f()::S) where T) end" => "(function (parens (where (parens (::-i (call f) S)) T)) (block))"
592+
"function (x*y ) end" => "(function (parens (call-i x * y)) (block))"
592593
# body
593594
"function f() \n a \n b end" => "(function (call f) (block a b))"
594595
"function f() end" => "(function (call f) (block))"

0 commit comments

Comments
 (0)