From 56afbaa6667dc74faea202ab6e8a43e18d3775ad Mon Sep 17 00:00:00 2001 From: Jannik Obermann <50554200+jannik4@users.noreply.github.com> Date: Sun, 26 Feb 2023 11:25:06 +0100 Subject: [PATCH] Add logos(crate = "...") attribute (#268) * Add logos(crate = "...") attribute * Use logos-derive per path --- logos-codegen/src/lib.rs | 13 ++++++++---- logos-codegen/src/parser/mod.rs | 18 ++++++++++++++++- logos/Cargo.toml | 2 +- tests/tests/crate_.rs | 36 +++++++++++++++++++++++++++++++++ 4 files changed, 63 insertions(+), 6 deletions(-) create mode 100644 tests/tests/crate_.rs diff --git a/logos-codegen/src/lib.rs b/logos-codegen/src/lib.rs index d7dd667d..60ffe6fa 100644 --- a/logos-codegen/src/lib.rs +++ b/logos-codegen/src/lib.rs @@ -26,6 +26,7 @@ use util::MaybeVoid; use proc_macro2::Span; use proc_macro2::TokenStream; use quote::quote; +use syn::parse_quote; use syn::spanned::Spanned; use syn::{Fields, ItemEnum}; @@ -211,6 +212,10 @@ pub fn generate(input: TokenStream) -> TokenStream { Mode::Utf8 => quote!(str), Mode::Binary => quote!([u8]), }; + let logos_path = parser + .logos_path + .take() + .unwrap_or_else(|| parse_quote!(::logos)); let error_def = match error { Some(error) => Some(quote!(const ERROR: Self = #name::#error;)), @@ -225,14 +230,14 @@ pub fn generate(input: TokenStream) -> TokenStream { let impl_logos = |body| { quote! { - impl<'s> ::logos::Logos<'s> for #this { + impl<'s> #logos_path::Logos<'s> for #this { type Extras = #extras; type Source = #source; #error_def - fn lex(lex: &mut ::logos::Lexer<'s, Self>) { + fn lex(lex: &mut #logos_path::Lexer<'s, Self>) { #body } } @@ -297,9 +302,9 @@ pub fn generate(input: TokenStream) -> TokenStream { let body = generator.generate(); let tokens = impl_logos(quote! { - use ::logos::internal::{LexerInternal, CallbackResult}; + use #logos_path::internal::{LexerInternal, CallbackResult}; - type Lexer<'s> = ::logos::Lexer<'s, #this>; + type Lexer<'s> = #logos_path::Lexer<'s, #this>; fn _end<'s>(lex: &mut Lexer<'s>) { lex.end() diff --git a/logos-codegen/src/parser/mod.rs b/logos-codegen/src/parser/mod.rs index f38eb850..960c0cb6 100644 --- a/logos-codegen/src/parser/mod.rs +++ b/logos-codegen/src/parser/mod.rs @@ -2,7 +2,7 @@ use beef::lean::Cow; use proc_macro2::{Span, TokenStream, TokenTree}; use quote::quote; use syn::spanned::Spanned; -use syn::{Attribute, GenericParam, Lit, Type}; +use syn::{Attribute, GenericParam, Lit, Path, Type}; use crate::error::Errors; use crate::leaf::{Callback, InlineCallback}; @@ -27,6 +27,7 @@ pub struct Parser { pub mode: Mode, pub extras: MaybeVoid, pub subpatterns: Subpatterns, + pub logos_path: Option, types: TypeParams, } @@ -129,6 +130,21 @@ impl Parser { ("subpattern", _) => { self.err(r#"Expected: subpattern name = r"regex""#, name.span()); } + ("crate", NestedValue::Assign(value)) => { + let value = syn::parse2::(value).ok().and_then(|lit| match lit { + Lit::Str(string) => syn::parse_str(&string.value()).ok(), + _ => None, + }); + match value { + Some(logos_path) => self.logos_path = Some(logos_path), + None => { + self.err(r#"Expected: crate = "some::path::to::logos""#, name.span()); + } + } + } + ("crate", _) => { + self.err(r#"Expected: crate = "some::path::to::logos""#, name.span()); + } (unknown, _) => { self.err( format!("Unknown nested attribute: {}", unknown), diff --git a/logos/Cargo.toml b/logos/Cargo.toml index 801672c2..2925f117 100644 --- a/logos/Cargo.toml +++ b/logos/Cargo.toml @@ -12,7 +12,7 @@ readme = "../README.md" edition = "2018" [dependencies] -logos-derive = { version = "0.12.1", optional = true } +logos-derive = { path = "../logos-derive", version = "0.12.1", optional = true } [features] default = ["export_derive", "std"] diff --git a/tests/tests/crate_.rs b/tests/tests/crate_.rs new file mode 100644 index 00000000..e9156586 --- /dev/null +++ b/tests/tests/crate_.rs @@ -0,0 +1,36 @@ +use logos_derive::Logos; +use tests::assert_lex; + +mod some { + pub mod path { + pub use logos as _logos; + } +} + +#[derive(Logos, Debug, Clone, Copy, PartialEq)] +#[logos(crate = "some::path::_logos")] +enum Token { + #[regex(r"[ \t\n\f]+", logos::skip)] + #[error] + Error, + + #[regex("-?[0-9]+")] + LiteralInteger, + + #[token("'")] + SingleQuote, +} + +#[test] +fn simple() { + assert_lex( + "' -1'2 '", + &[ + (Token::SingleQuote, "'", 0..1), + (Token::LiteralInteger, "-1", 2..4), + (Token::SingleQuote, "'", 4..5), + (Token::LiteralInteger, "2", 5..6), + (Token::SingleQuote, "'", 8..9), + ], + ); +}