Skip to main content

parse_emit_walkthrough/
parse_emit_walkthrough.rs

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