amarok_parser/builders/
mod.rs

1use amarok_syntax::{Diagnostic, Program, Spanned, Statement};
2use pest::iterators::Pair;
3
4use crate::grammar::Rule;
5
6pub(crate) mod expressions;
7pub(crate) mod helpers;
8pub(crate) mod statements;
9
10pub(crate) use expressions::build_expression;
11
12use helpers::span_of;
13use statements::{
14    build_assignment_statement, build_block_statement, build_expression_statement,
15    build_function_definition, build_if_statement, build_return_statement, build_use_statement,
16    build_while_statement,
17};
18
19pub(crate) fn build_program(pair: Pair<Rule>) -> Result<Program, Diagnostic> {
20    if pair.as_rule() != Rule::program {
21        return Err(
22            Diagnostic::new(format!("Expected program rule, got {:?}", pair.as_rule()))
23                .with_span(span_of(&pair)),
24        );
25    }
26
27    let mut statements: Vec<Spanned<Statement>> = Vec::new();
28
29    for item in pair.into_inner() {
30        // Pest may include markers like EOI under program, depending on how the grammar is structured.
31        // We only accept actual statement rules here.
32        match item.as_rule() {
33            Rule::assignment_statement
34            | Rule::return_statement
35            | Rule::if_statement
36            | Rule::while_statement
37            | Rule::function_definition
38            | Rule::block_statement
39            | Rule::use_statement
40            | Rule::expression_statement => statements.push(build_statement(item)?),
41
42            // Ignore anything else (EOI, or future wrapper rules).
43            _ => {}
44        }
45    }
46
47    Ok(Program { statements })
48}
49
50pub(crate) fn build_statement(pair: Pair<Rule>) -> Result<Spanned<Statement>, Diagnostic> {
51    let statement_span = span_of(&pair);
52
53    let statement_value = match pair.as_rule() {
54        Rule::assignment_statement => build_assignment_statement(pair)?,
55        Rule::expression_statement => build_expression_statement(pair)?,
56        Rule::block_statement => build_block_statement(pair)?,
57        Rule::if_statement => build_if_statement(pair)?,
58        Rule::while_statement => build_while_statement(pair)?,
59        Rule::function_definition => build_function_definition(pair)?,
60        Rule::return_statement => build_return_statement(pair)?,
61        Rule::use_statement => build_use_statement(pair)?,
62        other => {
63            return Err(
64                Diagnostic::new(format!("Unhandled statement rule: {other:?}"))
65                    .with_span(statement_span),
66            );
67        }
68    };
69
70    Ok(Spanned::new(statement_span, statement_value))
71}