diff --git a/src/glxml.gleam b/src/glxml.gleam
index 2fd15a7..f8fe4db 100644
--- a/src/glxml.gleam
+++ b/src/glxml.gleam
@@ -38,11 +38,13 @@ pub type Element {
Text(content: String)
Comment(content: String)
CData(content: String)
+ PI(name: String, content: String)
+ Whitespace
}
pub fn main() {
parse_document(
- "\r\n \n]]>",
+ "\r\n \n]]>",
)
|> echo
}
@@ -153,13 +155,9 @@ fn parse_content(
try_parsers(
[
parse_element(_, doctype),
- fn(doc) {
- case parse_comment(doc) {
- Ok(#(comment, doc)) -> Ok(#(Comment(comment), doc))
- Error(_) -> Error(Nil)
- }
- },
+ parse_comment,
parse_cdata,
+ parse_pi,
],
doc,
)
@@ -172,6 +170,38 @@ fn parse_content(
}
}
+fn parse_pi(doc: String) -> Result(#(Element, String), Nil) {
+ case doc {
+ "" <> tail -> {
+ use #(name, doc) <- result.try(parse_name(tail))
+ use <- bool.guard(
+ when: string.lowercase(name) == "xml",
+ return: Error(Nil),
+ )
+ let doc = trim_space(doc)
+ use #(content, doc) <- result.try(parse_pi_content(doc, ""))
+ case doc {
+ "?>" <> tail -> Ok(#(PI(name, content), tail))
+ _ -> Error(Nil)
+ }
+ }
+ _ -> Error(Nil)
+ }
+}
+
+fn parse_pi_content(doc: String, pi: String) -> Result(#(String, String), Nil) {
+ case doc {
+ "?>" <> _ -> Ok(#(pi, doc))
+ "" -> Error(Nil)
+ _ -> {
+ case parse_char(doc) {
+ Ok(#(char, doc)) -> parse_pi_content(doc, pi <> char)
+ Error(_) -> Ok(#(pi, doc))
+ }
+ }
+ }
+}
+
fn parse_cdata(doc: String) -> Result(#(Element, String), Nil) {
case doc {
" tail -> {
@@ -404,13 +434,22 @@ fn parse_prolog(
}
fn parse_misc(doc: String) -> String {
- let #(_, doc) =
- parse_multiple_optional(
+ case
+ try_parsers(
+ [
+ parse_comment,
+ fn(doc) {
+ parse_space(doc)
+ |> result.map(fn(sp) { #(Whitespace, sp.1) })
+ },
+ parse_pi,
+ ],
doc,
- try_parsers([parse_comment, parse_space], _),
- "",
)
- doc
+ {
+ Ok(#(_element, doc)) -> parse_misc(doc)
+ Error(Nil) -> doc
+ }
}
fn parse_decl(doc: String) -> Result(#(Declaration, String), Nil) {
@@ -640,12 +679,12 @@ fn parse_alpha(doc: String) -> Result(#(String, String), Nil) {
}
}
-fn parse_comment(doc: String) -> Result(#(String, String), Nil) {
+fn parse_comment(doc: String) -> Result(#(Element, String), Nil) {
case doc {
"" <> tail -> Ok(#(comment, tail))
+ "-->" <> tail -> Ok(#(Comment(comment), tail))
_ -> Error(Nil)
}
}