lib.rs 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. extern crate proc_macro;
  2. use proc_macro::TokenStream;
  3. use quote::ToTokens;
  4. use syn::parse_macro_input;
  5. mod parsing;
  6. use parsing::Protocol;
  7. mod error;
  8. mod generation;
  9. mod validation;
  10. macro_rules! unwrap_or_compile_err {
  11. ($result:expr) => {
  12. match $result {
  13. Ok(value) => value,
  14. Err(err) => return err.into_compile_error().into(),
  15. }
  16. };
  17. }
  18. /// Generates types for the actors participating in a messaging protocol.
  19. ///
  20. /// ## Usage Restrictions
  21. /// A type named `Result` which accepts a single type parameter must be in scope where you call this
  22. /// macro. This allows you to define the error type used by the generated traits by defining a
  23. /// type alias:
  24. /// ```
  25. /// struct MyError;
  26. /// type Result<T> = std::result::Result<T, MyError>;
  27. /// ```
  28. ///
  29. /// You must also ensure all message types referenced by the protocol are in scope.
  30. ///
  31. /// ## Grammar
  32. /// The grammar recognized by this macro is given below in the dialect of Extended Backus-Naur Form
  33. /// recognized by the `llgen` tool. The terminal symbol `Ident` has the same meaning as it does in
  34. /// the regular Rust syntax.
  35. ///
  36. /// ```ebnf
  37. /// protocol : name_def states_def ( transition ';' )* ;
  38. /// name_def : "let" "name" '=' Ident ';' ;
  39. /// states_def : "let" "states" '=' ident_array ';' ;
  40. /// ident_array : '[' Ident ( ',' Ident )* ','? ']' ;
  41. /// transition : state ( '?' message )? "->" states_list ( '>' dest_list )? ;
  42. /// state : Ident ident_array? ;
  43. /// states_list : state ( ',' state )* ','? ;
  44. /// dest_list : dest ( ',' dest )* ;
  45. /// dest : dest_state '!' message
  46. /// dest_state : ( "service" '(' Ident ')' ) | state ;
  47. /// message : Ident ( "::" "Reply" )? ident_array? ;
  48. /// ```
  49. #[proc_macro]
  50. pub fn protocol(input: TokenStream) -> TokenStream {
  51. let input = parse_macro_input!(input as Protocol);
  52. unwrap_or_compile_err!(input.validate());
  53. input.to_token_stream().into()
  54. }