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}