1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
mod error;
mod parse;
mod parsers;
mod pattern;
mod repr;
mod tokens;

use std::collections::VecDeque;

pub use error::{MacrosError, ParseError, ParseErrorKind};
pub use lazy_static::lazy_static;
pub use parse::Parse;
pub use pattern::{ParserInput, Pattern};
use proc_macro2::TokenStream;
pub use proc_macro2::{Spacing, Span};
use quote::ToTokens;
pub use repr::Repr;
pub use tokens::{Delimiter, LiteralKind, Token};

/// A stream of tokens.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct MacroStream {
    stream: VecDeque<Token>,
    popped: usize,
}

/// Type alias for the result of parsing to a `MacroStream`.
pub type ParseResult<T> = std::result::Result<T, ParseError>;

/// A match of a `Pattern`.
#[derive(Clone, Debug)]
pub enum Match {
    One(Token),
    Many(Vec<Match>),
    None,
}

impl MacroStream {
    /// Create a new empty `MacroStream`.
    pub fn new() -> Self {
        Self {
            stream: VecDeque::new(),
            popped: 0,
        }
    }

    /// Determine how many tokens have been popped from the stream.
    pub fn popped(&self) -> usize {
        self.popped
    }

    /// Create a `MacroStream` from a `proc_macro2::TokenStream`.
    pub fn from_tokens(stream: TokenStream) -> ParseResult<Self> {
        let mut tokens = VecDeque::new();
        for i in stream.into_iter() {
            tokens.push_back(i);
        }
        let mut stream = VecDeque::new();
        while !tokens.is_empty() {
            stream.push_back(Token::from_tokens(&mut tokens)?);
        }
        Ok(Self { stream, popped: 0 })
    }

    /// Pop a token from the stream.
    pub fn pop(&mut self) -> Option<Token> {
        self.stream.pop_front()
    }

    /// Peek at the next token in the stream.
    pub fn peek(&self) -> Option<&Token> {
        self.peek_at(0)
    }

    /// Peek at the token at the given index in the stream.
    pub fn peek_at(&self, i: usize) -> Option<&Token> {
        self.stream.get(i)
    }

    /// Parse the stream into a type.
    pub fn parse<T>(&mut self) -> Result<T, MacrosError>
    where
        T: Parse,
    {
        T::parse(self)
    }

    /// Determine if the stream is empty.
    pub fn is_empty(&self) -> bool {
        self.stream.is_empty()
    }

    /// Pop a token from the stream, or return an error if the stream is empty.
    pub fn pop_or_err(&mut self) -> Result<Token, ParseError> {
        self.pop()
            .ok_or_else(|| {
                ParseError::call_site(ParseErrorKind::UnexpectedEndOfInput("".to_string()))
            })
            .map(|i| {
                self.popped += 1;
                i
            })
    }

    /// Peek at the next token in the stream, or return an error if the stream is empty.
    pub fn peek_or_err(&self) -> Result<&Token, ParseError> {
        self.peek().ok_or_else(|| {
            ParseError::call_site(ParseErrorKind::UnexpectedEndOfInput("".to_string()))
        })
    }

    /// Push a token to the front of the stream.
    pub fn push_front(&mut self, token: Token) {
        self.stream.push_front(token)
    }

    /// Push a token to the back of the stream.
    pub fn push_back(&mut self, token: Token) {
        self.stream.push_back(token)
    }

    /// Get the length of the stream.
    pub fn len(&self) -> usize {
        self.stream.len()
    }

    /// Fork the stream (clone the stream and reset the popped count).
    pub fn fork(&self) -> Self {
        Self {
            stream: self.stream.clone(),
            popped: 0,
        }
    }

    /// Pop a number of tokens from the stream.
    pub fn pop_many(&mut self, p: usize) {
        for _ in 0..p {
            self.pop().unwrap();
        }
    }
}

impl From<TokenStream> for MacroStream {
    fn from(stream: TokenStream) -> Self {
        Self::from_tokens(stream).unwrap()
    }
}

impl Default for MacroStream {
    fn default() -> Self {
        Self::new()
    }
}

impl ToTokens for MacroStream {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        for i in &self.stream {
            i.to_tokens(tokens);
        }
    }
}

/// A shortcut for `proc_macro2::Span::call_site()`.
#[inline(always)]
pub fn call_site() -> Span {
    Span::call_site()
}

/// The trait for the output of a parser created by the `parser!` macro.
pub trait ParserOutput {
    fn set_match(&mut self, k: &str, m: Match);
    fn name() -> &'static str;
}