# Macro syn::custom_punctuation

source · [−]

    macro_rules! custom_punctuation {
        ($ident:ident, $($tt:tt)+) => { ... };
    }

Expand description

Define a type that supports parsing and printing a multi-character symbol as if it were a punctuation token.

## Usage

    syn::custom_punctuation!(LeftRightArrow, <=>);

The generated syntax tree node supports the following operations just like any built-in punctuation token.

- Peeking — `input.peek(LeftRightArrow)`

- Parsing — `input.parse::<LeftRightArrow>()?`

- Printing — `quote!( ... #lrarrow ... )`

- Construction from a `Span` — `let lrarrow = LeftRightArrow(sp)`

- Construction from multiple `Span` — `let lrarrow = LeftRightArrow([sp, sp, sp])`

- Field access to its spans — `let spans = lrarrow.spans`

## Example

    use proc_macro2::{TokenStream, TokenTree};
    use syn::parse::{Parse, ParseStream, Peek, Result};
    use syn::punctuated::Punctuated;
    use syn::Expr;

    syn::custom_punctuation!(PathSeparator, </>);

    // expr </> expr </> expr ...
    struct PathSegments {
        segments: Punctuated<Expr, PathSeparator>,
    }

    impl Parse for PathSegments {
        fn parse(input: ParseStream) -> Result<Self> {
            let mut segments = Punctuated::new();

            let first = parse_until(input, PathSeparator)?;
            segments.push_value(syn::parse2(first)?);

            while input.peek(PathSeparator) {
                segments.push_punct(input.parse()?);

                let next = parse_until(input, PathSeparator)?;
                segments.push_value(syn::parse2(next)?);
            }

            Ok(PathSegments { segments })
        }
    }

    fn parse_until<E: Peek>(input: ParseStream, end: E) -> Result<TokenStream> {
        let mut tokens = TokenStream::new();
        while !input.is_empty() && !input.peek(end) {
            let next: TokenTree = input.parse()?;
            tokens.extend(Some(next));
        }
        Ok(tokens)
    }

    fn main() {
        let input = r#" a::b </> c::d::e "#;
        let _: PathSegments = syn::parse_str(input).unwrap();
    }