This commit is contained in:
		
							
								
								
									
										23
									
								
								.github/workflows/test.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								.github/workflows/test.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					name: test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					on:
 | 
				
			||||||
 | 
					  push:
 | 
				
			||||||
 | 
					    branches:
 | 
				
			||||||
 | 
					      - master
 | 
				
			||||||
 | 
					      - main
 | 
				
			||||||
 | 
					  pull_request:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					jobs:
 | 
				
			||||||
 | 
					  test:
 | 
				
			||||||
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					      - uses: actions/checkout@v4
 | 
				
			||||||
 | 
					      - uses: erlef/setup-beam@v1
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          otp-version: "27.1.2"
 | 
				
			||||||
 | 
					          gleam-version: "1.12.0"
 | 
				
			||||||
 | 
					          rebar3-version: "3"
 | 
				
			||||||
 | 
					          # elixir-version: "1"
 | 
				
			||||||
 | 
					      - run: gleam deps download
 | 
				
			||||||
 | 
					      - run: gleam test
 | 
				
			||||||
 | 
					      - run: gleam format --check src test
 | 
				
			||||||
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					*.beam
 | 
				
			||||||
 | 
					*.ez
 | 
				
			||||||
 | 
					/build
 | 
				
			||||||
 | 
					erl_crash.dump
 | 
				
			||||||
							
								
								
									
										23
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								README.md
									
									
									
									
									
								
							@@ -1,3 +1,24 @@
 | 
				
			|||||||
