rustledger_parser/lib.rs
1//! Beancount parser using chumsky parser combinators.
2//!
3//! This crate provides a parser for the Beancount file format. It produces
4//! a stream of [`Directive`]s from source text, along with any parse errors.
5//!
6//! # Features
7//!
8//! - Full Beancount syntax support (all 12 directive types)
9//! - Error recovery (continues parsing after errors)
10//! - Precise source locations for error reporting
11//! - Support for includes, options, plugins
12//!
13//! # Example
14//!
15//! ```ignore
16//! use rustledger_parser::parse;
17//!
18//! let source = r#"
19//! 2024-01-15 * "Coffee Shop" "Morning coffee"
20//! Expenses:Food:Coffee 5.00 USD
21//! Assets:Cash
22//! "#;
23//!
24//! let (directives, errors) = parse(source);
25//! assert!(errors.is_empty());
26//! assert_eq!(directives.len(), 1);
27//! ```
28
29#![forbid(unsafe_code)]
30#![warn(missing_docs)]
31
32mod error;
33// mod lexer; // Disabled - using direct parser instead
34mod parser;
35mod span;
36
37pub use error::{ParseError, ParseErrorKind};
38pub use span::{Span, Spanned};
39
40use rustledger_core::Directive;
41
42/// Result of parsing a beancount file.
43#[derive(Debug)]
44pub struct ParseResult {
45 /// Successfully parsed directives.
46 pub directives: Vec<Spanned<Directive>>,
47 /// Options found in the file.
48 pub options: Vec<(String, String, Span)>,
49 /// Include directives found.
50 pub includes: Vec<(String, Span)>,
51 /// Plugin directives found.
52 pub plugins: Vec<(String, Option<String>, Span)>,
53 /// Parse errors encountered.
54 pub errors: Vec<ParseError>,
55}
56
57/// Parse beancount source code.
58///
59/// Returns a tuple of (directives, errors). The parser uses error recovery
60/// to continue parsing after encountering errors, so both may be non-empty.
61///
62/// # Arguments
63///
64/// * `source` - The beancount source code to parse
65///
66/// # Returns
67///
68/// A `ParseResult` containing directives, options, includes, plugins, and errors.
69pub fn parse(source: &str) -> ParseResult {
70 parser::parse(source)
71}
72
73/// Parse beancount source code, returning only directives and errors.
74///
75/// This is a simpler interface when you don't need options/includes/plugins.
76pub fn parse_directives(source: &str) -> (Vec<Spanned<Directive>>, Vec<ParseError>) {
77 let result = parse(source);
78 (result.directives, result.errors)
79}