|
| 1 | +# TODO use traits for hasmethod checks |
| 2 | + |
| 3 | +# Scalar parsers |
| 4 | + |
| 5 | +# content input |
| 6 | +""" |
| 7 | + noedparse(type::Type, node) |
| 8 | + nodeparse(type::Type, content) |
| 9 | + noedparse(::Type{Vector{T}}, nodes) |
| 10 | + nodeparse(::Type{Vector{T}}, contents) |
| 11 | +Parses a node content with the specidied type |
| 12 | +""" |
| 13 | +nodeparse(type::Type{<:Number}, content::String) = parse(type, content) |
| 14 | +nodeparse(type::Type{<:AbstractString}, content::String) = content |
| 15 | +function nodeparse(type::Type, content::String) |
| 16 | + # TODO: better specialized method detection |
| 17 | + # https://julialang.slack.com/archives/C6A044SQH/p1578442480438100 |
| 18 | + if hasmethod(type, Tuple{String}) && Core.Compiler.return_type(type, Tuple{Node})=== Union{} |
| 19 | + return type(content) |
| 20 | + elseif hasmethod(convert, Tuple{String, type}) |
| 21 | + return convert(type, content) |
| 22 | + elseif hasmethod(parse, Tuple{type, String}) |
| 23 | + return parse(type, content) |
| 24 | + else |
| 25 | + error("Could not parse a String as type $type") |
| 26 | + end |
| 27 | +end |
| 28 | + |
| 29 | +# elm input |
| 30 | +nodeparse(type::Type{<:Union{Number, AbstractString}}, elm::Node) = nodeparse(type, elm.content) |
| 31 | +function nodeparse(type::Type, elm::Node) |
| 32 | + content = elm.content |
| 33 | + if hasmethod(type, Tuple{String}) && Core.Compiler.return_type(type, Tuple{Node})=== Union{} |
| 34 | + return type(content) |
| 35 | + elseif hasmethod(convert, Tuple{String, type}) |
| 36 | + return convert(type, content) |
| 37 | + elseif hasmethod(parse, Tuple{type, String}) |
| 38 | + return parse(type, content) |
| 39 | + else |
| 40 | + # should be the last to avoid invoking generic methods |
| 41 | + return type(elm) |
| 42 | + end |
| 43 | +end |
| 44 | + |
| 45 | +# Vector parsers |
| 46 | +# both elm and content input |
| 47 | + |
| 48 | +# TODO slow for other than String|Number but compact |
| 49 | +numorstr(::Nothing) = [Number, AbstractString] |
| 50 | +@transform function nodeparse(type::Type{<:numorstr()}, elmsOrContents::Vector{Node}) |
| 51 | + return nodeparse.(type, elmsOrContents) |
| 52 | +end |
| 53 | +@transform function nodeparse(type::Type{<:numorstr()}, elmsOrContents::Vector{String}) |
| 54 | + return nodeparse.(type, elmsOrContents) |
| 55 | +end |
| 56 | +# TODO Faster code, but has redundancy: |
| 57 | + |
| 58 | +function nodeparse(::Type{T}, contents::Vector{String}) where {T} |
| 59 | + elms_typed = Vector{T}(undef, length(contents)) |
| 60 | + i = 1 |
| 61 | + if hasmethod(type, Tuple{String}) && Core.Compiler.return_type(type, Tuple{Node})=== Union{} |
| 62 | + for content in contents |
| 63 | + elms_typed[i] = type(content) |
| 64 | + i+=1 |
| 65 | + end |
| 66 | + elseif hasmethod(convert, Tuple{String, type}) |
| 67 | + for content in contents |
| 68 | + elms_typed[i] = convert(type, content) |
| 69 | + i+=1 |
| 70 | + end |
| 71 | + elseif hasmethod(parse, Tuple{type, String}) |
| 72 | + for content in contents |
| 73 | + elms_typed[i] = parse(type, content) |
| 74 | + i+=1 |
| 75 | + end |
| 76 | + else |
| 77 | + error("Could not parse a String as type $type") |
| 78 | + end |
| 79 | + return elms_typed |
| 80 | +end |
| 81 | + |
| 82 | +function nodeparse(type::Type{T}, elms::Vector{Node}) where {T} |
| 83 | + elms_typed = Vector{T}(undef, length(elms)) |
| 84 | + i = 1 |
| 85 | + if hasmethod(type, Tuple{String}) && Core.Compiler.return_type(type, Tuple{Node})=== Union{} |
| 86 | + for elm in elms |
| 87 | + elms_typed[i] = type(elm.content) |
| 88 | + i+=1 |
| 89 | + end |
| 90 | + elseif hasmethod(convert, Tuple{String, type}) |
| 91 | + for elm in elms |
| 92 | + elms_typed[i] = convert(type, elm.content) |
| 93 | + i+=1 |
| 94 | + end |
| 95 | + elseif hasmethod(parse, Tuple{type, String}) |
| 96 | + for elm in elms |
| 97 | + elms_typed[i] = parse(type, elm.content) |
| 98 | + i+=1 |
| 99 | + end |
| 100 | + else |
| 101 | + # should be the last to avoid invoking generic methods |
| 102 | + for elm in elms |
| 103 | + elms_typed[i] = type(elm) |
| 104 | + i+=1 |
| 105 | + end |
| 106 | + end |
| 107 | + return elms_typed |
| 108 | +end |
0 commit comments