Skip to content

Commit d9297c9

Browse files
committed
Parser optimization: Reuse position arrays, outline error code paths
1 parent 116ee31 commit d9297c9

File tree

2 files changed

+28
-6
lines changed

2 files changed

+28
-6
lines changed

src/parse_stream.jl

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,8 @@ mutable struct ParseStream
186186
lexer::Tokenize.Lexers.Lexer{IOBuffer}
187187
# Lookahead buffer for already lexed tokens
188188
lookahead::Vector{SyntaxToken}
189+
# Pool of stream positions for use as working space in parsing
190+
position_pool::Vector{Vector{ParseStreamPosition}}
189191
# Parser output as an ordered sequence of ranges, parent nodes after children.
190192
ranges::Vector{TaggedRange}
191193
# Parsing diagnostics (errors/warnings etc)
@@ -210,6 +212,7 @@ mutable struct ParseStream
210212
# like an acceptable tradeoff.
211213
ver = (version.major, version.minor)
212214
new(text_buf, text_root, lexer,
215+
Vector{Vector{ParseStreamPosition}}(),
213216
Vector{SyntaxToken}(),
214217
Vector{TaggedRange}(),
215218
Vector{Diagnostic}(),
@@ -268,6 +271,19 @@ function show_diagnostics(io::IO, stream::ParseStream, code)
268271
show_diagnostics(io, stream.diagnostics, code)
269272
end
270273

274+
# We manage a pool of stream positions as parser working space
275+
function acquire_positions(stream)
276+
if isempty(stream.position_pool)
277+
return Vector{ParseStreamPosition}()
278+
end
279+
pop!(stream.position_pool)
280+
end
281+
282+
function release_positions(stream, positions)
283+
empty!(positions)
284+
push!(stream.position_pool, positions)
285+
end
286+
271287
#-------------------------------------------------------------------------------
272288
# Stream input interface - the peek_* family of functions
273289

@@ -311,6 +327,11 @@ function _lookahead_index(stream::ParseStream, n::Integer, skip_newlines::Bool)
311327
end
312328
end
313329

330+
@noinline function _parser_stuck_error(stream)
331+
# Optimization: emit unlikely errors in a separate function
332+
error("The parser seems stuck at byte $(stream.next_byte)")
333+
end
334+
314335
"""
315336
peek(stream [, n=1]; skip_newlines=false)
316337
@@ -333,7 +354,7 @@ function peek_token(stream::ParseStream, n::Integer=1;
333354
skip_newlines=false, skip_whitespace=true)
334355
stream.peek_count += 1
335356
if stream.peek_count > 100_000
336-
error("The parser seems stuck at byte $(stream.next_byte)")
357+
_parser_stuck_error(stream)
337358
end
338359
i = _lookahead_index(stream, n, skip_newlines)
339360
if !skip_whitespace

src/parser.jl

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2940,8 +2940,8 @@ function parse_brackets(after_parse::Function,
29402940
space_sensitive=false,
29412941
where_enabled=true,
29422942
whitespace_newline=true)
2943-
params_marks = ParseStreamPosition[]
2944-
eq_positions = ParseStreamPosition[]
2943+
params_marks = acquire_positions(ps.stream)
2944+
eq_positions = acquire_positions(ps.stream)
29452945
last_eq_before_semi = 0
29462946
num_subexprs = 0
29472947
num_semis = 0
@@ -3021,6 +3021,8 @@ function parse_brackets(after_parse::Function,
30213021
emit(ps, mark, K"parameters")
30223022
end
30233023
end
3024+
release_positions(ps.stream, params_marks)
3025+
release_positions(ps.stream, eq_positions)
30243026
end
30253027

30263028
is_indentation(b::UInt8) = (b == UInt8(' ') || b == UInt8('\t'))
@@ -3036,9 +3038,7 @@ function parse_string(ps::ParseState, raw::Bool)
30363038
string_chunk_kind = delim_k in KSet`" """` ? K"String" : K"CmdString"
30373039
indent_ref_i = 0
30383040
indent_ref_len = typemax(Int)
3039-
if triplestr
3040-
indent_chunks = Vector{ParseStreamPosition}()
3041-
end
3041+
indent_chunks = acquire_positions(ps.stream)
30423042
buf = textbuf(ps)
30433043
str_flags = (triplestr ? TRIPLE_STRING_FLAG : EMPTY_FLAGS) |
30443044
(raw ? RAW_STRING_FLAG : EMPTY_FLAGS)
@@ -3191,6 +3191,7 @@ function parse_string(ps::ParseState, raw::Bool)
31913191
end
31923192
end
31933193
end
3194+
release_positions(ps.stream, indent_chunks)
31943195
if had_end_delim
31953196
if n_valid_chunks == 0
31963197
# Empty strings, or empty after triple quoted processing

0 commit comments

Comments
 (0)