Select Git revision
exception.rs
lib.rs 7.74 KiB
#![feature(proc_macro)]
extern crate proc_macro;
extern crate proc_macro2 as pm2;
#[macro_use]
extern crate quote;
#[macro_use]
extern crate syn;
use proc_macro::TokenStream;
use syn::spanned::Spanned;
use syn::synom::Synom;
use syn::{Ident, LitInt};
use quote::ToTokens;
use std::convert::From;
use std::error::Error;
/// Procedural macro `lit`
/// Parsing a `LitInt` with compile time range checking
#[proc_macro]
pub fn lit(input: TokenStream) -> TokenStream {
let v: LitInt = syn::parse(input).unwrap();
let value = v.value();
if !(10 <= value && value < 100) {
v.span()
.unstable()
.error(format!("expected literal 10 <= x < 100, got {}", value,))
.emit();
}
From::from(v.into_tokens())
}
/// Procedural macro `lite`
/// Parsing a `LitInt` with compile time range checking
#[proc_macro]
pub fn lite(input: TokenStream) -> TokenStream {
match syn::parse::<LitInt>(input) {
Ok(v) => {
let value = v.value();
if !(10 <= value && value < 100) {
v.span()
.unstable()
.error(format!("expected literal 10 <= x < 100, got {}", value,))
.emit();
}
From::from(v.into_tokens())
}
Err(err) => {
let desc = err.description();
let tokens = quote! {
compile_error!(#desc)
};
return tokens.into();
}
}
}
enum AppKeys {
Device,
Resources,
Interrupts,
Tasks,
Idle,
Init,
}
fn to_app_keys(id: Ident) -> Option<AppKeys> {
match id.as_ref() {
"device" => Some(AppKeys::Device),
_ => None,
}
}
// struct KeyVal {
// }
// impl Synom for KeyVal {
// named!(parse -> Self, do_parse!(
// val: syn!(Punctuadet) >> (KeyVal { })
// field: syn!(Ident) >>
// _colon: punct!(:) >>
// + switch!(value!(field.as_ref()),
// "path" => map!(syn!(Path), |path| {
// + parsed_init.path = Some(path);
// + }) |
// + "resources" => map!(parse_resource_ident, |res| {
// + parsed_init.resources = Some(res);
// + }) |
// + _ => call!(|_| {
// + field.span.unstable().error(format!("Unknown field `{}`", field)).emit();
// + panic!("Unknown field `{}`", field);
// + })
// + ) >>
// + _comma: syn!(Token![,]) >>
// + (())
// ));
// }
use syn::punctuated::Punctuated;
struct KeyVal {
key: Ident,
val: pm2::TokenStream,
}
impl Synom for KeyVal {
named!(parse -> Self, do_parse!(
key: call!(Ident::parse) >>
val: call!(pm2::TokenStream::parse) >> (KeyVal { key, val })
));
}
struct KeyVals {
keyvals: Punctuated<KeyVal, Token![,]>,
}
impl Synom for KeyVals {
named!(parse -> Self, do_parse!(
keyvals: call!(Punctuated::parse_terminated_nonempty) >>
(KeyVals { keyvals })
));
}
#[proc_macro]
pub fn app(input: TokenStream) -> TokenStream {
println!("-- app --");
let k: KeyVals = syn::parse(input).unwrap();
for k in k.keyvals.into_iter() {
println!("{:?}", k.key.as_ref());
println!("{:?}", k.val);
}
// {
// Ok(app) => {
// let tokens = quote!();
// tokens.into()
// }
// Err(err) => {
// let desc = err.description();
// let tokens = quote! {
// compile_error!(#desc)
// };
// tokens.into()
// }
// }
let tokens = quote!();
tokens.into()
}
// named!(parse -> LitInt, do_parse!(
// val: syn!(LitInt) >> (val)
// ));
// /// Procedural macro `litep`
// /// Parsing a `(LitInt)` into a `LitInt` with compile time range checking
// #[proc_macro]
// pub fn litep(input: TokenStream) -> TokenStream {
// let v = do_parse!(val: parens!(call!(LitInt::parse)) >> (MyLitP { val: val.1 }));
// match v(input) {
// Ok(v) => {
// let value = v.value();
// if !(10 <= value && value < 100) {
// v.span()
// .unstable()
// .error(format!("expected literal 10 <= x < 100, got {}", value,))
// .emit();
// }
// From::from(v.into_tokens())
// }
// Err(err) => {
// let desc = err.description();
// let tokens = quote! {
// compile_error!(#desc)
// };
// return tokens.into();
// }
// }
// }
// /// MyLit
// struct MyLit {
// val: LitInt,
// }
// impl Synom for MyLit {
// named!(parse -> Self, do_parse!(
// val: syn!(LitInt) >> (MyLit { val })
// ));
// }
// #[proc_macro]
// pub fn mylit(input: TokenStream) -> TokenStream {
// let v: MyLit = syn::parse(input).unwrap();
// let value = v.val.value();
// if !(10 <= value && value < 100) {
// v.val
// .span()
// .unstable()
// .error(format!(
// "expected literal 10 <= x < 100, got {}",
// value,
// ))
// .emit();
// }
// From::from(v.val.into_tokens())
// }
// /// MyLitP
// struct MyLitP {
// val: LitInt,
// }
// impl Synom for MyLitP {
// named!(parse -> Self, do_parse!(
// val: parens!(call!(LitInt::parse)) >> (MyLitP { val: val.1 })
// ));
// }
// #[proc_macro]
// pub fn mylitp(input: TokenStream) -> TokenStream {
// match syn::parse::<MyLitP>(input) {
// Ok(v) => {
// let value: u32 = v.val.value() as u32;
// if !(10 <= value && value < 100) {
// v.val
// .span()
// .unstable()
// .error(format!(
// "expected literal 10 <= x < 100, got {}",
// value,
// ))
// .emit();
// }
// From::from(v.val.into_tokens())
// }
// Err(err) => {
// let desc = err.description();
// let tokens = quote! {
// compile_error!(#desc)
// };
// return tokens.into();
// }
// }
// }
// // /// MyLits
// // struct MyLits {
// // val: LitInt,
// // valp: LitInt,
// // }
// // impl Synom for MyLits {
// // named!(parse -> Self, do_parse!(
// // val: syn!
// // valp: parens!(call!(LitInt::parse)) >> (MyLitP { val: val.1 })
// // ));
// // }
// // #[proc_macro]
// // pub fn mylitp(input: TokenStream) -> TokenStream {
// // match syn::parse::<MyLitP>(input) {
// // Ok(v) => {
// // let value: u32 = v.val.value() as u32;
// // if !(10 <= value && value < 100) {
// // v.val
// // .span()
// // .unstable()
// // .error(format!(
// // "expected literal 10 <= x < 100, got {}",
// // value,
// // ))
// // .emit();
// // }
// // From::from(v.val.into_tokens())
// // }
// // Err(err) => {
// // //let desc = format!("could not parse {:?}", err);
// // let desc = err.description();
// // // println!(
// // // "here -----------------------------------------desc {:?}",
// // // desc
// // // );
// // let tokens = quote! {
// // compile_error!(#desc)
// // };
// // return tokens.into();
// // }
// // }
// // }