Skip to main content

laburnum_syntax_macro/
lib.rs

1// Copyright Two Neutron Stars Incorporated and contributors
2// SPDX-License-Identifier: BlueOak-1.0.0
3
4use {
5  proc_macro_error::proc_macro_error,
6  proc_macro2::TokenStream,
7};
8
9mod args;
10use args::Args;
11mod ast;
12mod cst;
13mod error;
14
15#[proc_macro_attribute]
16#[proc_macro_error]
17pub fn laburnum_syntax(
18  args: proc_macro::TokenStream,
19  item: proc_macro::TokenStream,
20) -> proc_macro::TokenStream {
21  process(args.into(), item.into())
22    .unwrap_or_else(|syn_error| {
23      // Return the compile error token stream directly
24      syn_error.into_compile_error()
25    })
26    .into()
27}
28
29pub(crate) fn process(
30  attr: TokenStream,
31  item: TokenStream,
32) -> Result<TokenStream, syn::Error> {
33  // First we parse the flags from the attribute attr (if any)
34  let f = Args::parse(attr.clone());
35
36  // Validate that exactly one syntax type is specified
37  match (f.is_cst(), f.is_ast()) {
38    | (true, false) => cst::process(item, f),
39    | (false, true) => ast::process(item, f),
40    | (true, true) => {
41      // Both CST and AST specified - this is an error
42      Err(syn::Error::new(
43        f.conflicting_span(),
44        "Cannot specify both AST and CST flags. Choose either AST or CST, not both: #[laburnum_syntax(AST)] or #[laburnum_syntax(CST)].",
45      ))
46    },
47    | (false, false) => {
48      // Neither specified - provide helpful error
49      Err(syn::Error::new(
50        f.missing_type_span(),
51        "Missing syntax type specification. Add either AST or CST to the attribute: #[laburnum_syntax(AST)] or #[laburnum_syntax(CST)].",
52      ))
53    },
54  }
55}
56
57#[cfg(test)]
58mod tests;