lib.rs 2.0 KB

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