Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- extern crate syn;
- #[macro_use]
- extern crate quote;
- extern crate proc_macro2;
- use quote::ToTokens;
- use proc_macro2::{Ident, Span};
- /**
- * Generate a boilerplate for a plural rule function.
- */
- fn create_boilerplate_from_quote() -> syn::File {
- let locale = "en";
- let plural_type = "cardinal";
- // let fn_name = format!("pr_{}_{}", locale, plural_type);
- let fnname = "pr_en";
- let boilerplate_tokens = quote! {
- fn pr_en (po: PluralOperands) -> PluralCategory {}
- };
- syn::parse2(boilerplate_tokens).expect("Unable to parse boilerplate")
- }
- // This is a bit too high level since this one creates a full clause for `one` for
- // english, cardinal. But for now, it gives us a good starting point to get
- // an AST for the en, cardinal `one` rule.
- fn create_en_one_clause() -> syn::Expr {
- let one_clause_tokens = quote! {
- if po.i == 1 { return PluralCategory::ONE }
- };
- syn::parse2(one_clause_tokens).expect("Unable to parse tokens")
- }
- // This is just a generic return clause for `other`.
- fn create_en_other_clause() -> syn::Expr {
- let s = "PluralCategory::OTHER";
- let result = syn::parse_str(s).expect("Unable to parse boilerplate");
- return result;
- }
- /**
- * This function takes the file AST and adds an expression as a block
- * to its first function's body.
- *
- * This is what we'll use to inject blocks into the body.
- */
- fn add_block(f: &mut syn::File, b: syn::Expr) {
- let func = &mut f.items[0];
- match func {
- syn::Item::Fn(ref mut f) => {
- let block = &mut f.block;
- let stmts = &mut block.stmts;
- stmts.push(syn::Stmt::Expr(b));
- },
- _ => panic!("Unknown boilerplate")
- };
- }
- fn main() {
- // 1. Get the boilerplate AST
- let mut result = create_boilerplate_from_quote();
- // 2. Get the `one` block
- let one = create_en_one_clause();
- // 3. Get the `other` block
- let other = create_en_other_clause();
- // 4. Insert them in order
- add_block(&mut result, one);
- add_block(&mut result, other);
- // Print the result function.
- println!("{}", result.into_token_stream().to_string());
- }
- /**
- * This is just an insight into how the AST look. We're actually *not*
- * going to use this function at all :)
- */
- fn _create_boilerplate() -> syn::File {
- let mut segments: syn::punctuated::Punctuated<syn::PathSegment, syn::token::Colon2> = syn::punctuated::Punctuated::new();
- segments.push(syn::PathSegment {
- ident: Ident::new("PluralOperands", Span::call_site()),
- arguments: syn::PathArguments::None
- });
- let mut pc_segments: syn::punctuated::Punctuated<syn::PathSegment, syn::token::Colon2> = syn::punctuated::Punctuated::new();
- pc_segments.push(syn::PathSegment {
- ident: Ident::new("PluralCategory", Span::call_site()),
- arguments: syn::PathArguments::None
- });
- let mut inputs: syn::punctuated::Punctuated<syn::FnArg, syn::token::Comma> = syn::punctuated::Punctuated::new();
- inputs.push_value(
- syn::FnArg::Captured(
- syn::ArgCaptured {
- pat: syn::Pat::Ident(
- syn::PatIdent {
- by_ref: None,
- mutability: None,
- ident: Ident::new("po", Span::call_site()),
- subpat: None,
- }
- ),
- colon_token: syn::token::Colon::new(Span::call_site()),
- ty: syn::Type::Path(
- syn::TypePath {
- qself: None,
- path: syn::Path {
- leading_colon: None,
- segments
- }
- }
- ),
- }
- ));
- let syntax2 = syn::File {
- shebang: None,
- attrs: vec![],
- items: vec![
- syn::Item::Fn(
- syn::ItemFn {
- attrs: vec![],
- vis: syn::Visibility::Inherited,
- constness: None,
- unsafety: None,
- abi: None,
- ident: Ident::new("en_cardinal", Span::call_site()),
- decl: Box::new(syn::FnDecl {
- fn_token: syn::token::Fn(Span::call_site()),
- generics: syn::Generics {
- lt_token: None,
- params: syn::punctuated::Punctuated::new(),
- gt_token: None,
- where_clause: None,
- },
- paren_token: syn::token::Paren(Span::call_site()),
- inputs,
- variadic: None,
- output: syn::ReturnType::Type(
- syn::token::RArrow::new(Span::call_site()),
- Box::new(syn::Type::Path(syn::TypePath {
- qself: None,
- path: syn::Path {
- leading_colon: None,
- segments: pc_segments
- }
- }))
- ),
- }),
- block: Box::new(syn::Block {
- brace_token: syn::token::Brace(Span::call_site()),
- stmts: vec![]
- })
- }
- )
- ]
- };
- return syntax2;
- }
Add Comment
Please, Sign In to add comment