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
use quote::{format_ident, quote_spanned, TokenStreamExt, ToTokens};
use proc_macro2::{Span, Literal};
use syn::parse::{ParseStream, Result};
use syn::{Token, Expr, LitChar, LitBool, LitStr, LitInt, bracketed, braced};
use syn::token::{Bracket,Brace};
use crate::xtext::XtextClass;
pub enum XtextClassAttr {
Cl(XtextClass),
F(Bracket,String,Expr),
E(Brace,Expr),
B(LitBool,bool),
C(LitChar,char),
U(LitInt,u64),
S(LitStr,String),
}
impl XtextClassAttr {
pub fn span(&self) -> Span {
match self {
XtextClassAttr::Cl(cl) => { cl.span() },
XtextClassAttr::F(b,_,_) => { b.span },
XtextClassAttr::E(b,_) => { b.span },
XtextClassAttr::B(v,_) => { v.span },
XtextClassAttr::C(v,_) => { v.span() },
XtextClassAttr::U(v,_) => { v.span() },
XtextClassAttr::S(v,_) => { v.span() },
}
}
pub fn parse(input: ParseStream, key: String) -> Result<Self> {
if input.peek(Bracket) {
let _content;
let content2;
let bracket_token1:Bracket = bracketed!(_content in input);
let _bracket_token2:Bracket = bracketed!(content2 in _content);
let e: Expr = content2.parse()?;
Ok(XtextClassAttr::F(bracket_token1,key,e))
} else if input.peek(Brace) {
let _content;
let content2;
let brace_token1:Brace = braced!(_content in input);
let _brace_token2:Brace = braced!(content2 in _content);
let e: Expr = content2.parse()?;
Ok(XtextClassAttr::E(brace_token1,e))
} else if input.peek(LitBool) {
let b: LitBool = input.parse()?;
Ok(XtextClassAttr::B(b.clone(),b.value))
} else if input.peek(LitInt) {
let b: LitInt = input.parse()?;
let u: u64 = b.base10_parse()?;
Ok(XtextClassAttr::U(b.clone(),u))
} else if input.peek(LitChar) {
let b: LitChar = input.parse()?;
Ok(XtextClassAttr::C(b.clone(),b.value()))
} else if input.peek(Token![<]) && input.peek2(Token![!]) {
let cl: XtextClass = input.parse()?;
Ok(XtextClassAttr::Cl(cl))
} else {
let val: LitStr = input.parse()?;
Ok(XtextClassAttr::S(val.clone(),val.value()))
}
}
}
impl ToTokens for XtextClassAttr {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
let span = self.span();
match self {
XtextClassAttr::S(_,s) => {
let l: Literal = Literal::string(&s);
(quote_spanned!{span=>
#l.to_string()
}).to_tokens(tokens);
}, XtextClassAttr::B(_,e) => {
let e = format_ident!("{}", e, span=span);
e.to_tokens(tokens);
}, XtextClassAttr::Cl(cl) => {
cl.to_tokens(tokens);
}, XtextClassAttr::C(_,e) => {
let l: Literal = Literal::character(*e);
tokens.append(l);
}, XtextClassAttr::U(_,e) => {
let l: Literal = Literal::u64_unsuffixed(*e);
tokens.append(l);
}, XtextClassAttr::F(_,f,e) => {
let coerce = format_ident!("to_{}", f, span=span);
(quote_spanned!{span=>
#e.#coerce()
}).to_tokens(tokens);
}, XtextClassAttr::E(_,e) => {
e.to_tokens(tokens);
}
}
}
}