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
use proc_macro::*;
#[proc_macro]
pub fn pattern(input: TokenStream) -> TokenStream {
let input = input.into_iter().collect::<Vec<_>>();
let string = match &input[..] {
[TokenTree::Literal(lit)] => parse_str_literal(&lit),
_ => panic!("expected a single string literal to parse"),
};
let pattern = match pattern::parse(&string) {
Ok(pattern) => pattern,
Err(err) => panic!("invalid pattern syntax: {}", err),
};
format!("{{ use ::pelite::pattern::Atom::*; &{:?} }}", pattern).parse().unwrap()
}
fn parse_str_literal(input: &Literal) -> String {
let input = input.to_string();
let mut chars = input.chars();
let mut string = String::new();
if chars.next() != Some('"') {
panic!("expected string literal starting with a `\"` and no extraneous whitespace");
}
loop {
let chr = match chars.next() {
Some('\\') => {
match chars.next() {
Some('\\') => '\\',
Some('\'') => '\'',
Some('\"') => '\"',
Some('t') => '\t',
Some('r') => '\r',
Some('n') => '\n',
Some('u') => panic!("unicode escape sequence not supported"),
Some(chr) => panic!("unknown escape sequence: {}", chr),
None => panic!(""),
}
},
Some('"') => break,
Some(chr) => chr,
None => panic!("unexpected end of string literal, missing `\"` terminator?"),
};
string.push(chr);
}
string
}
#[allow(unused)]
mod pattern;