parse_it/lib.rs
1//! # Parse It
2//!
3//! *A user-friendly, opinionated parser generator for Rust.*
4//!
5//! ## Example
6//!
7//! ```rust
8//! use parse_it::{ParseIt, parse_it};
9//!
10//! #[derive(Debug, Clone)]
11//! pub enum Instr {
12//! Left,
13//! Right,
14//! Incr,
15//! Decr,
16//! Read,
17//! Write,
18//! Loop(Vec<Self>),
19//! }
20//!
21//! parse_it! {
22//! #[parser]
23//! mod parse {
24//! use super::Instr;
25//!
26//! type Lexer = parse_it::CharLexer;
27//!
28//! pub Brainfuck -> Vec<Instr> {
29//! Primitive* => self,
30//! }
31//!
32//! Primitive -> Instr {
33//! '<' => Instr::Left,
34//! '>' => Instr::Right,
35//! '+' => Instr::Incr,
36//! '-' => Instr::Decr,
37//! ',' => Instr::Read,
38//! '.' => Instr::Write,
39//! '[' Primitive+ ']' => Instr::Loop(self)
40//! }
41//! }
42//! }
43//!
44//! fn main() {
45//! let parser = parse::Brainfuck::default();
46//! let src = "--[>--->->->++>-<<<<<-------]>--.>---------.>--..+++.>----.>+++++++++.<<.+++.------.<-.>>+";
47//! let instrs = parser.parse(src).unwrap();
48//! println!("{:?}", instrs);
49//! }
50//! ```
51#![warn(missing_docs)]
52#![allow(clippy::needless_doctest_main)]
53
54pub mod lexer;
55pub mod memo;
56pub mod parser;
57
58pub use parse_it_macros::parse_it;
59
60pub use crate::{
61 lexer::{CharLexer, Cursor, LexerState},
62 memo::{left_rec, memorize, Memo},
63 parser::{Error, ParserState},
64};
65
66/// A lexer.
67pub trait LexIt {
68 /// The token type.
69 type Token<'a>;
70
71 /// Create a new lexer instance.
72 fn new() -> Self;
73
74 /// Get the next token from the lexer.
75 fn next<'a>(&self, lexbuf: &mut LexerState<'a>) -> Option<Self::Token<'a>>;
76}
77
78/// A parser.
79pub trait ParseIt {
80 /// The lexer type.
81 type Lexer: LexIt + Clone;
82 /// The parser output type.
83 type Output;
84
85 /// Parse from a [`ParserState`].
86 fn parse_stream<'a>(
87 &self,
88 state: &mut ParserState<'a, Self::Lexer>,
89 ) -> Result<Self::Output, Error>;
90
91 /// Parse from a string.
92 fn parse(&self, input: &str) -> Result<Self::Output, Error> {
93 let mut state = ParserState::new(input);
94 self.parse_stream(&mut state)
95 }
96}
97
98#[doc(hidden)]
99#[macro_export]
100macro_rules! identity {
101 ($expr:expr) => {
102 $expr
103 };
104}