Wow I should ahve committed a long time ago
Going down a rabbit hole trying to make a parser macro. Learning how to make a proc macro is... a steep learning curve.attempt/001
parent
8f3472c4cd
commit
6207a7f032
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,4 @@
|
|||||||
|
entities/camera.entity
|
||||||
|
entities/ui_container.entity
|
||||||
|
entities/ui_title.entity
|
||||||
|
entities/window.entity
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
entities/camera.entity
|
||||||
|
entities/van.entity
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
[package]
|
||||||
|
name = "parser"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
proc-macro = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
nom = "7"
|
||||||
|
syn = "2"
|
||||||
|
quote = "1"
|
||||||
@ -0,0 +1,92 @@
|
|||||||
|
use proc_macro::TokenStream;
|
||||||
|
use quote::quote;
|
||||||
|
use syn::{parse_macro_input, token::Paren, Expr, Ident, Type, TypeTuple};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum Component {
|
||||||
|
// Members(Vec<Component>),
|
||||||
|
Member {
|
||||||
|
tag: Ident,
|
||||||
|
inputs: Vec<Type>,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl syn::parse::Parse for Component {
|
||||||
|
fn parse(input: syn::parse::ParseStream) -> syn::parse::Result<Self> {
|
||||||
|
// TODO: Handle components with multiple struct members
|
||||||
|
let tag: Ident = input.parse()?;
|
||||||
|
let mut inputs = Vec::new();
|
||||||
|
while let Ok(ty) = input.parse() {
|
||||||
|
inputs.push(ty)
|
||||||
|
}
|
||||||
|
Ok(Component::Member { tag, inputs })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Macro for generating parsing functions for entity components.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// let line = "foo 1.2 2.3";
|
||||||
|
/// let (x, y) = parse!("foo <f32> <f32>")(line).unwrap();
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
#[proc_macro]
|
||||||
|
pub fn parse(tokens: TokenStream) -> TokenStream {
|
||||||
|
match parse_macro_input!(tokens as Component) {
|
||||||
|
Component::Member { tag, inputs } => {
|
||||||
|
// For each input value
|
||||||
|
// nom::character::complete::space1,
|
||||||
|
// Match on type to determine parsing function (either float or string likely)
|
||||||
|
// nom::number::complete::float,
|
||||||
|
let parsers = Vec::new();
|
||||||
|
let nom_tuple = quote! {
|
||||||
|
nom::bytes::complete::tag("#tag"),
|
||||||
|
#(nom::character::complete::space1, #parsers),*
|
||||||
|
};
|
||||||
|
|
||||||
|
let parsed_vars = Vec::new();
|
||||||
|
let nom_results = quote! {
|
||||||
|
#(#parsed_vars),*
|
||||||
|
};
|
||||||
|
|
||||||
|
let nom_output_type = quote! { #(#inputs),* };
|
||||||
|
let nom_outputs = quote! {
|
||||||
|
// (x1, x2, ...)
|
||||||
|
};
|
||||||
|
|
||||||
|
let expanded = quote! {
|
||||||
|
|line: &str| -> Result<#nom_output_type, nom::Err<_>> {
|
||||||
|
tuple(#nom_tuple)(line).map(|(_, #nom_results)| #nom_outputs)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TokenStream::from(expanded)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// let t = nom::bytes::complete::take_while1(nom::character::is_alphabetic)(todo!()).unwrap();
|
||||||
|
|
||||||
|
// let return_type = todo!();
|
||||||
|
// let method_body = todo!();
|
||||||
|
|
||||||
|
// let return_type = "Result<(f32, f32, f32), nom::Err<()>>";
|
||||||
|
// let method_body = "
|
||||||
|
// nom::sequence::tuple((
|
||||||
|
// nom::bytes::complete::tag(\"thing\"),
|
||||||
|
// nom::character::complete::space1,
|
||||||
|
// nom::number::complete::float,
|
||||||
|
// nom::character::complete::space1,
|
||||||
|
// nom::number::complete::float,
|
||||||
|
// nom::character::complete::space1,
|
||||||
|
// nom::number::complete::float
|
||||||
|
// ))(line)
|
||||||
|
// .map(|(_, (_, _, x, _, y, _, z))| {
|
||||||
|
// (x, y, z)
|
||||||
|
// })
|
||||||
|
// ";
|
||||||
|
|
||||||
|
// let lambda = format!("|line: &str| -> {} {{ {} }}", return_type, method_body);
|
||||||
|
|
||||||
|
// lambda.parse().unwrap()
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
use parser::parse;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let line = "thing 1.23 3.45 5.67";
|
||||||
|
let f = parse!(thing f32 f32 f32);
|
||||||
|
let (_x, _y, _z) = f(line).unwrap();
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue