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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
//! # Parsey
//!
//! `parsey` is a lightweight, `no_std` framework for creating custom parsers and abstract syntax trees (ASTs).
//! It provides two key traits: [`Parser`][crate::Parser] and [`Ast`][crate::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`][crate::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`][crate::Parser] trait,
//! which processes tokens and produces an AST.
//!
//! ```rust
//! use parsey::{Parser, Ast};
//!
//! #[derive(Debug)]
//! pub enum Token {
//! Zero,
//! One,
//! }
//!
//! #[derive(Debug)]
//! pub struct MyError;
//!
//! pub struct MyParser {
//! tokens: Vec<Token>,
//! }
//!
//! impl MyParser {
//! pub fn new(mut tokens: Vec<Token>) -> Self {
//! tokens.reverse();
//! Self { tokens }
//! }
//! }
//!
//! impl parsey::Parser<Token, MyError> for MyParser {
//! type Root = Program;
//! }
//!
//! impl Iterator for MyParser {
//! type Item = Token;
//!
//! fn next(&mut self) -> Option<Self::Item> {
//! self.tokens.pop()
//! }
//! }
//! ```
//!
//! ### Step 2: Define the AST Nodes
//! Create the structure for your AST by implementing the [`Ast`][crate::Ast] trait for each node.
//! The root node must match the type defined in `Parser::Root`.
//!
//! ```rust
//! #[derive(Debug)]
//! pub struct Program(Vec<Statement>);
//!
//! #[derive(Debug)]
//! pub enum Statement {
//! ZeroZero,
//! ZeroOne,
//! OneZero,
//! OneOne,
//! }
//!
//! impl parsey::Ast<Token, MyError> for Program {
//! fn parse<P>(parser: &mut std::iter::Peekable<P>) -> Result<Self, MyError>
//! where
//! P: parsey::Parser<Token, MyError>,
//! {
//! let mut statements = vec![];
//! while parser.peek().is_some() {
//! statements.push(Statement::parse(parser)?);
//! }
//! Ok(Self(statements))
//! }
//! }
//!
//! impl parsey::Ast<Token, MyError> for Statement {
//! fn parse<P>(parser: &mut std::iter::Peekable<P>) -> Result<Self, MyError>
//! where
//! P: parsey::Parser<Token, MyError>,
//! {
//! match parser.next() {
//! Some(Token::Zero) => match parser.next() {
//! Some(Token::Zero) => Ok(Statement::ZeroZero),
//! Some(Token::One) => Ok(Statement::ZeroOne),
//! _ => Err(MyError),
//! },
//! Some(Token::One) => match parser.next() {
//! Some(Token::Zero) => Ok(Statement::OneZero),
//! Some(Token::One) => Ok(Statement::OneOne),
//! _ => Err(MyError),
//! },
//! _ => Err(MyError),
//! }
//! }
//! }
//! ```
//!
//! ### Step 3: Parse Tokens
//! Use your parser to parse a sequence of tokens into an AST.
//!
//! ```rust
//! fn main() {
//! let tokens = vec![Token::One, Token::Zero, Token::One, Token::Zero];
//! let parser = MyParser::new(tokens);
//! let ast = parsey::Parser::parse(parser);
//! match ast {
//! Ok(ast) => println!("Parsed AST: {:?}", ast),
//! Err(e) => eprintln!("Parsing error: {:?}", e),
//! }
//! }
//! ```
use Peekable;
/// A trait representing a generic parser that consumes tokens and produces an AST.
///
/// This trait provides an abstraction for parsers that process tokens.
///
/// # Type Parameters
/// - `Token`: The type of tokens being parsed.
/// - `Error`: The type of errors that may occur during parsing.
/// A trait representing a component of an abstract syntax tree (AST).
///
/// This trait defines the interface for parsing a specific node or component of the AST
/// from a sequence of tokens.
///
/// # Type Parameters
/// - `Token`: The type of tokens being parsed.
/// - `Error`: The type of errors that may occur during parsing.