monistode_macros/
lib.rs

1mod assembler;
2use proc_macro::TokenStream;
3use syn::parse_macro_input;
4
5#[proc_macro]
6pub fn assembler(input: TokenStream) -> TokenStream {
7    // Parse an identifier and a string literal
8    let input = parse_macro_input!(input with syn::punctuated::Punctuated::<syn::Expr, syn::Token![,]>::parse_terminated)
9        .into_iter()
10        .collect::<Vec<_>>();
11
12    if input.len() != 2 {
13        panic!("Expected two arguments: architecture name and definition file path");
14    }
15
16    // Extract architecture from identifier
17    let architecture = if let syn::Expr::Path(path) = &input[0] {
18        if let Some(ident) = path.path.get_ident() {
19            ident.to_string()
20        } else {
21            panic!("Expected architecture identifier");
22        }
23    } else {
24        panic!("Expected architecture identifier");
25    };
26
27    // Extract filename from string literal
28    let filename = if let syn::Expr::Lit(syn::ExprLit {
29        lit: syn::Lit::Str(s),
30        ..
31    }) = &input[1]
32    {
33        s.value()
34    } else {
35        panic!("Expected string literal for filename");
36    };
37
38    let raw_definition = monistode_binutils::definition::RawDefinition::from_str(
39        match std::fs::read_to_string(&filename) {
40            Ok(x) => x,
41            Err(e) => panic!("Error reading {}: {}", filename, e),
42        }
43        .as_str(),
44    )
45    .unwrap();
46    let definition = monistode_binutils::definition::Definition::try_from(raw_definition).unwrap();
47    assembler::generate_parser(&definition, &architecture).into()
48}