diff --git a/core/encoding/xml/debug_print.odin b/core/encoding/xml/debug_print.odin index 65b71e30b..e6a8c9433 100644 --- a/core/encoding/xml/debug_print.odin +++ b/core/encoding/xml/debug_print.odin @@ -36,6 +36,10 @@ print :: proc(writer: io.Writer, doc: ^Document) -> (written: int, err: io.Error } } + for comment in doc.comments { + written += wprintf(writer, "[Pre-root comment] %v\n", comment) + } + if doc.root != nil { wprintln(writer, " --- ") print_element(writer, doc.root) diff --git a/core/encoding/xml/xml_reader.odin b/core/encoding/xml/xml_reader.odin index 34f6e65d0..b2226e6b9 100644 --- a/core/encoding/xml/xml_reader.odin +++ b/core/encoding/xml/xml_reader.odin @@ -86,10 +86,16 @@ Document :: struct { /* We only scan the . The grammar does not allow a comment to end in ---> */ - if doc.root == nil { - return doc, .Comment_Before_Root_Element - } - expect(t, .Dash) offset := t.offset @@ -329,12 +339,17 @@ parse_from_slice :: proc(data: []u8, options := DEFAULT_Options, path := "", err } if .Intern_Comments in opts.flags { - el := new(Element) + comment := strings.intern_get(&doc.intern, string(t.src[offset : t.offset - 1])) - el.parent = element - el.kind = .Comment - el.value = strings.intern_get(&doc.intern, string(t.src[offset : t.offset - 1])) - append(&element.children, el) + if doc.root == nil { + append(&doc.comments, comment) + } else { + el := new(Element) + el.parent = element + el.kind = .Comment + el.value = comment + append(&element.children, el) + } } expect(t, .Dash) @@ -350,6 +365,7 @@ parse_from_slice :: proc(data: []u8, options := DEFAULT_Options, path := "", err e.g. `, which means this is an 'empty' or self-closing tag. */ end_token := scan(t) - #partial switch end_token.kind { case .Gt: /* @@ -394,9 +409,12 @@ parse_from_slice :: proc(data: []u8, options := DEFAULT_Options, path := "", err case .Slash: /* - Empty tag? + Empty tag. Close it. */ expect(t, .Gt) or_return + parent = element.parent + element = parent + tag_is_open = false case: error(t, t.offset, "Expected close tag, got: %#v\n", end_token) @@ -411,25 +429,33 @@ parse_from_slice :: proc(data: []u8, options := DEFAULT_Options, path := "", err _ = expect(t, .Gt) or_return if element.ident != ident.text { - error(t, t.offset, "Mismatched Closing Tag: %v\n", ident.text) + error(t, t.offset, "Mismatched Closing Tag. Expected %v, got %v\n", element.ident, ident.text) return doc, .Mismatched_Closing_Tag } - parent = element.parent - element = parent + parent = element.parent + element = parent + tag_is_open = false case: error(t, t.offset, "Invalid Token after <: %#v\n", open) return } - case .EOF: + case -1: + /* + End of file. + */ + if tag_is_open { + return doc, .Premature_EOF + } break loop case: /* This should be a tag's body text. */ - element.value = scan_string(t, tok.pos.offset) or_return + body_text := scan_string(t, t.offset) or_return + element.value = strings.intern_get(&doc.intern, body_text) } } @@ -480,6 +506,7 @@ destroy :: proc(doc: ^Document) { strings.intern_destroy(&doc.intern) delete(doc.prolog) + delete(doc.comments) free(doc) }