From dc5b323d34ee6b33da92df88be2499f8f0e39e0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Haudebourg?= Date: Wed, 23 Aug 2023 18:19:11 +0200 Subject: [PATCH] Add `name` option. --- Cargo.toml | 2 +- examples/test.rs | 5 ++++- src/attribute.rs | 8 ++++++++ src/lib.rs | 31 ++++++++++++++++++++++--------- src/options.rs | 2 ++ 5 files changed, 37 insertions(+), 11 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 77a0270..806c6fd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "static-regular-grammar" -version = "1.0.0" +version = "1.1.0" edition = "2021" authors = ["Timothée Haudebourg "] categories = ["parsing"] diff --git a/examples/test.rs b/examples/test.rs index a497ea1..92ec89e 100644 --- a/examples/test.rs +++ b/examples/test.rs @@ -8,7 +8,10 @@ use static_regular_grammar::RegularGrammar; /// test = "%" / "$" /// ``` #[derive(RegularGrammar, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[grammar(sized(TestBuf, derive(Debug, Display, PartialEq, Eq, PartialOrd, Ord, Hash)))] +#[grammar( + name = "Test", + sized(TestBuf, derive(Debug, Display, PartialEq, Eq, PartialOrd, Ord, Hash)) +)] pub struct Test(str); fn main() { diff --git a/src/attribute.rs b/src/attribute.rs index f66f9f7..3050b19 100644 --- a/src/attribute.rs +++ b/src/attribute.rs @@ -27,6 +27,7 @@ pub enum Error { pub struct Attribute { pub file: Option, pub entry_point: Option, + pub name: Option, pub sized: Option, pub cache_path: Option, pub no_deref: bool, @@ -40,6 +41,7 @@ impl Attribute { pub fn append(&mut self, other: Self) { self.file = other.file.or(self.file.take()); self.entry_point = other.entry_point.or(self.entry_point.take()); + self.name = other.name.or(self.name.take()); if let Some(a) = other.sized { self.sized.get_or_insert_with(Default::default).append(a); @@ -57,6 +59,7 @@ impl Attribute { enum AttributeItem { File, EntryPoint, + Name, SizedType, CachePath, NoDeref, @@ -72,6 +75,7 @@ impl AttributeItem { match token { TokenTree::Ident(id) if id == "file" => Ok(Self::File), TokenTree::Ident(id) if id == "entry_point" => Ok(Self::EntryPoint), + TokenTree::Ident(id) if id == "name" => Ok(Self::Name), TokenTree::Ident(id) if id == "sized" => Ok(Self::SizedType), TokenTree::Ident(id) if id == "cache" => Ok(Self::CachePath), TokenTree::Ident(id) if id == "no_deref" => Ok(Self::NoDeref), @@ -164,6 +168,10 @@ impl Attribute { expect_eq(&mut tokens, span)?; result.entry_point = Some(expect_str_literal(&mut tokens, span)?) } + AttributeItem::Name => { + expect_eq(&mut tokens, span)?; + result.name = Some(expect_str_literal(&mut tokens, span)?) + } AttributeItem::CachePath => { expect_eq(&mut tokens, span)?; let path: PathBuf = expect_str_literal(&mut tokens, span)?.into(); diff --git a/src/lib.rs b/src/lib.rs index 5b04a0c..8dcf127 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -382,6 +382,11 @@ fn generate_typed( let vis = data.vis; let ident = data.ident; let ascii = data.options.ascii && T::is_ascii(&automaton); + let name = data + .options + .name + .or_else(|| data.options.entry_point) + .unwrap_or_else(|| ident.to_string()); if data.options.ascii && !ascii { return Err((Error::NotAscii, Span::call_site())); @@ -396,18 +401,19 @@ fn generate_typed( let as_inner = T::rust_as_inner_method(); let error = format_ident!("Invalid{}", ident); + let error_msg = format!("Invalid {name} `{{0}}`"); - let new_doc = format!("Creates a new [`{ident}`] by parsing the `input` value"); + let new_doc = format!("Creates a new {name} by parsing the `input` value"); let new_unchecked_doc = formatdoc!( r#" - Creates a new [`{ident}`] from the `input` value without validation. + Creates a new {name} from the `input` value without validation. # Safety - The input data *must* be a valid [`{ident}`]."# + The input data *must* be a valid {name}."# ); - let validate_doc = format!("Checks that the input iterator produces a valid [`{ident}`]"); + let validate_doc = format!("Checks that the input iterator produces a valid {name}"); let validate_body = if data.options.disable { quote! { panic!("automaton not generated") @@ -420,6 +426,14 @@ fn generate_typed( #[derive(Debug)] #vis struct #error(pub T); + impl ::core::fmt::Display for #error { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, #error_msg, self.0) + } + } + + impl ::std::error::Error for #error {} + impl #ident { #[doc = #new_doc] pub fn new>(input: &T) -> Result<&Self, #error<&T>> { @@ -679,16 +693,15 @@ fn generate_typed( let buffer_ident = buffer.ident; let owned_string_type = T::rust_owned_string_type(); - let owned_doc = format!("Owned [`{ident}`]."); - let owned_new_doc = - format!("Creates a new [`{buffer_ident}`] by parsing the `input` value"); + let owned_doc = format!("Owned {name}."); + let owned_new_doc = format!("Creates a new owned {name} by parsing the `input` value"); let owned_new_unchecked_doc = formatdoc!( r#" - Creates a new [`{buffer_ident}`] from the `input` value without validation. + Creates a new owned {name} from the `input` value without validation. # Safety - The input data *must* be a valid [`{ident}`]."# + The input data *must* be a valid {name}."# ); tokens.extend(quote! { diff --git a/src/options.rs b/src/options.rs index 5cc7cbc..81b3af3 100644 --- a/src/options.rs +++ b/src/options.rs @@ -7,6 +7,7 @@ use crate::{attribute::SizedTypeAttributes, Attribute, Error}; pub struct Options { pub file: Option, pub entry_point: Option, + pub name: Option, pub sized: Option, pub cache_path: PathBuf, pub no_deref: bool, @@ -21,6 +22,7 @@ impl Options { Ok(Self { file: attr.file, entry_point: attr.entry_point, + name: attr.name, sized: match attr.sized { Some(attr) => Some(SizedTypeOptions::from_attribute(attr, ident.span())?), None => None,