Skip to main content

bubbles/compiler/
mod.rs

1//! Compilation pipeline: source text → [`Program`].
2
3pub mod ast;
4pub mod expr;
5pub mod lexer;
6pub(crate) mod parser;
7pub mod program;
8pub(crate) mod validate;
9
10pub use ast::{BinOp, Expr, IfBranch, LineVariant, Node, OptionItem, Stmt, TextSegment, UnOp};
11pub use lexer::{Spanned, Token, tokenise};
12pub use program::{Program, VariableDecl};
13pub use validate::validate;
14
15use crate::error::Result;
16
17/// Compiles a single `.bub` source string into a [`Program`].
18///
19/// # Errors
20/// Returns [`crate::DialogueError::Parse`] if the source is malformed,
21/// or [`crate::DialogueError::DuplicateNode`] if two nodes share a title
22/// without `when:` grouping conditions.
23pub fn compile(source: &str) -> Result<Program> {
24    compile_many(&[("<source>", source)])
25}
26
27/// Compiles multiple named `.bub` sources into a single [`Program`].
28///
29/// Sources are merged in order; duplicate node titles without `when:` grouping
30/// conditions cause a [`crate::DialogueError::DuplicateNode`] error.
31///
32/// # Errors
33/// Returns a [`crate::DialogueError`] variant on any parse or merge failure.
34pub fn compile_many(sources: &[(&str, &str)]) -> Result<Program> {
35    let mut all_nodes = Vec::new();
36    for (name, source) in sources {
37        let nodes = parser::parse(name, source)?;
38        all_nodes.extend(nodes);
39    }
40    Program::from_nodes(all_nodes)
41}