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