Skip to main content

rl_lang/parser/utils/
mod.rs

1mod parse_type;
2use std::rc::Rc;
3
4use crate::{
5    ast::statements::TypeAnnotation,
6    lexer::tokentypes::TokenType,
7    parser::parser_logic::Parser,
8    utils::{errors::Error, span::Span},
9};
10
11impl Parser {
12    /// Returns the [`Span`] of the token at the current read head without consuming it.
13    pub fn peek_span(&self) -> Span {
14        self.tokens[self.current].span
15    }
16
17    /// Returns the [`Span`] of the most recently consumed token.
18    ///
19    /// Returns the span of `tokens[0]` when called before any [`advance`].
20    ///
21    /// [`advance`]: Parser::advance
22    pub fn previous_span(&self) -> Span {
23        if self.current == 0 {
24            self.tokens[0].span
25        } else {
26            self.tokens[self.current - 1].span
27        }
28    }
29
30    /// Returns `true` when the read head sits on [`TokenType::Eof`], indicating
31    /// the end of the token stream.
32    pub fn is_at_end(&self) -> bool {
33        #[cfg(feature = "debug")]
34        if matches!(self.peek(), TokenType::Eof) {
35            log::debug!("countered token [TokenType::Eof] indicating end of tokens for the file");
36        }
37        matches!(self.peek(), TokenType::Eof)
38    }
39
40    /// Advances the read head by one token, unless already at [`TokenType::Eof`].
41    pub fn advance(&mut self) {
42        if !self.is_at_end() {
43            self.current += 1;
44            #[cfg(feature = "debug")]
45            log::debug!("advancing the parser current token: {}", self.current);
46        }
47    }
48
49    /// Returns the [`TokenType`] at the current read head without consuming it.
50    pub fn peek(&self) -> TokenType {
51        #[cfg(feature = "debug")]
52        log::debug!(
53            "returning current token: [{:?}]",
54            &self.tokens[self.current].token
55        );
56        self.tokens[self.current].token.clone()
57    }
58
59    /// Returns the [`TokenType`] of the most recently consumed token.
60    ///
61    /// # Panics
62    /// Panics if called before any token has been consumed (`current == 0`).
63    pub fn previous(&self) -> TokenType {
64        #[cfg(feature = "debug")]
65        log::debug!(
66            "returning previous token: [{:?}]",
67            &self.tokens[self.current - 1].token
68        );
69        self.tokens[self.current - 1].token.clone()
70    }
71
72    /// Returns `true` if the token at the read head matches `token_type`.
73    ///
74    /// Literal-carrying variants (`NumberLiteral`, `StringLiteral`, etc.) are
75    /// matched by variant tag only - the inner value is ignored. Does **not**
76    /// consume the token.
77    pub fn check(&self, token_type: &TokenType) -> bool {
78        let current = self.peek();
79        match (token_type, &current) {
80            (TokenType::NumberLiteral(_), TokenType::NumberLiteral(_)) => true,
81            (TokenType::ByteLiteral(_), TokenType::ByteLiteral(_)) => true,
82            (TokenType::StringLiteral(_), TokenType::StringLiteral(_)) => true,
83            (TokenType::FloatLiteral(_), TokenType::FloatLiteral(_)) => true,
84            (TokenType::BoolLiteral(_), TokenType::BoolLiteral(_)) => true,
85            (TokenType::CharacterLiteral(_), TokenType::CharacterLiteral(_)) => true,
86            (TokenType::Identifier(_), TokenType::Identifier(_)) => true,
87            _ => token_type == &current,
88        }
89    }
90
91    /// Tries each variant in `types` against the current token via [`check`].
92    ///
93    /// On the first match the token is consumed via [`advance`] and `true` is
94    /// returned. Returns `false` without advancing if nothing matches.
95    ///
96    /// [`check`]: Parser::check
97    /// [`advance`]: Parser::advance
98    pub fn match_type(&mut self, types: &[TokenType]) -> bool {
99        for token_type in types {
100            if self.check(token_type) {
101                #[cfg(feature = "debug")]
102                log::debug!("Token {:?} matched one in [{:?}]", self.peek(), types);
103                self.advance();
104                return true;
105            }
106        }
107        #[cfg(feature = "debug")]
108        log::debug!("Token {:?} did not match any in [{:?}]", self.peek(), types);
109        false
110    }
111
112    /// Parses a single type keyword (or `array[T]`) as a function/lambda parameter
113    /// type annotation.
114    ///
115    /// Called when a type is expected in a parameter list position. For the
116    /// `array` keyword the inner element type is parsed recursively via
117    /// [`nested_array_type`].
118    ///
119    /// # Errors
120    /// Returns an error if the current token is not a recognised type keyword.
121    ///
122    /// [`nested_array_type`]: Parser::nested_array_type
123    pub fn parse_param_type(&mut self) -> Result<TypeAnnotation, Error> {
124        if matches!(self.peek(), TokenType::Array) {
125            self.advance();
126            return Ok(*self.nested_array_type()?);
127        }
128        if matches!(self.peek(), TokenType::Map) {
129            self.advance();
130            return Ok(*self.nested_map_type()?);
131        }
132        if matches!(self.peek(), TokenType::Set) {
133            self.advance();
134            return Ok(*self.set_type()?);
135        }
136        match self.peek() {
137            TokenType::Int => {
138                self.advance();
139                Ok(TypeAnnotation::Int)
140            }
141            TokenType::Byte => {
142                self.advance();
143                Ok(TypeAnnotation::Byte)
144            }
145            TokenType::Float => {
146                self.advance();
147                Ok(TypeAnnotation::Float)
148            }
149            TokenType::Bool => {
150                self.advance();
151                Ok(TypeAnnotation::Bool)
152            }
153            TokenType::String => {
154                self.advance();
155                Ok(TypeAnnotation::String)
156            }
157            TokenType::Char => {
158                self.advance();
159                Ok(TypeAnnotation::Char)
160            }
161            TokenType::Fn => {
162                self.advance();
163                Ok(TypeAnnotation::Fn)
164            }
165            TokenType::LeftParen => {
166                self.advance();
167                let mut inner = vec![];
168                loop {
169                    inner.push(self.parse_param_type()?);
170                    if !self.match_type(&[TokenType::Comma]) {
171                        break;
172                    }
173                }
174                if !self.match_type(&[TokenType::RightParen]) {
175                    return Err(self.err("expected `)` after tuple types", self.peek_span()));
176                }
177                Ok(TypeAnnotation::Tuple(Rc::new(inner)))
178            }
179            TokenType::Error => {
180                self.advance();
181                Ok(TypeAnnotation::Error)
182            }
183            TokenType::Result => {
184                self.advance();
185                if !self.match_type(&[TokenType::LeftBracket]) {
186                    return Err(self.err("expected `[` after `result`", self.peek_span()));
187                }
188                let inner = self.parse_param_type()?;
189                if !self.match_type(&[TokenType::RightBracket]) {
190                    return Err(self.err("expected `]` after result inner type", self.peek_span()));
191                }
192                Ok(TypeAnnotation::Result(Box::new(inner)))
193            }
194            TokenType::Null => {
195                self.advance();
196                Ok(TypeAnnotation::Null)
197            }
198
199            TokenType::Identifier(name) => {
200                self.advance();
201                if self.tag_names.contains(&name) {
202                    Ok(TypeAnnotation::Enum(name))
203                } else {
204                    Ok(TypeAnnotation::Record(name))
205                }
206            }
207
208            _ => Err(self.err("expected type", self.peek_span())),
209        }
210    }
211
212    /// Parses the `[T]` suffix of an `array[T]` type annotation, returning a
213    /// boxed [`TypeAnnotation::Array`].
214    ///
215    /// Expects the `array` keyword to have already been consumed. Reads
216    /// `[`, the inner element type (via [`parse_param_type`]), then `]`.
217    ///
218    /// # Errors
219    /// Returns an error if `[` or `]` are missing, or if the inner type is invalid.
220    ///
221    /// [`parse_param_type`]: Parser::parse_param_type
222    pub fn nested_array_type(&mut self) -> Result<Box<TypeAnnotation>, Error> {
223        match self.peek() {
224            TokenType::LeftBracket => {
225                self.advance();
226                let a = self.parse_param_type()?;
227                match self.peek() {
228                    TokenType::RightBracket => {
229                        self.advance();
230                        Ok(Box::new(TypeAnnotation::Array(Box::new(a))))
231                    }
232                    _ => Err(self.err("expected ']'", self.peek_span())),
233                }
234            }
235
236            _ => Err(self.err("expected '['", self.peek_span())),
237        }
238    }
239
240    pub fn nested_map_type(&mut self) -> Result<Box<TypeAnnotation>, Error> {
241        match self.peek() {
242            TokenType::LeftBracket => {
243                self.advance();
244                let key = self.parse_param_type()?;
245                if !self.match_type(&[TokenType::Comma]) {
246                    return Err(self.err(
247                        "expected `,` between map key and value types",
248                        self.peek_span(),
249                    ));
250                }
251                let value = self.parse_param_type()?;
252                match self.peek() {
253                    TokenType::RightBracket => {
254                        self.advance();
255                        Ok(Box::new(TypeAnnotation::Map(
256                            Box::new(key),
257                            Box::new(value),
258                        )))
259                    }
260                    _ => Err(self.err("expected ']'", self.peek_span())),
261                }
262            }
263
264            _ => Err(self.err("expected '['", self.peek_span())),
265        }
266    }
267
268    pub fn set_type(&mut self) -> Result<Box<TypeAnnotation>, Error> {
269        match self.peek() {
270            TokenType::LeftBracket => {
271                self.advance();
272                let a = self.parse_param_type()?;
273                match self.peek() {
274                    TokenType::RightBracket => {
275                        self.advance();
276                        Ok(Box::new(TypeAnnotation::Set(Box::new(a))))
277                    }
278                    _ => Err(self.err("expected ']'", self.peek_span())),
279                }
280            }
281
282            _ => Err(self.err("expected '['", self.peek_span())),
283        }
284    }
285}