mago_syntax/parser/
mod.rs

1use bumpalo::Bump;
2
3use mago_database::file::File;
4use mago_database::file::HasFileId;
5use mago_syntax_core::input::Input;
6
7use crate::ast::Program;
8use crate::ast::sequence::Sequence;
9use crate::lexer::Lexer;
10
11use crate::error::ParseError;
12use crate::parser::internal::statement::parse_statement;
13use crate::parser::internal::token_stream::TokenStream;
14
15mod internal;
16
17pub fn parse_file<'arena>(arena: &'arena Bump, file: &File) -> (&'arena Program<'arena>, Option<ParseError>) {
18    let source_text = arena.alloc_str(file.contents.as_ref());
19    let input = Input::new(file.id, source_text.as_bytes());
20    let lexer = Lexer::new(arena, input);
21
22    let mut stream = TokenStream::new(arena, lexer);
23
24    let mut error = None;
25    let statements = {
26        let mut statements = stream.new_vec();
27
28        loop {
29            match stream.has_reached_eof() {
30                Ok(false) => match parse_statement(&mut stream) {
31                    Ok(statement) => {
32                        statements.push(statement);
33                    }
34                    Err(parse_error) => {
35                        error = Some(parse_error);
36
37                        break;
38                    }
39                },
40                Ok(true) => {
41                    break;
42                }
43                Err(syntax_error) => {
44                    error = Some(ParseError::from(syntax_error));
45
46                    break;
47                }
48            }
49        }
50
51        statements
52    };
53
54    let program = arena.alloc(Program {
55        file_id: stream.file_id(),
56        source_text,
57        statements: Sequence::new(statements),
58        trivia: stream.get_trivia(),
59    });
60
61    (program, error)
62}