all repos — min @ ef23f36f41ba9c16c3fbec4a5e0bd31944e4ba16

A small but practical concatenative programming language.

minpkg/lib/min_xml.nim

 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
import 
    std/xmlparser,
    std/xmltree,
    std/parsexml,
    std/strtabs,
    std/critbits,
    nimquery
import
    ../core/parser,
    ../core/value,
    ../core/interpreter,
    ../core/utils


let xmltypes = "dict:xml-text|dict:xml-verbatim-text|xml-element|xml-cdata|xml-comment"

proc newXDict(i: In, xml: XmlNode): MinValue =
    result = newDict(i.scope)
    case xml.kind:
        of xnText:
            result.objType = "xml-text"
            i.dset(result, "text", xml.text.newVal)
        of xnVerbatimText:
            result.objType = "xml-verbatim-text"
            i.dset(result, "text", xml.text.newVal)
        of xnElement:
            result.objType = "xml-element"
            i.dset(result, "tag", xml.tag.newVal)
            var children = newSeq[MinValue](0)
            var attributes = newDict(i.scope)
            for child in xml.items:
                children.add i.newXDict(child)
            i.dset(result, "children", children.newVal)
            for attr in xml.attrs.pairs:
                i.dset(attributes, attr.key, attr.value.newVal)
            i.dset(result, "attributes", attributes)
        of xnCData:
            result.objType = "xml-cdata"
            i.dset(result, "text", xml.text.newVal)
        of xnEntity:
            result.objType = "xml-entity"
            i.dset(result, "text", xml.text.newVal)
        of xnComment:
            result.objType = "xml-comment"
            i.dset(result, "text", xml.text.newVal)

proc newXml(i: In, xdict: MinValue): XmlNode =
     case xdict.objType:
        of "xml-text":
            result = newText(i.dget(xdict, "text").getString)
        of "xml-verbatim-text":
            result = newVerbatimText(i.dget(xdict, "text").getString)
        of "xml-element":
            let tag = i.dget(xdict, "tag").getString
            let attributes = i.dget(xdict, "attributes")
            let children = i.dget(xdict, "children")
            result = newElement(tag)
            var attrs = newSeq[tuple[key, val: string]](0)
            for attr in i.keys(attributes).qVal:
                let key = attr.getString
                let val = i.dget(attributes, attr).getString
                attrs.add {key: key, val: val}
            result.attrs = attrs.toXmlAttributes
            for child in children.qVal:
                result.add i.newXml(child)
        of "xml-cdata":
            result = newCdata(i.dget(xdict, "text").getString)
        of "xml-entity":
            result = newEntity(i.dget(xdict, "text").getString)
        of "xml-comment":
            result = newComment(i.dget(xdict, "text").getString)

proc xml_module*(i: In) =

    let def = i.define()

    i.scope.symbols["xml-node"] = MinOperator(kind: minValOp, val: xmltypes.newVal, sealed: false, quotation: false)

    def.symbol("from-xml") do (i: In):
        let vals = i.expect("str")
        let s = vals[0].getString() 
        try:
            let xml = parseXml(s, {reportComments, allowUnquotedAttribs, allowEmptyAttribs})
            i.push(i.newXDict(xml))
        except CatchableError:
            let msg = getCurrentExceptionMsg()
            raiseInvalid(msg)

    def.symbol("xcomment") do (i: In):
        let vals = i.expect("'sym")
        i.push i.newXDict(newComment(vals[0].getString))   
    
    def.symbol("xcdata") do (i: In):
        let vals = i.expect("'sym")
        i.push i.newXDict(newCData(vals[0].getString))  

    def.symbol("xtext") do (i: In):
        let vals = i.expect("'sym")
        i.push i.newXDict(newText(vals[0].getString))  

    def.symbol("xverbatimtext") do (i: In):
        let vals = i.expect("'sym")
        i.push i.newXDict(newVerbatimText(vals[0].getString)) 

    def.symbol("xentity") do (i: In):
        let vals = i.expect("'sym")
        i.push i.newXDict(newEntity(vals[0].getString)) 

    def.symbol("xelement") do (i: In):
        let vals = i.expect("'sym")
        i.push i.newXDict(newElement(vals[0].getString))

    def.symbol("to-xml") do (i: In):
        let vals = i.expect("dict:xml-node")
        let xdict = vals[0]
        let xml = i.newXml(xdict)
        i.push ($xml).newVal

    def.symbol("xquery") do (i: In):
        let vals = i.expect("dict:xml-element", "'sym")
        let xdict = vals[0]
        let query = vals[1].getString
        let root = i.newXml(xdict)
        i.push i.newXDict(root.querySelector(query))

    def.finalize("xml")