1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
use crate::common::position::Position;
use crate::parse::ast::{AST, Node};
use crate::parse::iterator::LexIterator;
use crate::parse::lex::token::{Lex, Token};
use crate::parse::lex::tokenize;
use crate::parse::result::{expected, ParseErr, ParseResult};

pub mod ast;

mod iterator;

pub mod result;

mod block;
mod call;
mod class;
mod collection;
mod control_flow_expr;
mod control_flow_stmt;
mod definition;
mod expr_or_stmt;
mod expression;
mod lex;
mod operation;
mod statement;
mod ty;

/// Parse input, which is a string.
pub fn parse(input: &str) -> ParseResult {
    let tokens: Vec<Lex> = tokenize(input)
        .map(|tokens| tokens.into_iter().filter(|t| !matches!(t.token, Token::Comment(_))).collect())
        .map_err(ParseErr::from)?;

    let mut iterator = LexIterator::new(tokens.iter().peekable());
    let statements = block::parse_statements(&mut iterator)?;
    if iterator.peek_if(&|lex| lex.token != Token::Eof) {
        if let Some(lex) = iterator.peek_next() {
            return Err(Box::from(expected(&Token::Eof, &lex, "end of file")));
        }
    }

    let start = statements.first().map_or_else(Position::invisible, |stmt| stmt.pos);
    let end = statements.last().map_or_else(Position::invisible, |stmt| stmt.pos);

    Ok(Box::from(AST::new(start.union(end), Node::Block { statements })))
}

#[cfg(test)]
pub fn parse_direct(input: &str) -> ParseResult<Vec<AST>> {
    match parse(input)?.node {
        Node::Block { statements } => Ok(statements),
        _ => Ok(vec![]),
    }
}