{"id":13439958,"url":"https://github.com/pest-parser/pest","last_synced_at":"2025-05-13T11:04:52.223Z","repository":{"id":40594825,"uuid":"56964647","full_name":"pest-parser/pest","owner":"pest-parser","description":"The Elegant Parser","archived":false,"fork":false,"pushed_at":"2025-03-25T06:49:25.000Z","size":2418,"stargazers_count":4920,"open_issues_count":66,"forks_count":269,"subscribers_count":41,"default_branch":"master","last_synced_at":"2025-05-13T11:04:36.737Z","etag":null,"topics":["parsing","peg","rust"],"latest_commit_sha":null,"homepage":"https://pest.rs","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pest-parser.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"pest-parser","open_collective":"pest"}},"created_at":"2016-04-24T09:50:43.000Z","updated_at":"2025-05-13T08:22:42.000Z","dependencies_parsed_at":"2024-01-13T19:23:06.356Z","dependency_job_id":"8b865a76-f7c7-4896-ae80-0fbab2aab928","html_url":"https://github.com/pest-parser/pest","commit_stats":{"total_commits":1106,"total_committers":133,"mean_commits":8.31578947368421,"dds":0.5072332730560578,"last_synced_commit":"e457389b0b858b97cf4ae2fe83f0040abcf50dd6"},"previous_names":[],"tags_count":74,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pest-parser%2Fpest","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pest-parser%2Fpest/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pest-parser%2Fpest/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pest-parser%2Fpest/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pest-parser","download_url":"https://codeload.github.com/pest-parser/pest/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253929361,"owners_count":21985802,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["parsing","peg","rust"],"created_at":"2024-07-31T03:01:18.509Z","updated_at":"2025-05-13T11:04:51.945Z","avatar_url":"https://github.com/pest-parser.png","language":"Rust","funding_links":["https://github.com/sponsors/pest-parser","https://opencollective.com/pest"],"categories":["Rust","Libraries","库 Libraries","库","虚拟化","Tools and Frameworks","parsing"],"sub_categories":["Parsing","Parser","解析 Parsing","解析","Other dialects and variants","Rust","Parsers"],"readme":"\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://raw.github.com/pest-parser/pest/master/pest-logo.svg?sanitize=true\" width=\"80%\"/\u003e\n\u003c/p\u003e\n\n# pest. The Elegant Parser\n\n[![Join the chat at https://gitter.im/pest-parser/pest](https://badges.gitter.im/dragostis/pest.svg)](https://gitter.im/pest-parser/pest?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge\u0026utm_content=badge)\n[![Book](https://img.shields.io/badge/book-WIP-4d76ae.svg)](https://pest.rs/book)\n[![Docs](https://docs.rs/pest/badge.svg)](https://docs.rs/pest)\n\n[![pest Continuous Integration](https://github.com/pest-parser/pest/actions/workflows/ci.yml/badge.svg)](https://github.com/pest-parser/pest/actions/workflows/ci.yml)\n[![codecov](https://codecov.io/gh/pest-parser/pest/branch/master/graph/badge.svg)](https://codecov.io/gh/pest-parser/pest)\n\u003ca href=\"https://blog.rust-lang.org/2021/11/01/Rust-1.65.0.html\"\u003e\u003cimg alt=\"Rustc Version 1.65.0+\" src=\"https://img.shields.io/badge/rustc-1.65.0%2B-lightgrey.svg\"/\u003e\u003c/a\u003e\n\n[![Crates.io](https://img.shields.io/crates/d/pest.svg)](https://crates.io/crates/pest)\n[![Crates.io](https://img.shields.io/crates/v/pest.svg)](https://crates.io/crates/pest)\n\npest is a general purpose parser written in Rust with a focus on accessibility,\ncorrectness, and performance. It uses parsing expression grammars\n(or [PEG]) as input, which are similar in spirit to regular expressions, but\nwhich offer the enhanced expressivity needed to parse complex languages.\n\n[PEG]: https://en.wikipedia.org/wiki/Parsing_expression_grammar\n\n## Getting started\n\nThe recommended way to start parsing with pest is to read the official [book].\n\nOther helpful resources:\n\n* API reference on [docs.rs]\n* play with grammars and share them on our [fiddle]\n* find previous common questions answered or ask questions on [GitHub Discussions]\n* leave feedback, ask questions, or greet us on [Gitter] or [Discord]\n\n[book]: https://pest.rs/book\n[docs.rs]: https://docs.rs/pest\n[fiddle]: https://pest.rs/#editor\n[Gitter]: https://gitter.im/pest-parser/pest\n[Discord]: https://discord.gg/XEGACtWpT2\n[GitHub Discussions]: https://github.com/pest-parser/pest/discussions\n\n## Example\n\nThe following is an example of a grammar for a list of alphanumeric identifiers\nwhere all identifiers don't start with a digit:\n\n```rust\nalpha = { 'a'..'z' | 'A'..'Z' }\ndigit = { '0'..'9' }\n\nident = { !digit ~ (alpha | digit)+ }\n\nident_list = _{ ident ~ (\" \" ~ ident)* }\n          // ^\n          // ident_list rule is silent which means it produces no tokens\n```\n\nGrammars are saved in separate .pest files which are never mixed with procedural\ncode. This results in an always up-to-date formalization of a language that is\neasy to read and maintain.\n\n## Meaningful error reporting\n\nBased on the grammar definition, the parser also includes automatic error\nreporting. For the example above, the input `\"123\"` will result in:\n\n```\nthread 'main' panicked at ' --\u003e 1:1\n  |\n1 | 123\n  | ^---\n  |\n  = unexpected digit', src/main.rs:12\n```\nwhile `\"ab *\"` will result in:\n```\nthread 'main' panicked at ' --\u003e 1:1\n  |\n1 | ab *\n  |    ^---\n  |\n  = expected ident', src/main.rs:12\n```\n\nThese error messages can be obtained from their default `Display` implementation,\ne.g. `panic!(\"{}\", parser_result.unwrap_err())` or `println!(\"{}\", e)`.\n\n## Pairs API\n\nThe grammar can be used to derive a `Parser` implementation automatically.\nParsing returns an iterator of nested token pairs:\n\n```rust\nuse pest_derive::Parser;\nuse pest::Parser;\n\n#[derive(Parser)]\n#[grammar = \"ident.pest\"]\nstruct IdentParser;\n\nfn main() {\n    let pairs = IdentParser::parse(Rule::ident_list, \"a1 b2\").unwrap_or_else(|e| panic!(\"{}\", e));\n\n    // Because ident_list is silent, the iterator will contain idents\n    for pair in pairs {\n        // A pair is a combination of the rule which matched and a span of input\n        println!(\"Rule:    {:?}\", pair.as_rule());\n        println!(\"Span:    {:?}\", pair.as_span());\n        println!(\"Text:    {}\", pair.as_str());\n\n        // A pair can be converted to an iterator of the tokens which make it up:\n        for inner_pair in pair.into_inner() {\n            match inner_pair.as_rule() {\n                Rule::alpha =\u003e println!(\"Letter:  {}\", inner_pair.as_str()),\n                Rule::digit =\u003e println!(\"Digit:   {}\", inner_pair.as_str()),\n                _ =\u003e unreachable!()\n            };\n        }\n    }\n}\n```\n\nThis produces the following output:\n```\nRule:    ident\nSpan:    Span { start: 0, end: 2 }\nText:    a1\nLetter:  a\nDigit:   1\nRule:    ident\nSpan:    Span { start: 3, end: 5 }\nText:    b2\nLetter:  b\nDigit:   2\n```\n\n### Defining multiple parsers in a single file\nThe current automatic `Parser` derivation will produce the `Rule` enum\nwhich would have name conflicts if one tried to define multiple such structs\nthat automatically derive `Parser`. One possible way around it is to put each\nparser struct in a separate namespace:\n\n```rust\nmod a {\n    #[derive(Parser)]\n    #[grammar = \"a.pest\"]\n    pub struct ParserA;\n}\nmod b {\n    #[derive(Parser)]\n    #[grammar = \"b.pest\"]\n    pub struct ParserB;\n}\n```\n\n## Other features\n\n* Precedence climbing\n* Input handling\n* Custom errors\n* Runs on stable Rust\n\n## Projects using pest\n\nYou can find more projects and ecosystem tools in the [awesome-pest](https://github.com/pest-parser/awesome-pest) repo.\n\n* [pest_meta](https://github.com/pest-parser/pest/blob/master/meta/src/grammar.pest) (bootstrapped)\n* [AshPaper](https://github.com/shnewto/ashpaper)\n* [brain](https://github.com/brain-lang/brain)\n* [cicada](https://github.com/mitnk/cicada)\n* [comrak](https://github.com/kivikakk/comrak)\n* [elastic-rs](https://github.com/cch123/elastic-rs)\n* [graphql-parser](https://github.com/Keats/graphql-parser)\n* [handlebars-rust](https://github.com/sunng87/handlebars-rust)\n* [hexdino](https://github.com/Luz/hexdino)\n* [Huia](https://gitlab.com/jimsy/huia/)\n* [insta](https://github.com/mitsuhiko/insta)\n* [jql](https://github.com/yamafaktory/jql)\n* [json5-rs](https://github.com/callum-oakley/json5-rs)\n* [mt940](https://github.com/svenstaro/mt940-rs)\n* [Myoxine](https://github.com/d3bate/myoxine)\n* [py_literal](https://github.com/jturner314/py_literal)\n* [rouler](https://github.com/jarcane/rouler)\n* [RuSh](https://github.com/lwandrebeck/RuSh)\n* [rs_pbrt](https://github.com/wahn/rs_pbrt)\n* [stache](https://github.com/dgraham/stache)\n* [tera](https://github.com/Keats/tera)\n* [ui_gen](https://github.com/emoon/ui_gen)\n* [ukhasnet-parser](https://github.com/adamgreig/ukhasnet-parser)\n* [ZoKrates](https://github.com/ZoKrates/ZoKrates)\n* [Vector](https://github.com/timberio/vector)\n* [AutoCorrect](https://github.com/huacnlee/autocorrect)\n* [yaml-peg](https://github.com/aofdev/yaml-peg)\n* [qubit](https://github.com/abhimanyu003/qubit)\n* [caith](https://github.com/Geobert/caith) (a dice roller crate)\n* [Melody](https://github.com/yoav-lavi/melody)\n* [json5-nodes](https://github.com/jlyonsmith/json5-nodes)\n* [prisma](https://github.com/prisma/prisma)\n\n## Minimum Supported Rust Version (MSRV)\n\nThis library should always compile with default features on **Rust 1.65.0**.\n\n## no_std support\n\nThe `pest` and `pest_derive` crates can be built without the Rust standard\nlibrary and target embedded environments. To do so, you need to disable\ntheir default features. In your `Cargo.toml`, you can specify it as follows:\n\n```toml\n[dependencies]\n# ...\npest = { version = \"2\", default-features = false }\npest_derive = { version = \"2\", default-features = false }\n```\n\nIf you want to build these crates in the pest repository's workspace, you can\npass the `--no-default-features` flag to `cargo` and specify these crates using\nthe `--package` (`-p`) flag. For example:\n\n```bash\n$ cargo build --target thumbv7em-none-eabihf --no-default-features -p pest\n$ cargo bootstrap\n$ cargo build --target thumbv7em-none-eabihf --no-default-features -p pest_derive\n```\n\n## Special thanks\n\nA special round of applause goes to prof. Marius Minea for his guidance and all\npest contributors, some of which being none other than my friends.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpest-parser%2Fpest","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpest-parser%2Fpest","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpest-parser%2Fpest/lists"}