2 <img src="https://raw.github.com/pest-parser/pest/master/pest-logo.svg?sanitize=true" width="80%"/>
5 # pest. The Elegant Parser
7 [![Join the chat at https://gitter.im/dragostis/pest](https://badges.gitter.im/dragostis/pest.svg)](https://gitter.im/dragostis/pest?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
8 [![Book](https://img.shields.io/badge/book-WIP-4d76ae.svg)](https://pest-parser.github.io/book)
9 [![Docs](https://docs.rs/pest/badge.svg)](https://docs.rs/pest)
11 [![Build Status](https://travis-ci.org/pest-parser/pest.svg?branch=master)](https://travis-ci.org/pest-parser/pest)
12 [![codecov](https://codecov.io/gh/pest-parser/pest/branch/master/graph/badge.svg)](https://codecov.io/gh/pest-parser/pest)
13 [![Crates.io](https://img.shields.io/crates/d/pest.svg)](https://crates.io/crates/pest)
14 [![Crates.io](https://img.shields.io/crates/v/pest.svg)](https://crates.io/crates/pest)
16 pest is a general purpose parser written in Rust with a focus on accessibility,
17 correctness, and performance. It uses parsing expression grammars
18 (or [PEG]) as input, which are similar in spirit to regular expressions, but
19 which offer the enhanced expressivity needed to parse complex languages.
21 [PEG]: https://en.wikipedia.org/wiki/Parsing_expression_grammar
25 The recommended way to start parsing with pest is to read the official [book].
27 Other helpful resources:
29 * API reference on [docs.rs]
30 * play with grammars and share them on our [fiddle]
31 * leave feedback, ask questions, or greet us on [Gitter]
33 [book]: https://pest-parser.github.io/book
34 [docs.rs]: https://docs.rs/pest
35 [fiddle]: https://pest-parser.github.io/#editor
36 [Gitter]: https://gitter.im/dragostis/pest
40 The following is an example of a grammar for a list of alpha-numeric identifiers
41 where the first identifier does not start with a digit:
44 alpha = { 'a'..'z' | 'A'..'Z' }
47 ident = { (alpha | digit)+ }
49 ident_list = _{ !digit ~ ident ~ (" " ~ ident)+ }
51 // ident_list rule is silent which means it produces no tokens
54 Grammars are saved in separate .pest files which are never mixed with procedural
55 code. This results in an always up-to-date formalization of a language that is
56 easy to read and maintain.
58 ## Meaningful error reporting
60 Based on the grammar definition, the parser also includes automatic error
61 reporting. For the example above, the input `"123"` will result in:
64 thread 'main' panicked at ' --> 1:1
69 = unexpected digit', src/main.rs:12
71 while `"ab *"` will result in:
73 thread 'main' panicked at ' --> 1:1
78 = expected ident', src/main.rs:12
83 The grammar can be used to derive a `Parser` implementation automatically.
84 Parsing returns an iterator of nested token pairs:
89 extern crate pest_derive;
94 #[grammar = "ident.pest"]
98 let pairs = IdentParser::parse(Rule::ident_list, "a1 b2").unwrap_or_else(|e| panic!("{}", e));
100 // Because ident_list is silent, the iterator will contain idents
103 let span = pair.clone().into_span();
104 // A pair is a combination of the rule which matched and a span of input
105 println!("Rule: {:?}", pair.as_rule());
106 println!("Span: {:?}", span);
107 println!("Text: {}", span.as_str());
109 // A pair can be converted to an iterator of the tokens which make it up:
110 for inner_pair in pair.into_inner() {
111 let inner_span = inner_pair.clone().into_span();
112 match inner_pair.as_rule() {
113 Rule::alpha => println!("Letter: {}", inner_span.as_str()),
114 Rule::digit => println!("Digit: {}", inner_span.as_str()),
122 This produces the following output:
125 Span: Span { start: 0, end: 2 }
130 Span: Span { start: 3, end: 5 }
138 * Precedence climbing
141 * Runs on stable Rust
143 ## Projects using pest
145 * [pest_meta](https://github.com/pest-parser/pest/blob/master/meta/src/grammar.pest) (bootstrapped)
146 * [brain](https://github.com/brain-lang/brain)
147 * [Chelone](https://github.com/Aaronepower/chelone)
148 * [comrak](https://github.com/kivikakk/comrak)
149 * [graphql-parser](https://github.com/Keats/graphql-parser)
150 * [handlebars-rust](https://github.com/sunng87/handlebars-rust)
151 * [hexdino](https://github.com/Luz/hexdino)
152 * [Huia](https://gitlab.com/jimsy/huia/)
153 * [json5-rs](https://github.com/callum-oakley/json5-rs)
154 * [mt940](https://github.com/svenstaro/mt940-rs)
155 * [py_literal](https://github.com/jturner314/py_literal)
156 * [rouler](https://github.com/jarcane/rouler)
157 * [RuSh](https://github.com/lwandrebeck/RuSh)
158 * [rs_pbrt](https://github.com/wahn/rs_pbrt)
159 * [stache](https://github.com/dgraham/stache)
160 * [tera](https://github.com/Keats/tera)
161 * [ui_gen](https://github.com/emoon/ui_gen)
162 * [ukhasnet-parser](https://github.com/adamgreig/ukhasnet-parser)
166 A special round of applause goes to prof. Marius Minea for his guidance and all
167 pest contributors, some of which being none other than my friends.