Add: julia-0.6.2
Former-commit-id: ccc667cf67d569f3fb3df39aa57c2134755a7551
This commit is contained in:
241
julia-0.6.2/share/julia/base/parse.jl
Normal file
241
julia-0.6.2/share/julia/base/parse.jl
Normal file
@@ -0,0 +1,241 @@
|
||||
# This file is a part of Julia. License is MIT: https://julialang.org/license
|
||||
|
||||
import Base.Checked: add_with_overflow, mul_with_overflow
|
||||
|
||||
## string to integer functions ##
|
||||
|
||||
function parse(::Type{T}, c::Char, base::Integer=36) where T<:Integer
|
||||
a::Int = (base <= 36 ? 10 : 36)
|
||||
2 <= base <= 62 || throw(ArgumentError("invalid base: base must be 2 ≤ base ≤ 62, got $base"))
|
||||
d = '0' <= c <= '9' ? c-'0' :
|
||||
'A' <= c <= 'Z' ? c-'A'+10 :
|
||||
'a' <= c <= 'z' ? c-'a'+a : throw(ArgumentError("invalid digit: $(repr(c))"))
|
||||
d < base || throw(ArgumentError("invalid base $base digit $(repr(c))"))
|
||||
convert(T, d)
|
||||
end
|
||||
|
||||
function parseint_next(s::AbstractString, startpos::Int, endpos::Int)
|
||||
(0 < startpos <= endpos) || (return Char(0), 0, 0)
|
||||
j = startpos
|
||||
c, startpos = next(s,startpos)
|
||||
c, startpos, j
|
||||
end
|
||||
|
||||
function parseint_preamble(signed::Bool, base::Int, s::AbstractString, startpos::Int, endpos::Int)
|
||||
c, i, j = parseint_next(s, startpos, endpos)
|
||||
|
||||
while isspace(c)
|
||||
c, i, j = parseint_next(s,i,endpos)
|
||||
end
|
||||
(j == 0) && (return 0, 0, 0)
|
||||
|
||||
sgn = 1
|
||||
if signed
|
||||
if c == '-' || c == '+'
|
||||
(c == '-') && (sgn = -1)
|
||||
c, i, j = parseint_next(s,i,endpos)
|
||||
end
|
||||
end
|
||||
|
||||
while isspace(c)
|
||||
c, i, j = parseint_next(s,i,endpos)
|
||||
end
|
||||
(j == 0) && (return 0, 0, 0)
|
||||
|
||||
if base == 0
|
||||
if c == '0' && !done(s,i)
|
||||
c, i = next(s,i)
|
||||
base = c=='b' ? 2 : c=='o' ? 8 : c=='x' ? 16 : 10
|
||||
if base != 10
|
||||
c, i, j = parseint_next(s,i,endpos)
|
||||
end
|
||||
else
|
||||
base = 10
|
||||
end
|
||||
end
|
||||
return sgn, base, j
|
||||
end
|
||||
|
||||
function tryparse_internal(::Type{T}, s::AbstractString, startpos::Int, endpos::Int, base_::Integer, raise::Bool) where T<:Integer
|
||||
_n = Nullable{T}()
|
||||
sgn, base, i = parseint_preamble(T<:Signed, Int(base_), s, startpos, endpos)
|
||||
if sgn == 0 && base == 0 && i == 0
|
||||
raise && throw(ArgumentError("input string is empty or only contains whitespace"))
|
||||
return _n
|
||||
end
|
||||
if !(2 <= base <= 62)
|
||||
raise && throw(ArgumentError("invalid base: base must be 2 ≤ base ≤ 62, got $base"))
|
||||
return _n
|
||||
end
|
||||
if i == 0
|
||||
raise && throw(ArgumentError("premature end of integer: $(repr(SubString(s,startpos,endpos)))"))
|
||||
return _n
|
||||
end
|
||||
c, i = parseint_next(s,i,endpos)
|
||||
if i == 0
|
||||
raise && throw(ArgumentError("premature end of integer: $(repr(SubString(s,startpos,endpos)))"))
|
||||
return _n
|
||||
end
|
||||
|
||||
base = convert(T,base)
|
||||
m::T = div(typemax(T)-base+1,base)
|
||||
n::T = 0
|
||||
a::Int = base <= 36 ? 10 : 36
|
||||
while n <= m
|
||||
d::T = '0' <= c <= '9' ? c-'0' :
|
||||
'A' <= c <= 'Z' ? c-'A'+10 :
|
||||
'a' <= c <= 'z' ? c-'a'+a : base
|
||||
if d >= base
|
||||
raise && throw(ArgumentError("invalid base $base digit $(repr(c)) in $(repr(SubString(s,startpos,endpos)))"))
|
||||
return _n
|
||||
end
|
||||
n *= base
|
||||
n += d
|
||||
if i > endpos
|
||||
n *= sgn
|
||||
return Nullable{T}(n)
|
||||
end
|
||||
c, i = next(s,i)
|
||||
isspace(c) && break
|
||||
end
|
||||
(T <: Signed) && (n *= sgn)
|
||||
while !isspace(c)
|
||||
d::T = '0' <= c <= '9' ? c-'0' :
|
||||
'A' <= c <= 'Z' ? c-'A'+10 :
|
||||
'a' <= c <= 'z' ? c-'a'+a : base
|
||||
if d >= base
|
||||
raise && throw(ArgumentError("invalid base $base digit $(repr(c)) in $(repr(SubString(s,startpos,endpos)))"))
|
||||
return _n
|
||||
end
|
||||
(T <: Signed) && (d *= sgn)
|
||||
|
||||
n, ov_mul = mul_with_overflow(n, base)
|
||||
n, ov_add = add_with_overflow(n, d)
|
||||
if ov_mul | ov_add
|
||||
raise && throw(OverflowError())
|
||||
return _n
|
||||
end
|
||||
(i > endpos) && return Nullable{T}(n)
|
||||
c, i = next(s,i)
|
||||
end
|
||||
while i <= endpos
|
||||
c, i = next(s,i)
|
||||
if !isspace(c)
|
||||
raise && throw(ArgumentError("extra characters after whitespace in $(repr(SubString(s,startpos,endpos)))"))
|
||||
return _n
|
||||
end
|
||||
end
|
||||
return Nullable{T}(n)
|
||||
end
|
||||
|
||||
function tryparse_internal(::Type{Bool}, sbuff::Union{String,SubString},
|
||||
startpos::Int, endpos::Int, base::Integer, raise::Bool)
|
||||
if isempty(sbuff)
|
||||
raise && throw(ArgumentError("input string is empty"))
|
||||
return Nullable{Bool}()
|
||||
end
|
||||
|
||||
orig_start = startpos
|
||||
orig_end = endpos
|
||||
|
||||
# Ignore leading and trailing whitespace
|
||||
while isspace(sbuff[startpos]) && startpos <= endpos
|
||||
startpos = nextind(sbuff, startpos)
|
||||
end
|
||||
while isspace(sbuff[endpos]) && endpos >= startpos
|
||||
endpos = prevind(sbuff, endpos)
|
||||
end
|
||||
|
||||
len = endpos - startpos + 1
|
||||
p = pointer(sbuff) + startpos - 1
|
||||
(len == 4) && (0 == ccall(:memcmp, Int32, (Ptr{UInt8}, Ptr{UInt8}, UInt),
|
||||
p, "true", 4)) && (return Nullable(true))
|
||||
(len == 5) && (0 == ccall(:memcmp, Int32, (Ptr{UInt8}, Ptr{UInt8}, UInt),
|
||||
p, "false", 5)) && (return Nullable(false))
|
||||
|
||||
if raise
|
||||
substr = SubString(sbuff, orig_start, orig_end) # show input string in the error to avoid confusion
|
||||
if all(isspace, substr)
|
||||
throw(ArgumentError("input string only contains whitespace"))
|
||||
else
|
||||
throw(ArgumentError("invalid Bool representation: $(repr(substr))"))
|
||||
end
|
||||
end
|
||||
return Nullable{Bool}()
|
||||
end
|
||||
|
||||
@inline function check_valid_base(base)
|
||||
if 2 <= base <= 62
|
||||
return base
|
||||
end
|
||||
throw(ArgumentError("invalid base: base must be 2 ≤ base ≤ 62, got $base"))
|
||||
end
|
||||
|
||||
tryparse(::Type{T}, s::AbstractString, base::Integer) where {T<:Integer} =
|
||||
tryparse_internal(T, s, start(s), endof(s), check_valid_base(base), false)
|
||||
tryparse(::Type{T}, s::AbstractString) where {T<:Integer} =
|
||||
tryparse_internal(T, s, start(s), endof(s), 0, false)
|
||||
|
||||
function parse(::Type{T}, s::AbstractString, base::Integer) where T<:Integer
|
||||
get(tryparse_internal(T, s, start(s), endof(s), check_valid_base(base), true))
|
||||
end
|
||||
|
||||
function parse(::Type{T}, s::AbstractString) where T<:Integer
|
||||
get(tryparse_internal(T, s, start(s), endof(s), 0, true)) # Zero means, "figure it out"
|
||||
end
|
||||
|
||||
|
||||
## string to float functions ##
|
||||
|
||||
tryparse(::Type{Float64}, s::String) = ccall(:jl_try_substrtod, Nullable{Float64}, (Ptr{UInt8},Csize_t,Csize_t), s, 0, sizeof(s))
|
||||
tryparse(::Type{Float64}, s::SubString{String}) = ccall(:jl_try_substrtod, Nullable{Float64}, (Ptr{UInt8},Csize_t,Csize_t), s.string, s.offset, s.endof)
|
||||
|
||||
tryparse(::Type{Float32}, s::String) = ccall(:jl_try_substrtof, Nullable{Float32}, (Ptr{UInt8},Csize_t,Csize_t), s, 0, sizeof(s))
|
||||
tryparse(::Type{Float32}, s::SubString{String}) = ccall(:jl_try_substrtof, Nullable{Float32}, (Ptr{UInt8},Csize_t,Csize_t), s.string, s.offset, s.endof)
|
||||
|
||||
tryparse(::Type{T}, s::AbstractString) where {T<:Union{Float32,Float64}} = tryparse(T, String(s))
|
||||
|
||||
tryparse(::Type{Float16}, s::AbstractString) = convert(Nullable{Float16}, tryparse(Float32, s))
|
||||
|
||||
function parse(::Type{T}, s::AbstractString) where T<:AbstractFloat
|
||||
result = tryparse(T, s)
|
||||
if isnull(result)
|
||||
throw(ArgumentError("cannot parse $(repr(s)) as $T"))
|
||||
end
|
||||
return unsafe_get(result)
|
||||
end
|
||||
|
||||
float(x::AbstractString) = parse(Float64,x)
|
||||
|
||||
float(a::AbstractArray{<:AbstractString}) = map!(float, similar(a,typeof(float(0))), a)
|
||||
|
||||
## interface to parser ##
|
||||
|
||||
function parse(str::AbstractString, pos::Int; greedy::Bool=true, raise::Bool=true)
|
||||
# pos is one based byte offset.
|
||||
# returns (expr, end_pos). expr is () in case of parse error.
|
||||
bstr = String(str)
|
||||
ex, pos = ccall(:jl_parse_string, Any,
|
||||
(Ptr{UInt8}, Csize_t, Int32, Int32),
|
||||
bstr, sizeof(bstr), pos-1, greedy ? 1:0)
|
||||
if raise && isa(ex,Expr) && ex.head === :error
|
||||
throw(ParseError(ex.args[1]))
|
||||
end
|
||||
if ex === ()
|
||||
raise && throw(ParseError("end of input"))
|
||||
ex = Expr(:error, "end of input")
|
||||
end
|
||||
return ex, pos+1 # C is zero-based, Julia is 1-based
|
||||
end
|
||||
|
||||
function parse(str::AbstractString; raise::Bool=true)
|
||||
ex, pos = parse(str, 1, greedy=true, raise=raise)
|
||||
if isa(ex,Expr) && ex.head === :error
|
||||
return ex
|
||||
end
|
||||
if !done(str, pos)
|
||||
raise && throw(ParseError("extra token after end of expression"))
|
||||
return Expr(:error, "extra token after end of expression")
|
||||
end
|
||||
return ex
|
||||
end
|
||||
Reference in New Issue
Block a user