{"id":20400360,"url":"https://github.com/fschutt/nom-documentation-readme","last_synced_at":"2026-02-04T11:44:30.013Z","repository":{"id":90270360,"uuid":"93110493","full_name":"fschutt/nom-documentation-readme","owner":"fschutt","description":null,"archived":false,"fork":false,"pushed_at":"2017-06-02T00:21:47.000Z","size":4,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-14T07:18:21.576Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fschutt.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-06-02T00:21:20.000Z","updated_at":"2017-06-02T00:21:20.000Z","dependencies_parsed_at":null,"dependency_job_id":"260aa4db-c1ba-4b17-bb62-f7820d1d92a5","html_url":"https://github.com/fschutt/nom-documentation-readme","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/fschutt/nom-documentation-readme","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fschutt%2Fnom-documentation-readme","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fschutt%2Fnom-documentation-readme/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fschutt%2Fnom-documentation-readme/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fschutt%2Fnom-documentation-readme/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fschutt","download_url":"https://codeload.github.com/fschutt/nom-documentation-readme/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fschutt%2Fnom-documentation-readme/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29083228,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-04T03:31:03.593Z","status":"ssl_error","status_checked_at":"2026-02-04T03:29:50.742Z","response_time":62,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-15T04:39:53.817Z","updated_at":"2026-02-04T11:44:29.996Z","avatar_url":"https://github.com/fschutt.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# nom\n\nnom, eating data byte by byte\n\nnom is a parser combinator library with a focus on safe parsing,\nstreaming patterns, and (as much as possible) zero copying.\n\nThe code is available on [Github](https://github.com/Geal/nom)\n\n### Getting started\n\n#### Minimal parser\n\nHere is an example of the most basic parser you can write. It takes a bunch\nof bytes and looks for the binary representation of the string \"nom\".\n\n```rust\n#[macro_use]\nextern crate nom;\n\n// Generates something like:\n// fn cool_word(i: \u0026[u8]) -\u003e nom::IResult\u003c\u0026[u8], \u0026[u8]\u003e { ... }\nnamed!(cool_word\u003c\u0026[u8]\u003e, tag!(\"nom\"));\n\nfn main() {\n    println!(\"{:?}\", cool_word(b\"nom is awesome\"));\n}\n\n// Outputs: Done([32, 105, 115, 32, 97, 119, 101, 115, 111, 109, 101], [110, 111, 109])\n```\n\nThe heart of this is the `named!` macro, which generates a function, which \nreturns a `nom::IResult`. This is an alternative type for `std::Result`:\n\n```rust,ignore\npub enum IResult\u003cI, O, E = u32\u003e {\n   Done(I, O),          /* I holds the rest of the input, O holds the parsed output */\n   Error(Err\u003cE\u003e),       /* Error holds the error. It's possible to have sub-errors. */\n   Incomplete(Needed),  /* Incomplete is for parsing streams (via network) */\n}\n```\n\nThe last three bytes hold the value `nom` as bytes (nom only occured once in\nour string). A function in nom can return a specific type (in this case, it \njust returned `IResult`). You can, for example use the following function to \nreturn an IResult of `str` from the parser, instead of `\u0026[u8]`:\n\n```rust,ignore\n// Takes \u0026str as input (first argument), produces an IResult of type \u0026str (second argument)\nnamed!(cool_word\u003c\u0026str, \u0026str\u003e, tag!(\"nom\"));\n// outputs: Done(\" is awesome\", \"nom\")\n```\n\n#### Repeated and alternative parsers\n\nOne of the core strengths of nom is the ability to combine sub-parsers into \nlarger, mor complicated parsers. For this to work, we have to define two \nfunctions: One to parse a singular \"nom\" string, and one to expect that the \n\"nom\" is at least __once__ contained in our input:\n\n```rust\n# #[macro_use]\n# extern crate nom;\n# \n// same as before\nnamed!(cool_word\u003c\u0026str, \u0026str\u003e, tag!(\"nom\"));\n\n// the many1 macro produes a vector of T\nnamed!(many_cool_words \u003c\u0026str, Vec\u003c\u0026str\u003e\u003e,\n   many1!(cool_word));\n\nfn main() {\n    println!(\"{:?}\", many_cool_words(\"nomnomnomnomnomnom oh yes!\"));\n}\n\n// Output: Done(\" oh yes!\", [\"nom\", \"nom\", \"nom\", \"nom\", \"nom\", \"nom\"])\n```\n\nThe macros `many1!`, `many0` or `many`, `many_m_n` and `many_till` can be \nused for repeated content. `many1` for example has the restriction that the\ngiven parser must match at least once, if the string did not contain the word\n\"nom\", it would fail.\n\nAlternative parsers can be written using the `alt!` macro. It tries the first\nparser and if it fails, tries the second parser (seperated by a vertical bar).\nYou can even try more than two parsers, by chaining them via a `|`.\n\n```rust\n# #[macro_use]\n# extern crate nom;\n# \nnamed!(parse_many_as \u003c\u0026str, Vec\u003cchar\u003e\u003e,\n   many1!(char!('a')));\n\nnamed!(parse_many_bs \u003c\u0026str, Vec\u003cchar\u003e\u003e,\n   many1!(char!('b')));\n\nnamed!(many_as_or_bs \u003c\u0026str, Vec\u003cchar\u003e\u003e,\n     alt!(parse_many_as | parse_many_bs));\n\nfn main() {\n    println!(\"{:?}\", many_as_or_bs(\"aaaaaaaples\"));\n    println!(\"{:?}\", many_as_or_bs(\"bbbaaaaples\"));\n}\n\n// Done(\"ples\", ['a', 'a', 'a', 'a', 'a', 'a', 'a'])\n// Done(\"aaaaples\", ['b', 'b', 'b'])\n```\n\nHere, we also introduced the `char!` macro for single characters.\nNote that the order of parsers are important in the `alt!` macro. This will,\nfor example, not parse the \"b\"s in our string and stop at the first \"failed\" \nparsing result:\n\n```rust,ignore\n\nfn main() {\n   println!(\"{:?}\", many_as_or_bs(\"aaabbbaaaabbbples\"));\n}\n\n// Done(\"bbbaaaabbbples\", ['a', 'a', 'a'])\n```\n\n#### Capturing / serializing input to structs\n\nUsually when using nom you have some sort of input that you want to serialize\nto a data structure. `nom` is a zero-copy parser, meaning that it will build\nreferences to the data you give it, not clone the data.\n\nSerializing blocks of data that follow a specific order is done using the \n`do_parse!` macro. This macro takes a list of parsers, seperated by a `\u003e\u003e`\nand runs them sequentially on your data. __Note:__ In older versions of `nom`,\nthe `\u003e\u003e` was a tilde character (`~`). This still works (same effect), but the\n`\u003e\u003e` should be used.\n\n```rust\n# #[macro_use]\n# extern crate nom;\n# \nnamed!(many_as \u003c\u0026str, Vec\u003cchar\u003e\u003e,\n   many1!(char!('a')));\n\nnamed!(many_bs \u003c\u0026str, Vec\u003cchar\u003e\u003e,\n   many1!(char!('b')));\n\nnamed!(as_space_then_bs \u003c\u0026str, ()\u003e, do_parse!(\n    many_as \u003e\u003e\n    char!(' ') \u003e\u003e\n    many_bs \u003e\u003e\n    () ));\n\nfn main() {\n    println!(\"{:?}\", as_space_then_bs(\"aaa bbbbbbbbbb\"));\n}\n\n// Done(\"\", ())\n```\n\n`do_parse` uses the last seperated item as a return type that it returns from\nthe generated function. In the above case, this was simply `()`, a void type.\nHowever, you can bind named fields to the parsers (using the `name: parser` syntax)\nand then capture the output to a struct.\n\n```rust\n# #[macro_use]\n# extern crate nom;\n# \n# pub struct ImportantStruct {\n#    a_vec: Vec\u003cchar\u003e,\n#    b_vec: Vec\u003cchar\u003e,\n# }\n# named!(many_as \u003c\u0026str, Vec\u003cchar\u003e\u003e,\n#   many1!(char!('a')));\n#\n# named!(many_bs \u003c\u0026str, Vec\u003cchar\u003e\u003e,\n#    many1!(char!('b')));\n# \n//[...]\n// see previous example for the missing code\n\nnamed!(serialize_a_b_struct\u003c\u0026str, ImportantStruct\u003e, do_parse!(\n    captured_as: many_as \u003e\u003e\n    char!(' ') \u003e\u003e\n    captured_bs: many_bs \u003e\u003e\n    (ImportantStruct { \n           a_vec: captured_as, \n           b_vec: captured_bs\n    }) ));\n\nfn main() {\n    let serialized_struct = serialize_a_b_struct(\"aaa bbbbbbbbbb\").unwrap();\n    println!(\"{:?}\", serialized_struct.1.a_vec);\n    println!(\"{:?}\", serialized_struct.1.b_vec);\n}\n\n// ['a', 'a', 'a']\n// ['b', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b']\n```\n\nNotice: The captured struct has to be wrapped in `()` and the resulting type\nhas to be unwrapped (for this example), resulting in a `(\u0026str, ImportantStruct)`.\nSo we have to use `.1` to get our struct.\n\n#### Conditional parsing, serializing enums, convenience parsers\n\nNow that you know how to assign fields, you can write conditional parsers using\n`opt!` and `cond!`. `opt!` returns an `Option` with `Some(IResult)` if the given\nparser succeded.\n\n```rust\n# #[macro_use]\n# extern crate nom;\n# \nuse std::str::FromStr;\nuse nom::digit;\n\nnamed!(negative_i32 \u003c\u0026str, i32\u003e, do_parse!(\n    neg: opt!(char!('-')) \u003e\u003e\n    digs: cond_reduce!(neg.is_some(), \n        map_res!(digit, i32::from_str)) \u003e\u003e\n    (-digs) ));\n\nfn main() {\n    println!(\"{:?}\", negative_i32(\"1023\"));\n    println!(\"{:?}\", negative_i32(\"-55\"));\n}\n\n// Error(CondReduce)\n// Done(\"\", -55)\n```\n\nThis is a parser that only parses negative numbers. It looks for the char \"-\" \nas the first input, then stores the result in `neg`. The `cond_reduce!` macro only \nexecutes if the first argument is `true` - otherwise it returns an Error. Of\ncourse you could also use an `if` statement inside the return type.\n\nThe `nom::digit` parser is a convenience parser for basic types, provided by nom.\nNom has convenience parsers for integers (with various endianness) and strings.\n\nYou can also serialize directly to enums by using a closure or extract bytes\nusing the `take!`:\n\n```rust\n# #[macro_use]\n# extern crate nom;\nuse nom::Endianness;\n\n#[derive(Debug)]\nstruct Header\u003c'a\u003e {\n  endianness:   Endianness,\n  version:      \u0026'a[u8],\n}\n\nnamed!(parse_header\u003c\u0026[u8], Header\u003e, \n    do_parse!(\n        endianness: alt!(\n          tag!(b\"v\") =\u003e {|_| Endianness::Little } |\n          tag!(b\"V\") =\u003e {|_| Endianness::Big } ) \u003e\u003e\n        version: take!(3) \u003e\u003e\n        (Header {\n          endianness:   endianness,\n          version:      version,\n        })\n    )\n);\n\nfn main() {\n    println!(\"{:?}\", parse_header(b\"v244\"));\n}\n\n// Done([], Header { endianness: Little, version: [50, 52, 52] })\n```\n\n#### Simple error handling\n\nTo handle errors with `nom`, you can use the `add_return_error!` macro when \nyou want to make your own error code (all errors in `nom` are `i32`) and \nlater on use pattern `error_to_list!` to get a `Vec` over the error codes.\nThen you can implement error handling how you want. Or you can use the \nerror_chain` crate to transform noms `ErrorKind` into a string for an error message. \n\nSee the [Error management](error_management.html) page for more details\n\n#### Simple CSV parser\n\nThis is an example of how to combine parsers to make a CSV parser. There are \nmore complicated formats, but this should give you an idea of how parsers can\nbe combined to form bigger ones. Each sub-parser is a seperate function and \ncan thus be tested on its own.\n\n```rust\n# #[macro_use]\n# extern crate nom;\n# \nnamed!(csv_escaped_char\u003c\u0026str, char\u003e, alt!(\n    tag!(\"\\\"\\\"\") =\u003e { |_| '\"' } |\n        none_of!(\"\\\"\")));\n\nnamed!(csv_style_str\u003c\u0026str, String\u003e, do_parse!(\n    char!('\"') \u003e\u003e\n    chars: many0!(csv_escaped_char) \u003e\u003e\n    char!('\"') \u003e\u003e\n    (chars.into_iter().collect()) ));\n\nfn main() {\n    println!(\"{:?}\", csv_style_str(r#\"\"some string\" is cool\"#));\n    println!(\"{:?}\", csv_style_str(\n        r#\"\"some string with \"\" internal quotes!\" is also cool\"#));\n}\n```\n\n\n\n### Further Reading\n\n- [Nom guides](home.html)\n- [The design of nom](how_nom_macros_work.html)\n- [How to write parsers](making_a_new_parser_from_scratch.html)\n- [Error management](error_management.html)\n- [Migrating from nom 1.0 to 2.0 / higher](upgrading_to_nom_2.html)\n- [FAQ](FAQ.html)\n\nAlso, you can join us on `#nom` on our IRC channel at `irc.mozilla.org:6667`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffschutt%2Fnom-documentation-readme","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffschutt%2Fnom-documentation-readme","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffschutt%2Fnom-documentation-readme/lists"}