diff --git a/base/client.jl b/base/client.jl index 32abab9309556..e883dbcfd2ba1 100644 --- a/base/client.jl +++ b/base/client.jl @@ -154,10 +154,7 @@ function eval_user_input(errio, @nospecialize(ast), show_value::Bool) end function _parse_input_line_core(s::String, filename::String) - JL_PARSE_ALL = 3 - ex,_ = ccall(:jl_parse, Any, - (Ptr{UInt8}, Csize_t, Ptr{UInt8}, Csize_t, Csize_t, Cint), - s, sizeof(s), filename, sizeof(filename), 0, JL_PARSE_ALL) + ex = Meta.parseall(s, filename=filename) if ex isa Expr && ex.head === :toplevel if isempty(ex.args) return nothing diff --git a/base/meta.jl b/base/meta.jl index b904335dd0100..8bb02bb7e4509 100644 --- a/base/meta.jl +++ b/base/meta.jl @@ -149,6 +149,24 @@ struct ParseError <: Exception msg::AbstractString end +function _jl_parse(text::AbstractString, filename::AbstractString, + pos::Integer, rule::Integer) + if pos < 1 || pos > ncodeunits(text) + 1 + throw(BoundsError(text, pos)) + end + # Technically only need pointers to UTF-8 buffers here. For now converting + # to a plain String is the easy way to ensure that. + filename = String(filename) + text = String(text) + # Call into the parser which can be replaced globally during bootstrap with + # jl_set_parser + ex,pos = ccall(:jl_parse, Any, + (Ptr{UInt8}, Csize_t, Ptr{UInt8}, Csize_t, Csize_t, Cint), + text, sizeof(text), filename, sizeof(filename), pos-1, rule) + # internally, pos is a zero-based byte offset - convert back. + ex, pos+1 +end + """ parse(str, start; greedy=true, raise=true, depwarn=true) @@ -171,25 +189,17 @@ julia> Meta.parse("x = 3, y = 5", 5) """ function parse(str::AbstractString, pos::Integer; greedy::Bool=true, raise::Bool=true, depwarn::Bool=true) - if pos < 1 || pos > ncodeunits(str) + 1 - throw(BoundsError(str, pos)) - end filename = "none" JL_PARSE_ATOM = 1 JL_PARSE_STATEMENT = 2 rule = greedy ? JL_PARSE_STATEMENT : JL_PARSE_ATOM # For now, assume all parser warnings are depwarns # TODO: remove parser-depwarn; parser no longer emits warnings. - ex, pos = with_logger(depwarn ? current_logger() : NullLogger()) do - ccall(:jl_parse, Any, - (Ptr{UInt8}, Csize_t, Ptr{UInt8}, Csize_t, Csize_t, Cint), - str, sizeof(str), filename, sizeof(filename), pos-1, rule) - end + ex, pos = _jl_parse(str, "none", pos, rule) if raise && isa(ex,Expr) && ex.head === :error throw(ParseError(ex.args[1])) end - # internal pos is zero-based byte offset - return ex, pos+1 + return ex, pos end """ @@ -229,6 +239,17 @@ function parse(str::AbstractString; raise::Bool=true, depwarn::Bool=true) return ex end +function parseatom(text::AbstractString, pos::Integer; filename="none") + JL_PARSE_ATOM = 1 + return _jl_parse(text, filename, pos, JL_PARSE_ATOM) +end + +function parseall(text::AbstractString; filename="none") + JL_PARSE_ALL = 3 + ex,_ = _jl_parse(text, filename, 1, JL_PARSE_ALL) + return ex +end + """ partially_inline!(code::Vector{Any}, slot_replacements::Vector{Any}, type_signature::Type{<:Tuple}, static_param_values::Vector{Any},