# glxml
 | 
					# glxml
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Gleam XML Parser
 | 
					[](https://hex.pm/packages/glxml)
 | 
				
			||||||
 | 
					[](https://hexdocs.pm/glxml/)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```sh
 | 
				
			||||||
 | 
					gleam add glxml@1
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					```gleam
 | 
				
			||||||
 | 
					import glxml
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn main() -> Nil {
 | 
				
			||||||
 | 
					  // TODO: An example of the project in use
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Further documentation can be found at <https://hexdocs.pm/glxml>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Development
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```sh
 | 
				
			||||||
 | 
					gleam run   # Run the project
 | 
				
			||||||
 | 
					gleam test  # Run the tests
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										19
									
								
								gleam.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								gleam.toml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					name = "glxml"
 | 
				
			||||||
 | 
					version = "1.0.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Fill out these fields if you intend to generate HTML documentation or publish
 | 
				
			||||||
 | 
					# your project to the Hex package manager.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# description = ""
 | 
				
			||||||
 | 
					# licences = ["Apache-2.0"]
 | 
				
			||||||
 | 
					# repository = { type = "github", user = "", repo = "" }
 | 
				
			||||||
 | 
					# links = [{ title = "Website", href = "" }]
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# For a full reference of all the available options, you can have a look at
 | 
				
			||||||
 | 
					# https://gleam.run/writing-gleam/gleam-toml/.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[dependencies]
 | 
				
			||||||
 | 
					gleam_stdlib = ">= 0.44.0 and < 2.0.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[dev-dependencies]
 | 
				
			||||||
 | 
					gleeunit = ">= 1.0.0 and < 2.0.0"
 | 
				
			||||||
							
								
								
									
										11
									
								
								manifest.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								manifest.toml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					# This file was generated by Gleam
 | 
				
			||||||
 | 
					# You typically do not need to edit this file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					packages = [
 | 
				
			||||||
 | 
					  { name = "gleam_stdlib", version = "0.65.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "7C69C71D8C493AE11A5184828A77110EB05A7786EBF8B25B36A72F879C3EE107" },
 | 
				
			||||||
 | 
					  { name = "gleeunit", version = "1.6.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "FDC68A8C492B1E9B429249062CD9BAC9B5538C6FBF584817205D0998C42E1DAC" },
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[requirements]
 | 
				
			||||||
 | 
					gleam_stdlib = { version = ">= 0.44.0 and < 2.0.0" }
 | 
				
			||||||
 | 
					gleeunit = { version = ">= 1.0.0 and < 2.0.0" }
 | 
				
			||||||
							
								
								
									
										273
									
								
								src/glxml.gleam
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										273
									
								
								src/glxml.gleam
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,273 @@
 | 
				
			|||||||
 | 
					import gleam/result
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub type Declaration {
 | 
				
			||||||
 | 
					  Declaration(versioninfo: String, encoding: String)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub type DocType {
 | 
				
			||||||
 | 
					  None
 | 
				
			||||||
 | 
					  DocType(name: String)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub type Document {
 | 
				
			||||||
 | 
					  Document(decl: Declaration, doctype: DocType)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn main() {
 | 
				
			||||||
 | 
					  parse_document("<?xml version=\"1.1\" encoding='UTF-8'?>") |> echo
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn parse_document(doc: String) -> Result(Document, Nil) {
 | 
				
			||||||
 | 
					  use #(decl, doctype, _doc) <- result.try(parse_prolog(doc))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Ok(Document(decl, doctype))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn parse_prolog(doc: String) -> Result(#(Declaration, DocType, String), Nil) {
 | 
				
			||||||
 | 
					  use #(decl, doc) <- result.try(parse_decl(doc))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Ok(#(decl, None, doc))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn parse_decl(doc: String) -> Result(#(Declaration, String), Nil) {
 | 
				
			||||||
 | 
					  case doc {
 | 
				
			||||||
 | 
					    "<?xml" <> tail -> {
 | 
				
			||||||
 | 
					      use #(versioninfo, doc) <- result.try(parse_versioninfo(tail))
 | 
				
			||||||
 | 
					      let #(encoding, doc) = case parse_encodingdecl(doc) {
 | 
				
			||||||
 | 
					        Ok(e) -> e
 | 
				
			||||||
 | 
					        Error(_) -> #("", doc)
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      case trim_space(doc) {
 | 
				
			||||||
 | 
					        "?>" <> tail -> Ok(#(Declaration(versioninfo:, encoding:), tail))
 | 
				
			||||||
 | 
					        _ -> Error(Nil)
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    _ -> Error(Nil)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn parse_versioninfo(doc: String) -> Result(#(String, String), Nil) {
 | 
				
			||||||
 | 
					  use #(_, doc) <- result.try(parse_space(doc))
 | 
				
			||||||
 | 
					  case doc {
 | 
				
			||||||
 | 
					    "version=" <> tail -> {
 | 
				
			||||||
 | 
					      use #(version, doc) <- result.try(parse_version(tail))
 | 
				
			||||||
 | 
					      Ok(#(version, doc))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    _ -> Error(Nil)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn parse_version(doc: String) -> Result(#(String, String), Nil) {
 | 
				
			||||||
 | 
					  case doc {
 | 
				
			||||||
 | 
					    "\"1." <> tail -> {
 | 
				
			||||||
 | 
					      use #(version, doc) <- result.try(do_parse_version(tail, "1."))
 | 
				
			||||||
 | 
					      case doc {
 | 
				
			||||||
 | 
					        "\"" <> tail -> Ok(#(version, tail))
 | 
				
			||||||
 | 
					        _ -> Error(Nil)
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    "'1." <> tail -> {
 | 
				
			||||||
 | 
					      use #(version, doc) <- result.try(do_parse_version(tail, "1."))
 | 
				
			||||||
 | 
					      case doc {
 | 
				
			||||||
 | 
					        "'" <> tail -> Ok(#(version, tail))
 | 
				
			||||||
 | 
					        _ -> Error(Nil)
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    _ -> Error(Nil)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn do_parse_version(
 | 
				
			||||||
 | 
					  doc: String,
 | 
				
			||||||
 | 
					  version: String,
 | 
				
			||||||
 | 
					) -> Result(#(String, String), Nil) {
 | 
				
			||||||
 | 
					  case do_parse_digit(doc) {
 | 
				
			||||||
 | 
					    Ok(#(digit, doc)) -> do_parse_version(doc, version <> digit)
 | 
				
			||||||
 | 
					    Error(_) if version == "" -> Error(Nil)
 | 
				
			||||||
 | 
					    Error(_) -> Ok(#(version, doc))
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn parse_encodingdecl(doc: String) -> Result(#(String, String), Nil) {
 | 
				
			||||||
 | 
					  use #(_, doc) <- result.try(parse_space(doc))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  case doc {
 | 
				
			||||||
 | 
					    "encoding=" <> tail -> {
 | 
				
			||||||
 | 
					      case tail {
 | 
				
			||||||
 | 
					        "\"" <> tail -> {
 | 
				
			||||||
 | 
					          use #(encoding, doc) <- result.try(parse_encoding(tail))
 | 
				
			||||||
 | 
					          case doc {
 | 
				
			||||||
 | 
					            "\"" <> tail -> Ok(#(encoding, tail))
 | 
				
			||||||
 | 
					            _ -> Error(Nil)
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        "'" <> tail -> {
 | 
				
			||||||
 | 
					          use #(encoding, doc) <- result.try(parse_encoding(tail))
 | 
				
			||||||
 | 
					          case doc {
 | 
				
			||||||
 | 
					            "'" <> tail -> Ok(#(encoding, tail))
 | 
				
			||||||
 | 
					            _ -> Error(Nil)
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        _ -> Error(Nil)
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    _ -> Error(Nil)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn parse_encoding(doc: String) -> Result(#(String, String), Nil) {
 | 
				
			||||||
 | 
					  case do_parse_alpha(doc) {
 | 
				
			||||||
 | 
					    Ok(#(char, doc)) -> {
 | 
				
			||||||
 | 
					      Ok(parse_multiple_optional(
 | 
				
			||||||
 | 
					        doc,
 | 
				
			||||||
 | 
					        try_parsers(
 | 
				
			||||||
 | 
					          [
 | 
				
			||||||
 | 
					            do_parse_alpha,
 | 
				
			||||||
 | 
					            do_parse_digit,
 | 
				
			||||||
 | 
					            fn(doc) {
 | 
				
			||||||
 | 
					              case doc {
 | 
				
			||||||
 | 
					                "." as char <> tail | "_" as char <> tail | "-" as char <> tail ->
 | 
				
			||||||
 | 
					                  Ok(#(char, tail))
 | 
				
			||||||
 | 
					                _ -> Error(Nil)
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					          _,
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					        char,
 | 
				
			||||||
 | 
					      ))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    Error(_) -> Error(Nil)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn do_parse_digit(doc: String) -> Result(#(String, String), Nil) {
 | 
				
			||||||
 | 
					  case doc {
 | 
				
			||||||
 | 
					    "0" as digit <> tail
 | 
				
			||||||
 | 
					    | "1" as digit <> tail
 | 
				
			||||||
 | 
					    | "2" as digit <> tail
 | 
				
			||||||
 | 
					    | "3" as digit <> tail
 | 
				
			||||||
 | 
					    | "4" as digit <> tail
 | 
				
			||||||
 | 
					    | "5" as digit <> tail
 | 
				
			||||||
 | 
					    | "6" as digit <> tail
 | 
				
			||||||
 | 
					    | "7" as digit <> tail
 | 
				
			||||||
 | 
					    | "8" as digit <> tail
 | 
				
			||||||
 | 
					    | "9" as digit <> tail -> Ok(#(digit, tail))
 | 
				
			||||||
 | 
					    _ -> Error(Nil)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn do_parse_alpha(doc: String) -> Result(#(String, String), Nil) {
 | 
				
			||||||
 | 
					  case doc {
 | 
				
			||||||
 | 
					    "a" as char <> tail
 | 
				
			||||||
 | 
					    | "b" as char <> tail
 | 
				
			||||||
 | 
					    | "c" as char <> tail
 | 
				
			||||||
 | 
					    | "d" as char <> tail
 | 
				
			||||||
 | 
					    | "e" as char <> tail
 | 
				
			||||||
 | 
					    | "f" as char <> tail
 | 
				
			||||||
 | 
					    | "g" as char <> tail
 | 
				
			||||||
 | 
					    | "h" as char <> tail
 | 
				
			||||||
 | 
					    | "i" as char <> tail
 | 
				
			||||||
 | 
					    | "j" as char <> tail
 | 
				
			||||||
 | 
					    | "k" as char <> tail
 | 
				
			||||||
 | 
					    | "l" as char <> tail
 | 
				
			||||||
 | 
					    | "m" as char <> tail
 | 
				
			||||||
 | 
					    | "n" as char <> tail
 | 
				
			||||||
 | 
					    | "o" as char <> tail
 | 
				
			||||||
 | 
					    | "p" as char <> tail
 | 
				
			||||||
 | 
					    | "q" as char <> tail
 | 
				
			||||||
 | 
					    | "r" as char <> tail
 | 
				
			||||||
 | 
					    | "s" as char <> tail
 | 
				
			||||||
 | 
					    | "t" as char <> tail
 | 
				
			||||||
 | 
					    | "u" as char <> tail
 | 
				
			||||||
 | 
					    | "v" as char <> tail
 | 
				
			||||||
 | 
					    | "w" as char <> tail
 | 
				
			||||||
 | 
					    | "x" as char <> tail
 | 
				
			||||||
 | 
					    | "y" as char <> tail
 | 
				
			||||||
 | 
					    | "z" as char <> tail
 | 
				
			||||||
 | 
					    | "A" as char <> tail
 | 
				
			||||||
 | 
					    | "B" as char <> tail
 | 
				
			||||||
 | 
					    | "C" as char <> tail
 | 
				
			||||||
 | 
					    | "D" as char <> tail
 | 
				
			||||||
 | 
					    | "E" as char <> tail
 | 
				
			||||||
 | 
					    | "F" as char <> tail
 | 
				
			||||||
 | 
					    | "G" as char <> tail
 | 
				
			||||||
 | 
					    | "H" as char <> tail
 | 
				
			||||||
 | 
					    | "I" as char <> tail
 | 
				
			||||||
 | 
					    | "J" as char <> tail
 | 
				
			||||||
 | 
					    | "K" as char <> tail
 | 
				
			||||||
 | 
					    | "L" as char <> tail
 | 
				
			||||||
 | 
					    | "M" as char <> tail
 | 
				
			||||||
 | 
					    | "N" as char <> tail
 | 
				
			||||||
 | 
					    | "O" as char <> tail
 | 
				
			||||||
 | 
					    | "P" as char <> tail
 | 
				
			||||||
 | 
					    | "Q" as char <> tail
 | 
				
			||||||
 | 
					    | "R" as char <> tail
 | 
				
			||||||
 | 
					    | "S" as char <> tail
 | 
				
			||||||
 | 
					    | "T" as char <> tail
 | 
				
			||||||
 | 
					    | "U" as char <> tail
 | 
				
			||||||
 | 
					    | "V" as char <> tail
 | 
				
			||||||
 | 
					    | "W" as char <> tail
 | 
				
			||||||
 | 
					    | "X" as char <> tail
 | 
				
			||||||
 | 
					    | "Y" as char <> tail
 | 
				
			||||||
 | 
					    | "Z" as char <> tail -> Ok(#(char, tail))
 | 
				
			||||||
 | 
					    _ -> Error(Nil)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn trim_space(doc: String) -> String {
 | 
				
			||||||
 | 
					  case parse_space(doc) {
 | 
				
			||||||
 | 
					    Ok(#(_, doc)) -> trim_space(doc)
 | 
				
			||||||
 | 
					    Error(_) -> doc
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn parse_space(doc: String) -> Result(#(String, String), Nil) {
 | 
				
			||||||
 | 
					  case doc {
 | 
				
			||||||
 | 
					    " " as ws <> tail
 | 
				
			||||||
 | 
					    | "\t" as ws <> tail
 | 
				
			||||||
 | 
					    | "\n" as ws <> tail
 | 
				
			||||||
 | 
					    | "\r" as ws <> tail -> Ok(#(ws, tail))
 | 
				
			||||||
 | 
					    _ -> Error(Nil)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn try_parsers(
 | 
				
			||||||
 | 
					  over list: List(fn(String) -> Result(#(a, String), Nil)),
 | 
				
			||||||
 | 
					  against static_data: String,
 | 
				
			||||||
 | 
					) -> Result(#(a, String), Nil) {
 | 
				
			||||||
 | 
					  case list {
 | 
				
			||||||
 | 
					    [] -> Error(Nil)
 | 
				
			||||||
 | 
					    [first, ..rest] ->
 | 
				
			||||||
 | 
					      case first(static_data) {
 | 
				
			||||||
 | 
					        Error(_) -> try_parsers(rest, static_data)
 | 
				
			||||||
 | 
					        Ok(r) -> Ok(r)
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn parse_multiple(
 | 
				
			||||||
 | 
					  to_parse str: String,
 | 
				
			||||||
 | 
					  with to_run: fn(String) -> Result(#(String, String), Nil),
 | 
				
			||||||
 | 
					) -> Result(#(String, String), Nil) {
 | 
				
			||||||
 | 
					  case parse_multiple_optional(str, to_run, "") {
 | 
				
			||||||
 | 
					    #("", _) -> Error(Nil)
 | 
				
			||||||
 | 
					    #(r, rest) -> Ok(#(r, rest))
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn parse_multiple_optional(
 | 
				
			||||||
 | 
					  to_parse str: String,
 | 
				
			||||||
 | 
					  with to_run: fn(String) -> Result(#(String, String), Nil),
 | 
				
			||||||
 | 
					  acc ret: String,
 | 
				
			||||||
 | 
					) -> #(String, String) {
 | 
				
			||||||
 | 
					  case str {
 | 
				
			||||||
 | 
					    "" -> #(ret, str)
 | 
				
			||||||
 | 
					    _ ->
 | 
				
			||||||
 | 
					      case to_run(str) {
 | 
				
			||||||
 | 
					        Ok(#(r, rest)) -> parse_multiple_optional(rest, to_run, ret <> r)
 | 
				
			||||||
 | 
					        Error(_) -> #(ret, str)
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										13
									
								
								test/glxml_test.gleam
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								test/glxml_test.gleam
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					import gleeunit
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn main() -> Nil {
 | 
				
			||||||
 | 
					  gleeunit.main()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// gleeunit test functions end in `_test`
 | 
				
			||||||
 | 
					pub fn hello_world_test() {
 | 
				
			||||||
 | 
					  let name = "Joe"
 | 
				
			||||||
 | 
					  let greeting = "Hello, " <> name <> "!"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  assert greeting == "Hello, Joe!"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user