]> git.proxmox.com Git - rustc.git/blob - vendor/pest_derive/_README.md
New upstream version 1.72.1+dfsg1
[rustc.git] / vendor / pest_derive / _README.md
1
2 <p align="center">
3 <img src="https://raw.github.com/pest-parser/pest/master/pest-logo.svg?sanitize=true" width="80%"/>
4 </p>
5
6 # pest. The Elegant Parser
7
8 [![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&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
9 [![Book](https://img.shields.io/badge/book-WIP-4d76ae.svg)](https://pest.rs/book)
10 [![Docs](https://docs.rs/pest/badge.svg)](https://docs.rs/pest)
11
12 [![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)
13 [![codecov](https://codecov.io/gh/pest-parser/pest/branch/master/graph/badge.svg)](https://codecov.io/gh/pest-parser/pest)
14 <a href="https://blog.rust-lang.org/2021/11/01/Rust-1.60.0.html"><img alt="Rustc Version 1.60.0+" src="https://img.shields.io/badge/rustc-1.60.0%2B-lightgrey.svg"/></a>
15
16 [![Crates.io](https://img.shields.io/crates/d/pest.svg)](https://crates.io/crates/pest)
17 [![Crates.io](https://img.shields.io/crates/v/pest.svg)](https://crates.io/crates/pest)
18
19 pest is a general purpose parser written in Rust with a focus on accessibility,
20 correctness, and performance. It uses parsing expression grammars
21 (or [PEG]) as input, which are similar in spirit to regular expressions, but
22 which offer the enhanced expressivity needed to parse complex languages.
23
24 [PEG]: https://en.wikipedia.org/wiki/Parsing_expression_grammar
25
26 ## Getting started
27
28 The recommended way to start parsing with pest is to read the official [book].
29
30 Other helpful resources:
31
32 * API reference on [docs.rs]
33 * play with grammars and share them on our [fiddle]
34 * find previous common questions answered or ask questions on [GitHub Discussions]
35 * leave feedback, ask questions, or greet us on [Gitter] or [Discord]
36
37 [book]: https://pest.rs/book
38 [docs.rs]: https://docs.rs/pest
39 [fiddle]: https://pest.rs/#editor
40 [Gitter]: https://gitter.im/pest-parser/pest
41 [Discord]: https://discord.gg/XEGACtWpT2
42 [GitHub Discussions]: https://github.com/pest-parser/pest/discussions
43
44 ## Example
45
46 The following is an example of a grammar for a list of alphanumeric identifiers
47 where all identifiers don't start with a digit:
48
49 ```rust
50 alpha = { 'a'..'z' | 'A'..'Z' }
51 digit = { '0'..'9' }
52
53 ident = { !digit ~ (alpha | digit)+ }
54
55 ident_list = _{ ident ~ (" " ~ ident)* }
56 // ^
57 // ident_list rule is silent which means it produces no tokens
58 ```
59
60 Grammars are saved in separate .pest files which are never mixed with procedural
61 code. This results in an always up-to-date formalization of a language that is
62 easy to read and maintain.
63
64 ## Meaningful error reporting
65
66 Based on the grammar definition, the parser also includes automatic error
67 reporting. For the example above, the input `"123"` will result in:
68
69 ```
70 thread 'main' panicked at ' --> 1:1
71 |
72 1 | 123
73 | ^---
74 |
75 = unexpected digit', src/main.rs:12
76 ```
77 while `"ab *"` will result in:
78 ```
79 thread 'main' panicked at ' --> 1:1
80 |
81 1 | ab *
82 | ^---
83 |
84 = expected ident', src/main.rs:12
85 ```
86
87 These error messages can be obtained from their default `Display` implementation,
88 e.g. `panic!("{}", parser_result.unwrap_err())` or `println!("{}", e)`.
89
90 ## Pairs API
91
92 The grammar can be used to derive a `Parser` implementation automatically.
93 Parsing returns an iterator of nested token pairs:
94
95 ```rust
96 extern crate pest;
97 #[macro_use]
98 extern crate pest_derive;
99
100 use pest::Parser;
101
102 #[derive(Parser)]
103 #[grammar = "ident.pest"]
104 struct IdentParser;
105
106 fn main() {
107    let pairs = IdentParser::parse(Rule::ident_list, "a1 b2").unwrap_or_else(|e| panic!("{}", e));
108
109 // Because ident_list is silent, the iterator will contain idents
110 for pair in pairs {
111 // A pair is a combination of the rule which matched and a span of input
112 println!("Rule: {:?}", pair.as_rule());
113 println!("Span: {:?}", pair.as_span());
114 println!("Text: {}", pair.as_str());
115
116 // A pair can be converted to an iterator of the tokens which make it up:
117 for inner_pair in pair.into_inner() {
118 match inner_pair.as_rule() {
119 Rule::alpha => println!("Letter: {}", inner_pair.as_str()),
120 Rule::digit => println!("Digit: {}", inner_pair.as_str()),
121 _ => unreachable!()
122 };
123 }
124 }
125 }
126 ```
127
128 This produces the following output:
129 ```
130 Rule: ident
131 Span: Span { start: 0, end: 2 }
132 Text: a1
133 Letter: a
134 Digit: 1
135 Rule: ident
136 Span: Span { start: 3, end: 5 }
137 Text: b2
138 Letter: b
139 Digit: 2
140 ```
141
142 ### Defining multiple parsers in a single file
143 The current automatic `Parser` derivation will produce the `Rule` enum
144 which would have name conflicts if one tried to define multiple such structs
145 that automatically derive `Parser`. One possible way around it is to put each
146 parser struct in a separate namespace:
147
148 ```rust
149 mod a {
150 #[derive(Parser)]
151 #[grammar = "a.pest"]
152 pub struct ParserA;
153 }
154 mod b {
155 #[derive(Parser)]
156 #[grammar = "b.pest"]
157 pub struct ParserB;
158 }
159 ```
160
161 ## Other features
162
163 * Precedence climbing
164 * Input handling
165 * Custom errors
166 * Runs on stable Rust
167
168 ## Projects using pest
169
170 You can find more projects and ecosystem tools in the [awesome-pest](https://github.com/pest-parser/awesome-pest) repo.
171
172 * [pest_meta](https://github.com/pest-parser/pest/blob/master/meta/src/grammar.pest) (bootstrapped)
173 * [AshPaper](https://github.com/shnewto/ashpaper)
174 * [brain](https://github.com/brain-lang/brain)
175 * [cicada](https://github.com/mitnk/cicada)
176 * [comrak](https://github.com/kivikakk/comrak)
177 * [elastic-rs](https://github.com/cch123/elastic-rs)
178 * [graphql-parser](https://github.com/Keats/graphql-parser)
179 * [handlebars-rust](https://github.com/sunng87/handlebars-rust)
180 * [hexdino](https://github.com/Luz/hexdino)
181 * [Huia](https://gitlab.com/jimsy/huia/)
182 * [insta](https://github.com/mitsuhiko/insta)
183 * [jql](https://github.com/yamafaktory/jql)
184 * [json5-rs](https://github.com/callum-oakley/json5-rs)
185 * [mt940](https://github.com/svenstaro/mt940-rs)
186 * [Myoxine](https://github.com/d3bate/myoxine)
187 * [py_literal](https://github.com/jturner314/py_literal)
188 * [rouler](https://github.com/jarcane/rouler)
189 * [RuSh](https://github.com/lwandrebeck/RuSh)
190 * [rs_pbrt](https://github.com/wahn/rs_pbrt)
191 * [stache](https://github.com/dgraham/stache)
192 * [tera](https://github.com/Keats/tera)
193 * [ui_gen](https://github.com/emoon/ui_gen)
194 * [ukhasnet-parser](https://github.com/adamgreig/ukhasnet-parser)
195 * [ZoKrates](https://github.com/ZoKrates/ZoKrates)
196 * [Vector](https://github.com/timberio/vector)
197 * [AutoCorrect](https://github.com/huacnlee/autocorrect)
198 * [yaml-peg](https://github.com/aofdev/yaml-peg)
199 * [qubit](https://github.com/abhimanyu003/qubit)
200 * [caith](https://github.com/Geobert/caith) (a dice roller crate)
201 * [Melody](https://github.com/yoav-lavi/melody)
202 * [json5-nodes](https://github.com/jlyonsmith/json5-nodes)
203
204 ## Minimum Supported Rust Version (MSRV)
205
206 This library should always compile with default features on **Rust 1.60.0**
207 or **Rust 1.61** with `const_prec_climber`.
208
209 ## no_std support
210
211 The `pest` and `pest_derive` crates can be built without the Rust standard
212 library and target embedded environments. To do so, you need to disable
213 their default features. In your `Cargo.toml`, you can specify it as follows:
214
215 ```toml
216 [dependencies]
217 # ...
218 pest = { version = "2", default-features = false }
219 pest_derive = { version = "2", default-features = false }
220 ```
221
222 If you want to build these crates in the pest repository's workspace, you can
223 pass the `--no-default-features` flag to `cargo` and specify these crates using
224 the `--package` (`-p`) flag. For example:
225
226 ```bash
227 $ cargo build --target thumbv7em-none-eabihf --no-default-features -p pest
228 $ cargo bootstrap
229 $ cargo build --target thumbv7em-none-eabihf --no-default-features -p pest_derive
230 ```
231
232 ## Special thanks
233
234 A special round of applause goes to prof. Marius Minea for his guidance and all
235 pest contributors, some of which being none other than my friends.