Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ version = "1.0.0-DEV"
Serialization = "1.0"
julia = "1.0"

[deps]

[extras]
Logging = "56ddb016-857b-54e1-b83d-db4d58db5568"
Serialization = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
Expand Down
2 changes: 1 addition & 1 deletion src/parse_stream.jl
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ function ParseStream(text::String, index::Integer=1; version=VERSION)
ParseStream(unsafe_wrap(Vector{UInt8}, text),
text, index, version)
end
function ParseStream(text::SubString, index::Integer=1; version=VERSION)
function ParseStream(text::SubString{String}, index::Integer=1; version=VERSION)
# See also IOBuffer(SubString("x"))
ParseStream(unsafe_wrap(Vector{UInt8}, pointer(text), sizeof(text)),
text, index, version)
Expand Down
81 changes: 80 additions & 1 deletion test/parse_stream.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ using JuliaSyntax: ParseStream,
peek, peek_token,
bump, bump_trivia, bump_invisible,
emit, emit_diagnostic, TRIVIA_FLAG, INFIX_FLAG,
ParseStreamPosition, first_child_position, last_child_position
ParseStreamPosition, first_child_position, last_child_position,
parsestmt

# Here we manually issue parse events in the order the Julia parser would issue
# them
Expand Down Expand Up @@ -147,3 +148,81 @@ end
@test first_child_position(st, position(st)) == ParseStreamPosition(4, 1)
@test last_child_position(st, position(st)) == ParseStreamPosition(7, 2)
end

# This is coppied from InlineStrings.jl instead of depending
# on InlineStrings for compat with Julia 1.2 and earlier:
primitive type String3 <: AbstractString 4*8 end
Base.ncodeunits(x::String3) = Int(Base.trunc_int(UInt8, x))
function Base.codeunit(x::T, i::Int) where {T <: String3}
@boundscheck checkbounds(Bool, x, i) || throw(BoundsError(x, i))
return Base.trunc_int(UInt8, Base.lshr_int(x, 8 * (sizeof(T) - i)))
end
function Base.String(x::T) where {T <: String3}
len = ncodeunits(x)
out = Base._string_n(len)
ref = Ref{T}(_bswap(x))
GC.@preserve ref out begin
ptr = convert(Ptr{UInt8}, Base.unsafe_convert(Ptr{T}, ref))
unsafe_copyto!(pointer(out), ptr, len)
end
return out
end
function Base.isvalid(x::String3, i::Int)
@boundscheck checkbounds(Bool, x, i) || throw(BoundsError(x, i))
return @inbounds thisind(x, i) == i
end
function Base.thisind(s::String3, i::Int)
i == 0 && return 0
n = ncodeunits(s)
i == n + 1 && return i
@boundscheck Base.between(i, 1, n) || throw(BoundsError(s, i))
@inbounds b = codeunit(s, i)
(b & 0xc0 == 0x80) & (i-1 > 0) || return i
@inbounds b = codeunit(s, i-1)
Base.between(b, 0b11000000, 0b11110111) && return i-1
(b & 0xc0 == 0x80) & (i-2 > 0) || return i
@inbounds b = codeunit(s, i-2)
Base.between(b, 0b11100000, 0b11110111) && return i-2
(b & 0xc0 == 0x80) & (i-3 > 0) || return i
@inbounds b = codeunit(s, i-3)
Base.between(b, 0b11110000, 0b11110111) && return i-3
return i
end
Base.@propagate_inbounds function Base.iterate(s::String3, i::Int=firstindex(s))
(i % UInt) - 1 < ncodeunits(s) || return nothing
b = @inbounds codeunit(s, i)
u = UInt32(b) << 24
Base.between(b, 0x80, 0xf7) || return reinterpret(Char, u), i+1
return iterate_continued(s, i, u)
end
function iterate_continued(s::String3, i::Int, u::UInt32)
u < 0xc0000000 && (i += 1; @goto ret)
n = ncodeunits(s)
# first continuation byte
(i += 1) > n && @goto ret
@inbounds b = codeunit(s, i)
b & 0xc0 == 0x80 || @goto ret
u |= UInt32(b) << 16
# second continuation byte
((i += 1) > n) | (u < 0xe0000000) && @goto ret
@inbounds b = codeunit(s, i)
b & 0xc0 == 0x80 || @goto ret
u |= UInt32(b) << 8
# third continuation byte
((i += 1) > n) | (u < 0xf0000000) && @goto ret
@inbounds b = codeunit(s, i)
b & 0xc0 == 0x80 || @goto ret
u |= UInt32(b); i += 1
@label ret
return reinterpret(Char, u), i
end
# End coppied from InlineStrings.jl

@testset "SubString{String3} (issue #505)" begin
x = reinterpret(String3, 0x31203203)
@test x == "1 2"
y = split(x)[1]
@test y == "1"
@test ParseStream(y) isa ParseStream
@test parsestmt(Expr, y) == parsestmt(Expr, "1")
end