py_lex/
token.rs

1use terl::*;
2#[derive(Debug, Clone)]
3pub struct Token {
4    pub string: String,
5    /// note: span here are span in [`Buffer<char>`]
6    span: Span,
7}
8
9impl Token {
10    pub fn new(string: impl Into<String>, span: Span) -> Self {
11        Self {
12            string: string.into(),
13            span,
14        }
15    }
16}
17
18impl std::ops::Deref for Token {
19    type Target = str;
20
21    fn deref(&self) -> &Self::Target {
22        &self.string
23    }
24}
25
26impl std::fmt::Display for Token {
27    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28        self.string.fmt(f)
29    }
30}
31
32impl WithSpan for Token {
33    #[inline]
34    fn get_span(&self) -> Span {
35        self.span
36    }
37}
38
39impl ParseUnit<char> for Token {
40    type Target = Self;
41
42    fn parse(p: &mut Parser<char>) -> ParseResult<Self, char> {
43        fn w(c: &char) -> bool {
44            c.is_ascii_alphanumeric() || *c == '_'
45        }
46
47        // skip whitespace
48        while p.next_if(|c| !w(c)).is_some() {}
49
50        // get string until whitespace
51        let mut string = String::new();
52        p.start_taking();
53        while let Some(next) = p.next_if(w) {
54            string.push(*next);
55        }
56
57        // return unmatch if string is empty
58        if string.is_empty() {
59            return p.unmatch("empty string");
60        }
61
62        Ok(Token {
63            string,
64            span: p.get_span(),
65        })
66    }
67}
68
69impl ParseUnit<Token> for Token {
70    type Target = Token;
71
72    #[inline]
73    fn parse(p: &mut Parser<Token>) -> Result<Self::Target, ParseError> {
74        match p.next().cloned() {
75            Some(token) => Ok(token),
76            None => p.unmatch("no token left"),
77        }
78    }
79}
80
81impl Source for Token {
82    type HandleErrorWith<'b> = (&'b Buffer<char>, &'b Buffer<Token>);
83
84    #[inline]
85    fn handle_location<S>(
86        with: &Self::HandleErrorWith<'_>,
87        buffer: &mut S,
88        loc: Span,
89        msg: &str,
90    ) -> std::fmt::Result
91    where
92        S: std::fmt::Write,
93    {
94        let (chars, tokens) = with;
95        let loc = tokens[loc.start].get_span() + tokens[loc.end - 1].get_span();
96        char::handle_location(chars, buffer, loc, msg)
97    }
98}
99
100/// a type which implemented [`ParseUnit<S>`] with source code it selected
101pub struct PU<P> {
102    pub(crate) span: Span,
103    pub(crate) item: P,
104}
105
106impl<S, P> ParseUnit<S> for PU<P>
107where
108    P: ParseUnit<S>,
109    S: Source,
110{
111    type Target = PU<P::Target>;
112
113    fn parse(p: &mut Parser<S>) -> Result<Self::Target, ParseError> {
114        P::parse(p).map(|item| PU::new(p.get_span(), item))
115    }
116}
117
118impl<P> WithSpan for PU<P> {
119    fn get_span(&self) -> Span {
120        self.span
121    }
122}
123
124impl<P> PU<P> {
125    #[inline]
126    pub const fn new(span: Span, item: P) -> Self {
127        Self { span, item }
128    }
129
130    /// take [ParseUnit::Target] from [`PU`]
131    #[inline]
132    pub fn take(self) -> P {
133        self.item
134    }
135
136    /// map [ParseUnit::Target]
137    #[inline]
138    pub fn map<P1, M>(self, mapper: M) -> PU<P1>
139    where
140        M: FnOnce(P) -> P1,
141    {
142        PU::new(self.span, mapper(self.item))
143    }
144}
145
146impl<P> std::fmt::Debug for PU<P>
147where
148    P: std::fmt::Debug,
149{
150    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
151        f.debug_struct("PU")
152            .field("span", &self.span)
153            .field("item", &self.item)
154            .finish()
155    }
156}
157
158impl<P> std::fmt::Display for PU<P>
159where
160    P: std::fmt::Display,
161{
162    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
163        std::fmt::Display::fmt(&self.item, f)
164    }
165}
166
167impl<P> Clone for PU<P>
168where
169    P: Clone,
170{
171    fn clone(&self) -> Self {
172        Self {
173            span: self.span,
174            item: self.item.clone(),
175        }
176    }
177}
178
179impl<P> Copy for PU<P> where P: Copy {}
180
181impl<P> std::ops::Deref for PU<P> {
182    type Target = P;
183
184    fn deref(&self) -> &Self::Target {
185        &self.item
186    }
187}
188
189impl<P> std::ops::DerefMut for PU<P> {
190    fn deref_mut(&mut self) -> &mut Self::Target {
191        &mut self.item
192    }
193}
194
195pub struct RPU<Item>(pub Item);
196
197impl<Item, S: Source> ReverseParseUnit<S> for RPU<Item>
198where
199    Item: ReverseParseUnit<S>,
200{
201    type Left = PU<Item::Left>;
202
203    #[inline]
204    fn reverse_parse(&self, p: &mut Parser<S>) -> Result<Self::Left, ParseError> {
205        self.0
206            .reverse_parse(p)
207            .map(|item| PU::new(p.get_span(), item))
208    }
209}
210
211#[cfg(test)]
212mod tests {
213
214    use super::*;
215
216    #[test]
217
218    fn token() {
219        use terl::*;
220        let file_name = std::any::type_name_of_val(&token).to_owned();
221        let src = "123456 abcde \n 114514abc [] ()";
222        let buffer = Buffer::new(file_name, src.chars().collect());
223        let mut parser = Parser::new(buffer);
224
225        let mut tokens: Vec<_> = vec![];
226        while let Some(token) = parser.parse::<PU<Token>>().apply(mapper::Try).unwrap() {
227            tokens.push(token)
228        }
229
230        let expect = src.chars().enumerate().collect::<Vec<_>>();
231        let expect = expect
232            .split(|(.., c)| c.is_whitespace())
233            .fold(vec![], |mut expect, slice| {
234                //  " \n " will generate two empty slice
235                if !slice.is_empty() {
236                    let span = Span::new(slice.first().unwrap().0, slice.last().unwrap().0);
237                    let string = slice.iter().map(|(.., c)| c).collect::<String>();
238                    expect.push(Token::new(string, span));
239                }
240                expect
241            });
242
243        for (got, expect) in tokens.into_iter().zip(expect) {
244            let (got, expect): (&str, &str) = (&got, &expect);
245            assert_eq!(got, expect);
246        }
247    }
248}