Skip to main content

lust/parser/
mod.rs

1mod expr_parser;
2mod item_parser;
3mod stmt_parser;
4mod type_parser;
5use crate::{
6    ast::{Item, ItemKind, Span},
7    error::{LustError, Result},
8    lexer::{Token, TokenKind},
9};
10use alloc::{
11    format,
12    string::{String, ToString},
13    vec::Vec,
14};
15pub struct Parser {
16    tokens: Vec<Token>,
17    current: usize,
18}
19
20impl Parser {
21    pub fn new(tokens: Vec<Token>) -> Self {
22        Self { tokens, current: 0 }
23    }
24
25    pub fn parse(&mut self) -> Result<Vec<Item>> {
26        let mut items = Vec::new();
27        while !self.is_at_end() {
28            if self.is_item_start() {
29                items.push(self.parse_item()?);
30            } else {
31                let start_token = self.current_token().clone();
32                let mut stmts = Vec::new();
33                while !self.is_at_end() && !self.is_item_start() {
34                    stmts.push(self.parse_stmt()?);
35                }
36
37                if !stmts.is_empty() {
38                    let end_token = if self.current > 0 {
39                        self.tokens[self.current - 1].clone()
40                    } else {
41                        self.current_token().clone()
42                    };
43                    items.push(Item::new(
44                        ItemKind::Script(stmts),
45                        self.make_span(&start_token, &end_token),
46                    ));
47                } else {
48                    break;
49                }
50            }
51        }
52
53        Ok(items)
54    }
55
56    fn is_item_start(&self) -> bool {
57        match self.peek_kind() {
58            TokenKind::Function
59            | TokenKind::Struct
60            | TokenKind::Enum
61            | TokenKind::Trait
62            | TokenKind::Impl
63            | TokenKind::Type
64            | TokenKind::Const
65            | TokenKind::Static
66            | TokenKind::Use
67            | TokenKind::Module
68            | TokenKind::Extern => true,
69            TokenKind::Pub => self.peek_ahead(1).map_or(false, |t| {
70                matches!(
71                    t.kind,
72                    TokenKind::Function
73                        | TokenKind::Struct
74                        | TokenKind::Enum
75                        | TokenKind::Trait
76                        | TokenKind::Impl
77                        | TokenKind::Type
78                        | TokenKind::Const
79                        | TokenKind::Static
80                        | TokenKind::Use
81                        | TokenKind::Module
82                        | TokenKind::Extern
83                )
84            }),
85            _ => false,
86        }
87    }
88
89    fn current_token(&self) -> &Token {
90        &self.tokens[self.current]
91    }
92
93    fn peek_kind(&self) -> TokenKind {
94        self.current_token().kind.clone()
95    }
96
97    fn peek_ahead(&self, n: usize) -> Option<&Token> {
98        self.tokens.get(self.current + n)
99    }
100
101    fn advance(&mut self) -> &Token {
102        if !self.is_at_end() {
103            self.current += 1;
104        }
105
106        &self.tokens[self.current - 1]
107    }
108
109    fn is_at_end(&self) -> bool {
110        self.peek_kind() == TokenKind::Eof
111    }
112
113    fn check(&self, kind: TokenKind) -> bool {
114        if self.is_at_end() {
115            return false;
116        }
117
118        self.peek_kind() == kind
119    }
120
121    fn match_token(&mut self, kinds: &[TokenKind]) -> bool {
122        for kind in kinds {
123            if self.check(kind.clone()) {
124                self.advance();
125                return true;
126            }
127        }
128
129        false
130    }
131
132    fn consume(&mut self, kind: TokenKind, message: &str) -> Result<&Token> {
133        if self.check(kind) {
134            Ok(self.advance())
135        } else {
136            let token = self.current_token();
137            Err(LustError::ParserError {
138                line: token.line,
139                column: token.column,
140                message: format!("{} (got {:?}, expected {:?})", message, token.kind, kind),
141                module: None,
142            })
143        }
144    }
145
146    fn expect_identifier(&mut self) -> Result<String> {
147        if self.check(TokenKind::Identifier) || self.check(TokenKind::Type) {
148            let token = self.advance().clone();
149            Ok(token.lexeme.clone())
150        } else {
151            let token = self.current_token().clone();
152            Err(LustError::ParserError {
153                line: token.line,
154                column: token.column,
155                message: format!(
156                    "Expected identifier (got {:?}, expected Identifier)",
157                    token.kind
158                ),
159                module: None,
160            })
161        }
162    }
163
164    fn make_span(&self, start_token: &Token, end_token: &Token) -> Span {
165        Span::new(
166            start_token.line,
167            start_token.column,
168            end_token.line,
169            end_token.column,
170        )
171    }
172
173    fn error(&self, message: &str) -> LustError {
174        let token = self.current_token();
175        LustError::ParserError {
176            line: token.line,
177            column: token.column,
178            message: message.to_string(),
179            module: None,
180        }
181    }
182
183    #[allow(dead_code)]
184    fn synchronize(&mut self) {
185        self.advance();
186        while !self.is_at_end() {
187            match self.peek_kind() {
188                TokenKind::Function
189                | TokenKind::Local
190                | TokenKind::If
191                | TokenKind::While
192                | TokenKind::For
193                | TokenKind::Return
194                | TokenKind::Struct
195                | TokenKind::Enum
196                | TokenKind::Trait
197                | TokenKind::Impl => return,
198                _ => {}
199            }
200
201            self.advance();
202        }
203    }
204}