1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
//! # Parsey
//!
//! `parsey` is a lightweight, `no_std` framework for creating custom parsers and abstract syntax trees (ASTs).
//! It provides two key traits: [`Parser`] and [`Ast`], which together form the foundation
//! for building parsers and representing the structure of parsed data.
//!
//! ## Key Features
//! - **Generic Parsing Framework:** Abstracts the process of parsing tokens into structured data.
//! - **Customizable AST Nodes:** Easily define nodes of your AST by implementing the [`Ast`] trait.
//! - **Integration with `no_std`:** Ideal for embedded or constrained environments.
//!
//! ## Getting Started
//!
//! ### Step 1: Implement the `Parser` Trait
//! Define a struct that will serve as your parser. This struct must implement the [`Parser`] trait,
//! which processes tokens and produces an AST.
//!
//! ```rust,ignore
//! use parsey::{Ast, Parser, TokenStream};
//!
//! #[derive(Debug, PartialEq)]
//! pub enum MyToken {
//! Zero,
//! One,
//! }
//!
//! #[derive(Debug, PartialEq)]
//! pub struct MyError;
//!
//! pub struct MyParser {
//! tokens: Vec<MyToken>,
//! }
//!
//! impl MyParser {
//! pub fn new(mut tokens: Vec<MyToken>) -> Self {
//! tokens.into()
//! }
//! }
//!
//! impl Parser<MyToken, MyError> for MyParser {
//! type Root = Root;
//!
//! fn expect(
//! peekable_parser: &mut TokenStream<Self, MyToken, MyError>,
//! token: MyToken,
//! ) -> Result<(), MyError> {
//! if peekable_parser.peek() == Some(&token) {
//! peekable_parser.next();
//! Ok(())
//! } else {
//! Err(MyError)
//! }
//! }
//! }
//!
//! impl Iterator for MyParser {
//! type Item = MyToken;
//!
//! fn next(&mut self) -> Option<Self::Item> {
//! self.tokens.pop()
//! }
//! }
//!
//! impl From<Vec<MyToken>> for MyParser {
//! fn from(mut value: Vec<MyToken>) -> Self {
//! value.reverse();
//! Self { tokens: value }
//! }
//! }
//! ```
//!
//! ### Step 2: Define the AST Nodes
//! Create the structure for your AST by implementing the [`Ast`] trait for each node.
//! The root node must match the type defined in `Parser::Root`.
//!
//! ```rust,ignore
//! #[derive(Debug, PartialEq)]
//! pub struct Root(Vec<TwoBit>);
//!
//! #[derive(Debug, PartialEq)]
//! pub enum TwoBit {
//! ZeroZero,
//! ZeroOne,
//! OneZero,
//! OneOne,
//! }
//!
//! impl Ast<MyToken, MyError> for Root {
//! fn parse<P>(token_stream: &mut TokenStream<P, MyToken, MyError>) -> Result<Self, MyError>
//! where
//! P: Parser<MyToken, MyError>,
//! {
//! let mut two_bits = vec![];
//! while token_stream.peek().is_some() {
//! two_bits.push(TwoBit::parse(token_stream)?);
//! }
//! Ok(Self(two_bits))
//! }
//! }
//!
//! impl parsey::Ast<MyToken, MyError> for TwoBit {
//! fn parse<P>(token_stream: &mut TokenStream<P, MyToken, MyError>) -> Result<Self, MyError>
//! where
//! P: parsey::Parser<MyToken, MyError>,
//! {
//! match token_stream.next() {
//! Some(MyToken::Zero) => match token_stream.next() {
//! Some(MyToken::Zero) => Ok(TwoBit::ZeroZero),
//! Some(MyToken::One) => Ok(TwoBit::ZeroOne),
//! _ => Err(MyError),
//! },
//! Some(MyToken::One) => match token_stream.next() {
//! Some(MyToken::Zero) => Ok(TwoBit::OneZero),
//! Some(MyToken::One) => Ok(TwoBit::OneOne),
//! _ => Err(MyError),
//! },
//! _ => Err(MyError),
//! }
//! }
//! }
//! ```
//!
//! ### Step 3: Parse Tokens
//! Use your parser to parse a sequence of tokens into an AST.
//!
//! ```rust,ignore
//! fn main() {
//! use MyToken::{One, Zero};
//! use TwoBit::{OneOne, OneZero, ZeroOne, ZeroZero};
//!
//! let tokens = vec![Zero, Zero, Zero, One, One, Zero, One, One];
//! let parser = MyParser::new(tokens);
//! let ast = parser.parse().unwrap();
//! assert_eq!(ast, Root(vec![ZeroZero, ZeroOne, OneZero, OneOne]));
//! }
//! ```
pub use Ast;
pub use Parser;
pub use TokenStream;