Skip to main content

parse_emit_walkthrough/
parse_emit_walkthrough.rs

1use m2_syn::{
2    IdentToken, Lex, Parse, ParseStream, Span, Spanned, TokenParseError, TokenStream, TokenTree,
3    parse2, quote_m2,
4};
5
6#[derive(Debug, Clone, PartialEq, Eq)]
7struct Name(IdentToken);
8
9impl Parse for Name {
10    fn parse(input: &mut ParseStream) -> Result<Self, TokenParseError> {
11        let Some(token) = input.next_token() else {
12            return Err(TokenParseError::UnexpectedEnd {
13                expected: "identifier",
14                span: Span::detached(),
15            });
16        };
17
18        let span = token.span();
19        match token {
20            TokenTree::Ident(identifier) => Ok(Self(identifier)),
21            token => Err(TokenParseError::UnexpectedToken {
22                expected: "identifier",
23                found: token.spelling().unwrap_or("group or trivia").to_owned(),
24                span,
25            }),
26        }
27    }
28}
29
30impl Lex for Name {
31    fn to_tokens(&self, output: &mut TokenStream) {
32        self.0.to_tokens(output);
33    }
34}
35
36#[derive(Debug, Clone, PartialEq, Eq)]
37struct Addition {
38    left: Name,
39    operator: m2_syn::Token![+],
40    right: Name,
41}
42
43impl Parse for Addition {
44    fn parse(input: &mut ParseStream) -> Result<Self, TokenParseError> {
45        Ok(Self {
46            left: Name::parse(input)?,
47            operator: Parse::parse(input)?,
48            right: Name::parse(input)?,
49        })
50    }
51}
52
53impl Lex for Addition {
54    fn to_tokens(&self, output: &mut TokenStream) {
55        output.extend(self.left.to_token_stream());
56        output.extend(self.operator.to_token_stream());
57        output.extend(self.right.to_token_stream());
58    }
59}
60
61fn main() -> Result<(), TokenParseError> {
62    let quoted = quote_m2!(left + right);
63    println!("1. quote_m2! produced:\n{quoted:#?}\n");
64
65    let parsed: Addition = parse2(quoted)?;
66    println!("2. Parse produced:\n{parsed:#?}\n");
67
68    let emitted = parsed.to_token_stream();
69    println!("3. Lex produced:\n{emitted:#?}\n");
70    println!("4. Display merged those tokens as: {emitted}");
71
72    let reparsed: Addition = parse2(emitted)?;
73    assert_eq!(reparsed, parsed);
74
75    Ok(())
76}