#![allow(dead_code)]
extern crate proc_macro;
use proc_macro::{TokenTree, Span, TokenStream, Delimiter, Group, Literal, Ident, Punct, Spacing};
use proc_macro::token_stream::IntoIter;
pub fn error_span(err: &str, span: Span) -> TokenStream {
let mut tb = TokenBuilder::new();
tb.ident_with_span("compile_error", span).add("!(").string(err).add(");");
tb.end()
}
pub fn error(err: &str) -> TokenStream {
let mut tb = TokenBuilder::new();
tb.add("compile_error!(").string(err).add(");");
tb.end()
}
pub fn error_result(err: &str) -> Result<(), TokenStream> {
Err(error(err))
}
pub fn unwrap_option(input: TokenStream) -> Result<TokenStream, TokenStream> {
let mut ty_parser = TokenParser::new(input.clone());
if ty_parser.eat_ident("Option") {
if !ty_parser.eat_punct_alone('<') {
return Err(error("Expected '<' after 'Option'"));
}
Ok(ty_parser.eat_level_or_punct('>'))
} else {
Err(input)
}
}
pub struct TokenBuilder {
pub groups: Vec<(Delimiter, TokenStream)>
}
impl TokenBuilder {
pub fn new() -> Self {
Self {
groups: vec![(Delimiter::None, TokenStream::new())]
}
}
pub fn is_empty(&self) -> bool {
self.groups.len() == 1 && self.groups[0].1.is_empty()
}
pub fn end(mut self) -> TokenStream {
if self.groups.len() != 1 {
panic!("Groups not empty, you missed a pop_group")
}
self.groups.pop().unwrap().1
}
pub fn extend(&mut self, tt: TokenTree) -> &mut Self {
self.groups.last_mut().unwrap().1.extend(Some(tt));
self
}
pub fn stream(&mut self, what: Option<TokenStream>) -> &mut Self {
if let Some(what) = what {
for c in what.into_iter() {
self.extend(c);
}
}
self
}
pub fn suf_u16(&mut self, val: u16) -> &mut Self {
self.extend(TokenTree::from(Literal::u16_suffixed(val)));
self
}
pub fn chr(&mut self, val: char) -> &mut Self {
self.extend(TokenTree::from(Literal::character(val)));
self
}
pub fn add(&mut self, what: &str) -> &mut Self {
let b = what.as_bytes();
let mut o = 0;
while o < b.len() {
let c0 = b[o] as char;
let c1 = if o + 1 < b.len() { b[o + 1] as char } else { '\0' };
match (c0, c1) {
('\r', _) | ('\n', _) | (' ', _) | ('\t', _) => { o += 1; }
('{', _) => { self.push_group(Delimiter::Brace); o += 1; },
('(', _) => { self.push_group(Delimiter::Parenthesis); o += 1; },
('[', _) => { self.push_group(Delimiter::Bracket); o += 1; },
('}', _) => { self.pop_group(Delimiter::Brace); o += 1; },
(')', _) => { self.pop_group(Delimiter::Parenthesis); o += 1; },
(']', _) => { self.pop_group(Delimiter::Bracket); o += 1; },
('<', '<') | ('>', '>') | ('&', '&') | ('|', '|') |
('-', '>') | ('=', '>') |
('<', '=') | ('>', '=') | ('=', '=') | ('!', '=') | (':', ':') |
('+', '=') | ('-', '=') | ('*', '=') | ('/', '=') | ('.', '.') => {
self.punct(std::str::from_utf8(&b[o..o + 2]).unwrap());
o += 2;
}
('+', _) | ('-', _) | ('*', _) | ('/', _) | ('#', _) |
('=', _) | ('<', _) | ('>', _) | ('?', _) | (';', _) | ('&', _) |
('^', _) | (':', _) | (',', _) | ('!', _) | ('.', _) | ('|', _) => {
self.punct(std::str::from_utf8(&b[o..o + 1]).unwrap());
o += 1;
},
('0', 'x') => {
let mut e = o + 2;
let mut out: u64 = 0;
while e < b.len() {
match b[e] {
b'0'..=b'9' => out = (out << 4) | (b[e] - b'0') as u64,
b'a'..=b'f' => out = (out << 4) | (b[e] - b'a' + 10) as u64,
b'A'..=b'F' => out = (out << 4) | (b[e] - b'A' + 10) as u64,
b'_' => (),
_ => break,
};
e += 1;
}
self.suf_u64(out);
o = e;
}
('0'..='9', _) => {
let mut e = o + 1;
while e < b.len() {
match b[e] {
b'0'..=b'9' => e += 1,
_ => break,
}
}
let num = std::str::from_utf8(&b[o..e]).unwrap();
self.unsuf_usize(num.parse().expect("Can't parse usize number"));
o = e;
}
('"', _) => {
let mut e = o + 1;
while e < b.len() {
if b[e] == b'"' { break; }
e += 1;
}
self.string(std::str::from_utf8(&b[o + 1..e]).unwrap());
o = e + 1;
}
('\'', _) => {
let mut e = o + 1;
while e < b.len() {
if !(b[e] as char).is_alphanumeric() && b[e] != b'_' {
break;
}
e += 1;
}
if o == e {
panic!("Unexpected character {:?}", b[e] as char);
}
let ident = std::str::from_utf8(&b[o..e]).unwrap();
self.lifetime_mark();
self.ident(ident);
o = e;
}
_ => {
let mut e = o;
while e < b.len() {
if !(b[e] as char).is_alphanumeric() && b[e] != b'_' {
break;
}
e += 1;
}
if o == e {
panic!("Unexpected character {:?}", b[e] as char);
}
let ident = std::str::from_utf8(&b[o..e]).unwrap();
self.ident(ident);
o = e;
}
}
}
self
}
pub fn add_body(&mut self, body: TokenStream) -> &mut Self {
self.push_group(Delimiter::Brace);
self.stream(Some(body));
self.pop_group(Delimiter::Brace);
self
}
pub fn ident(&mut self, id: &str) -> &mut Self {
self.extend(TokenTree::from(Ident::new(id, Span::call_site())))
}
pub fn ident_with_span(&mut self, id: &str, span: Span) -> &mut Self {
self.extend(TokenTree::from(Ident::new(id, span)))
}
pub fn punct(&mut self, s: &str) -> &mut Self {
for (last, c) in s.chars().identify_last() {
self.extend(TokenTree::from(Punct::new(c, if last { Spacing::Alone } else { Spacing::Joint })));
}
self
}
pub fn lifetime_mark(&mut self) -> &mut Self {
self.extend(TokenTree::from(Punct::new('\'', Spacing::Joint)));
self
}
pub fn sep(&mut self) -> &mut Self {
self.extend(TokenTree::from(Punct::new(':', Spacing::Joint)));
self.extend(TokenTree::from(Punct::new(':', Spacing::Alone)));
self
}
pub fn string(&mut self, val: &str) -> &mut Self {
self.extend(TokenTree::from(Literal::string(val)))
}
pub fn unsuf_usize(&mut self, val: usize) -> &mut Self {
self.extend(TokenTree::from(Literal::usize_unsuffixed(val)))
}
pub fn suf_u64(&mut self, val: u64) -> &mut Self {
self.extend(TokenTree::from(Literal::u64_suffixed(val)))
}
pub fn push_group(&mut self, delim: Delimiter) -> &mut Self {
self.groups.push((delim, TokenStream::new()));
self
}
pub fn pop_group(&mut self, delim: Delimiter) -> &mut Self {
if self.groups.len() < 2 {
panic!("pop_group stack is empty {}", self.groups.len());
}
let ts = self.groups.pop().unwrap();
if ts.0 != delim {
panic!("pop_group Delimiter mismatch, got {:?} expected {:?}", ts.0, delim);
}
self.extend(TokenTree::from(Group::new(delim, ts.1)));
self
}
pub fn error<T: Into<String>>(&mut self, msg: T) -> &mut Self {
let msg = msg.into();
self.extend(TokenTree::from(Literal::string(&msg)));
self
}
pub fn error_span<T: Into<String>>(&mut self, msg: T, span: Span) -> &mut Self {
let msg = msg.into();
self.extend(TokenTree::from(Literal::string(&msg)));
self
}
pub fn unexpected(&mut self, tt: TokenTree) -> &mut Self {
self.extend(TokenTree::from(Literal::string("Unexpected token")));
self
}
}
impl Default for TokenBuilder {
fn default() -> Self {
Self::new()
}
}
pub trait IdentifyLast: Iterator + Sized {
fn identify_last(self) -> Iter<Self>;
}
impl<It> IdentifyLast for It where It: Iterator {
fn identify_last(mut self) -> Iter<Self> {
let e = self.next();
Iter {
iter: self,
buffer: e,
}
}
}
pub struct Iter<It> where It: Iterator {
iter: It,
buffer: Option<It::Item>,
}
impl<It> Iterator for Iter<It> where It: Iterator {
type Item = (bool, It::Item);
fn next(&mut self) -> Option<Self::Item> {
match self.buffer.take() {
None => None,
Some(e) => {
match self.iter.next() {
None => Some((true, e)),
Some(f) => {
self.buffer = Some(f);
Some((false, e))
},
}
},
}
}
}
#[derive(Debug)]
pub struct Attribute {
pub name: String,
pub args: Option<TokenStream>
}
pub struct StructField {
pub name: String,
pub ty: TokenStream,
pub attrs: Vec<Attribute>
}
pub struct TokenParser {
iter_stack: Vec<IntoIter>,
pub current: Option<TokenTree>
}
impl TokenParser {
pub fn new(start: TokenStream) -> Self {
let mut ret = Self { iter_stack: vec![start.into_iter()], current: None };
ret.advance();
ret
}
pub fn advance(&mut self) {
if let Some(tok) = self.iter_stack.last_mut().unwrap().next() {
self.current = Some(tok);
} else {
self.current = None;
}
}
pub fn unexpected(&self) -> TokenStream {
error("Unexpected token")
}
pub fn is_delim(&mut self, delim: Delimiter) -> bool {
if let Some(TokenTree::Group(group)) = &self.current {
group.delimiter() == delim
} else {
false
}
}
pub fn open_delim(&mut self, delim: Delimiter) -> bool {
if let Some(TokenTree::Group(group)) = &self.current {
if group.delimiter() == delim {
self.iter_stack.push(group.stream().into_iter());
self.advance();
return true;
}
}
false
}
pub fn open_brace(&mut self) -> bool {
self.open_delim(Delimiter::Brace)
}
pub fn is_eot(&mut self) -> bool {
self.current.is_none() && self.iter_stack.is_empty()
}
pub fn eat_eot(&mut self) -> bool {
if self.is_eot() {
self.iter_stack.pop();
if !self.iter_stack.is_empty() {
self.advance()
}
return true;
}
false
}
pub fn eat_level(&mut self) -> TokenStream {
let mut tb = TokenBuilder::new();
while !self.eat_eot() {
tb.extend(self.current.clone().unwrap());
self.advance();
}
tb.end()
}
pub fn eat_level_or_punct(&mut self, what: char) -> TokenStream {
let mut tb = TokenBuilder::new();
while !self.eat_eot() {
if self.is_punct_alone(what) {
self.advance();
return tb.end();
}
tb.extend(self.current.clone().unwrap());
self.advance();
}
tb.end()
}
pub fn eat_ident(&mut self, what: &str) -> bool {
if let Some(TokenTree::Ident(ident)) = &self.current {
if ident.to_string() == what {
self.advance();
return true;
}
}
false
}
pub fn is_literal(&mut self) -> bool {
if let Some(TokenTree::Literal(_)) = &self.current {
true
} else {
false
}
}
pub fn eat_literal(&mut self) -> Option<Literal> {
if let Some(TokenTree::Literal(lit)) = &self.current {
let ret = Some(lit.clone());
self.advance();
ret
} else {
None
}
}
pub fn span(&self) -> Option<Span> {
self.current.as_ref().map(|current| current.span())
}
pub fn is_punct_alone(&mut self, what: char) -> bool {
if let Some(TokenTree::Punct(current)) = &self.current {
current.as_char() == what && current.spacing() == Spacing::Alone
} else {
false
}
}
pub fn eat_punct_alone(&mut self, what: char) -> bool {
if self.is_punct_alone(what) {
self.advance();
true
} else {
false
}
}
pub fn eat_any_ident(&mut self) -> Option<String> {
if let Some(TokenTree::Ident(ident)) = &self.current {
let ret = Some(ident.to_string());
self.advance();
ret
} else {
None
}
}
pub fn eat_any_ident_with_span(&mut self) -> Option<(String, Span)> {
if let Some(TokenTree::Ident(ident)) = &self.current {
let ret = Some((ident.to_string(), self.span().unwrap()));
self.advance();
ret
} else {
None
}
}
pub fn eat_double_colon_destruct(&mut self) -> bool {
if let Some(TokenTree::Punct(current)) = &self.current {
if current.as_char() == ':' && current.spacing() == Spacing::Joint {
self.advance();
if let Some(TokenTree::Punct(current)) = &self.current {
if current.as_char() == ':' && current.spacing() == Spacing::Alone {
self.advance();
return true;
}
}
}
}
false
}
pub fn eat_struct_field(&mut self) -> Option<StructField> {
let attrs = self.eat_attributes();
self.eat_ident("pub");
if let Some(field) = self.eat_any_ident() {
if self.eat_punct_alone(':') {
if let Some(ty) = self.eat_type() {
return Some(StructField { name: field, ty, attrs });
}
}
}
None
}
pub fn eat_attributes(&mut self) -> Vec<Attribute> {
let mut results = Vec::new();
while self.eat_punct_alone('#') {
if !self.open_bracket() {
break;
}
let mut assign_form = false;
while let Some(ident) = self.eat_any_ident() {
if self.eat_punct_alone('=') {
let level = self.eat_level();
results.push(Attribute { name: ident, args: Some(level) });
assign_form = true;
break;
}
if !self.open_paren() && !self.open_brace() {
results.push(Attribute { name: ident, args: None });
break;
}
results.push(Attribute { name: ident, args: Some(self.eat_level()) });
self.eat_punct_alone(',');
}
if !assign_form && !self.eat_eot() {
break;
}
}
results
}
pub fn eat_all_struct_fields(&mut self) -> Option<Vec<StructField>> {
if self.open_brace() {
let mut fields = Vec::new();
while !self.eat_eot() {
if let Some(sf) = self.eat_struct_field() {
fields.push(sf);
self.eat_punct_alone(',');
} else {
return None;
}
}
Some(fields)
} else {
None
}
}
pub fn eat_body(&mut self) -> Option<TokenStream> {
let mut tb = TokenBuilder::new();
let mut brace_count = 0;
if !self.open_brace() {
return None;
}
brace_count += 1;
tb.add("{");
while brace_count > 0 {
if self.eat_eot() {
return None;
}
if self.is_delim(Delimiter::Brace) {
if self.open_brace() {
brace_count += 1;
tb.add("{");
} else {
brace_count -= 1;
tb.add("}");
}
} else {
if let Some(current) = &self.current {
tb.extend(current.clone());
}
self.advance();
}
}
Some(tb.end())
}
pub fn eat_generic(&mut self) -> Option<TokenStream> {
let mut tb = TokenBuilder::new();
if self.eat_punct_alone('<') {
tb.add("<");
let mut stack = 1;
while stack > 0 {
if self.eat_punct_alone('<') {
tb.add("<");
stack += 1;
} else if self.eat_punct_alone('>') {
tb.add(">");
stack -= 1;
} else if self.eat_eot() {
return None;
} else {
if let Some(current) = &self.current {
tb.extend(current.clone());
}
self.advance();
}
}
return Some(tb.end());
}
None
}
pub fn eat_where_clause(&mut self, generic: Option<&str>) -> Option<TokenStream> {
let mut tb = TokenBuilder::new();
if self.eat_ident("where") {
tb.add("where");
if let Some(generic) = generic {
tb.add(generic);
}
if self.eat_punct_alone('{') {
tb.add("{");
let mut stack = 1;
while stack > 0 {
if self.eat_punct_alone('{') {
tb.add("{");
stack += 1;
} else if self.eat_punct_alone('}') {
tb.add("}");
stack -= 1;
} else if self.eat_eot() {
return None;
} else {
if let Some(current) = &self.current {
tb.extend(current.clone());
}
self.advance();
}
}
}
Some(tb.end())
} else {
None
}
}
pub fn eat_all_types(&mut self) -> Option<Vec<TokenStream>> {
if self.open_paren() {
let mut ret = Vec::new();
while !self.eat_eot() {
self.eat_ident("pub");
if let Some(tt) = self.eat_type() {
ret.push(tt);
self.eat_punct_alone(',');
} else {
return None;
}
}
Some(ret)
} else {
None
}
}
pub fn eat_type(&mut self) -> Option<TokenStream> {
let mut tb = TokenBuilder::new();
if self.eat_punct_alone('&') {
tb.add("&");
if self.eat_punct_any('\'') {
tb.lifetime_mark();
if let Some((ty, span)) = self.eat_any_ident_with_span() {
tb.ident_with_span(&ty, span);
}
}
}
if self.open_bracket() {
tb.add("[");
while !self.eat_eot() {
if let Some(current) = &self.current {
tb.extend(current.clone());
}
self.advance();
}
tb.add("]");
Some(tb.end())
} else if self.open_paren() {
tb.add("(");
while !self.eat_eot() {
tb.stream(self.eat_type());
self.eat_punct_alone(',');
}
tb.add(")");
Some(tb.end())
} else if let Some((ty, span)) = self.eat_any_ident_with_span() {
tb.ident_with_span(&ty, span);
if ty == "dyn" {
if let Some((ty, span)) = self.eat_any_ident_with_span() {
tb.ident_with_span(&ty, span);
}
}
tb.stream(self.eat_generic());
Some(tb.end())
} else {
None
}
}
pub fn open_bracket(&mut self) -> bool {
self.open_delim(Delimiter::Bracket)
}
pub fn open_paren(&mut self) -> bool {
self.open_delim(Delimiter::Parenthesis)
}
pub fn starts_with<T: Into<String>>(&mut self, what: T) -> bool {
let what = what.into();
let mut i = 0;
while i < what.len() {
if let Some(TokenTree::Ident(ident)) = &self.current {
if ident.to_string().starts_with(&what[i..]) {
return true;
}
}
i += 1;
}
false
}
pub fn eat_punct_any(&mut self, what: char) -> bool {
if let Some(TokenTree::Punct(current)) = &self.current {
current.as_char() == what
} else {
false
}
}
pub fn error<T: Into<String>>(&mut self, msg: T) -> TokenStream {
let mut tb = TokenBuilder::new();
let msg = msg.into();
tb.error(msg);
tb.end()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Visibility {
Public,
Private,
}