1use mago_ast::Program;
2use mago_ast::sequence::Sequence;
3use mago_interner::ThreadedInterner;
4use mago_lexer::Lexer;
5use mago_lexer::input::Input;
6use mago_source::Source;
7
8use crate::error::ParseError;
9use crate::internal::statement::parse_statement;
10use crate::internal::token_stream::TokenStream;
11
12pub mod error;
13
14mod internal;
15
16pub fn parse_source(interner: &ThreadedInterner, source: &Source) -> (Program, Option<ParseError>) {
17 let content = interner.lookup(&source.content);
18 let lexer = Lexer::new(interner, Input::new(source.identifier, content.as_bytes()));
19
20 construct(interner, lexer)
21}
22
23pub fn parse(interner: &ThreadedInterner, input: Input<'_>) -> (Program, Option<ParseError>) {
24 let lexer = Lexer::new(interner, input);
25
26 construct(interner, lexer)
27}
28
29fn construct<'i>(interner: &'i ThreadedInterner, lexer: Lexer<'_, 'i>) -> (Program, Option<ParseError>) {
30 let mut stream = TokenStream::new(interner, lexer);
31
32 let mut error = None;
33 let statements = {
34 let mut statements = Vec::new();
35
36 loop {
37 match stream.has_reached_eof() {
38 Ok(false) => match parse_statement(&mut stream) {
39 Ok(statement) => {
40 statements.push(statement);
41 }
42 Err(parse_error) => {
43 error = Some(parse_error);
44
45 break;
46 }
47 },
48 Ok(true) => {
49 break;
50 }
51 Err(syntax_error) => {
52 error = Some(ParseError::from(syntax_error));
53
54 break;
55 }
56 }
57 }
58
59 statements
60 };
61
62 (
63 Program {
64 source: stream.get_position().source,
65 statements: Sequence::new(statements),
66 trivia: stream.get_trivia(),
67 },
68 error,
69 )
70}