enum_lexer/
lib.rs

1//! # Enum Lexer
2//! 
3//! A proc_macro lexer generator. using `enum`-like syntax.
4//! 
5//! ## Write a lexer
6//! 
7//! ```no_run
8//! #![feature(exclusive_range_pattern)]
9//!
10//! use enum_lexer::enum_lexer;
11//!
12//! enum_lexer! {
13//!     #[derive(Debug, Eq, PartialEq)]
14//!     enum lexer {
15//!         Ident(String): {
16//!             r"[A-Za-z_][A-Za-z_0-9]*" => Ident(text),
17//!         }
18//!         LitInt(usize): {
19//!             r"[0-9][0-9]*" =>
20//!                 LitInt(text.parse::<usize>()?), // default error type is Box<dyn Error>
21//!         }
22//!         Op(char): {
23//!             r"\+" => Op('+'),
24//!             r"\-" => Op('-'),
25//!         }
26//!         Def: r"def",
27//!         Let: r"let",
28//!         Group(Vec<Token>, char) : {
29//!             r"\(" => {
30//!                 Group(read_group()?, '(')       // construct a token tree within '(', ')'.
31//!             }
32//!             r"\)" => { panic!("error") }
33//!         }
34//!         COMMENTS: {                             // COMMENTS will be ignored
35//!             r"//.*?\n" => !,
36//!             r"/\*.*?\*/" => !,
37//!         }
38//!     }
39//! }
40//! ```
41//! 
42//! This will generate struct and enum like:
43//! 
44//! ```ignore
45//! mod lexer {
46//!      #[derive(Debug, Eq, PartialEq)]
47//!      pub struct Token {
48//!          pub inner: TokenInner,
49//!          pub span: Span,
50//!      }
51//!      
52//!      #[derive(Debug, Eq, PartialEq)]
53//!      pub enum TokenInner {
54//!          Ident(String),
55//!          LitInt(usize),
56//!          Op(char),
57//!          Def,
58//!          Let,
59//!          Group(Vec<Token>, char),
60//!      }
61//!      pub struct TokenIterator{...}
62//!      pub type LexError = Box<&dyn Error>;
63//!      pub fn parse_str(src: &str) -> Result<TokenIterator>;
64//! }
65//! ```
66//! ## Usage
67//! 
68//! ```ignore
69//! let vec: lexer::Result<Vec<_>> =
70//!     lexer::parse_str(r#"
71//!         let a = 10 + (1 + 2) // alpha
72//!     "#).unwrap().collect();
73//! 
74//! println!("{:?}", vec);
75//! ```
76//! 
77//! ## Customizing Error Types
78//! 
79//! ```ignore
80//! enum_lexer! {
81//!     type LexError = MyError;
82//!     enum lexer {
83//!         LitStr: "\".*?\""
84//!     }
85//! }
86//! ```
87//! 
88
89mod cursor;
90
91pub use enum_lexer_macro::enum_lexer;
92
93pub use enum_lexer_macro::enum_lexer_test;
94
95pub use cursor::*;
96
97use std::{ fmt };
98
99#[derive(Debug, Clone)]
100pub struct SpanError(pub Span);
101
102impl std::error::Error for SpanError {
103    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
104        None
105    }
106}
107
108impl std::fmt::Display for SpanError {
109    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
110        write!(f, "lexer error at {:?}", self.0)
111    }
112}
113
114#[derive(Debug, Clone)]
115pub struct GroupError();
116
117impl std::error::Error for GroupError {
118    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
119        None
120    }
121}
122
123impl std::fmt::Display for GroupError {
124    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
125        write!(f, "brace not match")
126    }
127}