Skip to content

Commit

Permalink
working on include directive
Browse files Browse the repository at this point in the history
  • Loading branch information
alensiljak committed Oct 16, 2023
1 parent 8fb9cdf commit 6f3356f
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 44 deletions.
103 changes: 64 additions & 39 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ use crate::{
journal::Journal,
post::Post,
scanner::{self, PostTokens},
xact::Xact,
xact::Xact, parse_file,
};

pub const ISO_DATE_FORMAT: &str = "%Y-%m-%d";
Expand Down Expand Up @@ -81,7 +81,6 @@ pub fn parse_amount_parts(
} else {
None
}

}

pub(crate) struct Parser<'j, T: Read> {
Expand Down Expand Up @@ -172,20 +171,23 @@ impl<'j, T: Read> Parser<'j, T> {
c => {
// 4.7.2 command directives

// if !general_directive()
if self.general_directive() {
return Ok(());
}

match c {
// ACDNY
'P' => {
// price
self.price_xact_directive();
}
// ACDNPY
'P' => {
// a pricing xact
self.price_xact_directive();
}

c => {
log::warn!("not handled: {:?}", c);
todo!("handle other directives");
c => {
log::warn!("not handled: {:?}", c);
todo!("handle other directives");
}
}
}
// TODO: todo!("the rest")
// TODO: todo!("the rest")
}
}

Expand All @@ -194,12 +196,14 @@ impl<'j, T: Read> Parser<'j, T> {

/// textual.cc
/// bool instance_t::general_directive(char *line)
fn general_directive(&self) -> bool {
fn general_directive(&mut self) -> bool {
// todo: skip if (*p == '@' || *p == '!')

// split directive and argument
let mut iter = self.buffer.split_whitespace();
let Some(directive) = iter.next() else { panic!("no directive?") };
let Some(directive) = iter.next() else {
panic!("no directive?")
};
let argument = iter.next();

// todo: check arguments for directives that require one
Expand All @@ -220,7 +224,7 @@ impl<'j, T: Read> Parser<'j, T> {
}

// bcde
'i' => match self.buffer.as_str() {
'i' => match directive {
"include" => {
self.include_directive(argument.unwrap());
return true;
Expand Down Expand Up @@ -324,38 +328,54 @@ impl<'j, T: Read> Parser<'j, T> {
Ok(())
}

fn include_directive(&self, argument: &str) {
/// textual.cc
/// void instance_t::include_directive(char *line)
fn include_directive(&mut self, argument: &str) {
let mut filename: PathBuf;

// if (line[0] != '/' && line[0] != '\\' && line[0] != '~')
if argument.starts_with('/') || argument.starts_with('\\') || argument.starts_with('~') {
filename = PathBuf::from_str(argument).unwrap();
} else {
// relative path
// TODO: get the parent path?
// dir = parent_path()
// if (parent_path.empty())
// else, use current directory
/*
filename = PathBuf::from_str(argument).unwrap();
// get the parent path?
match filename.parent() {
Some(parent) => {
// absolute path
filename = parent.to_path_buf();
},
None => {
// no parent path, use current directory
filename = env::current_dir().unwrap();
},
}
*/
filename = env::current_dir().unwrap();

filename.set_file_name(argument);
filename.push(argument);
}

let mut file_found = false;
// TODO: resolve glob, i.e *.ledger

// let mut file_found = false;
let parent_path = filename.parent().unwrap();
if parent_path.exists() {
if filename.is_file() {
// let base = filename.file_name();

// TODO: read file
// read_into_journal(source, journal)
todo!("read file")
// read file.
//read_into_journal(source, journal);
// parse_file(filename.to_str().unwrap(), self.journal);
todo!("read file");
// The problem is again having a mutable reference and immutable ones.
// Try using Nom for parsing instead.
}
}

if !file_found {
panic!("Include file not found");
}
// if !file_found {
// panic!("Include file not found");
// }
}

/// Parses the trailing note from the buffer.
Expand Down Expand Up @@ -491,14 +511,15 @@ mod tests {
use crate::journal::Journal;

/// Enable this test again when the functionality is complete
//#[test]
#[test]
fn test_general_directive() {
let source = Cursor::new("include some-file.ledger");
let source = Cursor::new("include tests/basic.ledger");
let mut journal = Journal::new();

let parser = Parser::new(source, &mut journal);
let mut parser = Parser::new(source, &mut journal);

parser.general_directive();
parser.parse();
//parser.general_directive();

todo!("assert")
}
Expand Down Expand Up @@ -681,11 +702,11 @@ mod parser_tests {
let parent = journal.get_account(account.parent);
assert_eq!("Assets", parent.name);
// amount
let Some(a1) = &p1.amount else {panic!()};
let Some(a1) = &p1.amount else { panic!() };
assert_eq!("20", a1.quantity.to_string());
let comm1 = a1.get_commodity().unwrap();
assert_eq!("VEUR", comm1.symbol);
let Some(ref cost1) = p1.cost else { panic!()};
let Some(ref cost1) = p1.cost else { panic!() };
// cost
assert_eq!(200, cost1.quantity.into());
assert_eq!("EUR", cost1.get_commodity().unwrap().symbol);
Expand All @@ -694,7 +715,7 @@ mod parser_tests {
let p2 = &posts[1];
assert_eq!("Assets", journal.get_account(p2.account).name);
// amount
let Some(a2) = &p2.amount else {panic!()};
let Some(a2) = &p2.amount else { panic!() };
assert_eq!("-200", a2.quantity.to_string());
let comm2 = a2.get_commodity().unwrap();
assert_eq!("EUR", comm2.symbol);
Expand Down Expand Up @@ -905,7 +926,9 @@ mod amount_parsing_tests {
let _ = parse_post(" Assets -20000.00 EUR", xact_ptr, &mut journal);
let xact = &journal.xacts[0];
let post = xact.posts.first().unwrap();
let Some(ref amount) = post.amount else { panic!()};
let Some(ref amount) = post.amount else {
panic!()
};

// Assert
assert_eq!("-20000.00", amount.quantity.to_string());
Expand All @@ -922,7 +945,9 @@ mod amount_parsing_tests {
let _ = parse_post(" Assets A$-20000.00", xact_ptr, &mut journal);
let xact = &journal.xacts[0];
let post = xact.posts.first().unwrap();
let Some(ref amount) = post.amount else { panic!()};
let Some(ref amount) = post.amount else {
panic!()
};

// Assert
assert_eq!("-20000.00", amount.quantity.to_string());
Expand Down
17 changes: 12 additions & 5 deletions src/reader.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! The Journal Reader.
//! Reads directives from the given source and returns them as an iterator.
//!
//! An attempt to replace the Parser::parse() method.

use std::io::{BufRead, BufReader, Cursor, Read};

Expand All @@ -13,7 +15,6 @@ pub fn create_reader<T: Read>(source: T) -> DirectiveIter<T> {
pub fn create_str_reader<T: Read>(source: &str) -> DirectiveIter<Cursor<&str>> {
let cursor = Cursor::new(source);
let iter: DirectiveIter<Cursor<&str>> = DirectiveIter::new(cursor);
// read(cursor)
iter
}

Expand Down Expand Up @@ -48,6 +49,7 @@ impl<T: Read> Iterator for DirectiveIter<T> {
}
Ok(result) => {
// TODO: Recognise directive, if any.

// TODO: Read additional lines, if needed (like for Xact).
// TODO: Parse and return the directive.

Expand All @@ -63,7 +65,7 @@ impl<T: Read> Iterator for DirectiveIter<T> {
mod tests {
use std::io::Cursor;

use crate::reader::create_str_reader;
use crate::{reader::create_str_reader, directives::DirectiveType};

#[test]
fn basic_test() {
Expand All @@ -79,14 +81,19 @@ mod tests {
assert_eq!(1, counter);
}

// #[test]
fn iterator_test() {
let content = "blah blah";
#[test]
fn one_xact_test() {
let content = r#"2023-03-04 Shop
Expenses:Clothing 20 EUR
Assets:Credit Card
"#;
//let iter = DirectiveIter::new();
let iter = create_str_reader::<Cursor<&str>>(content);

// iter.count()
for x in iter {
println!("Directive: {:?}", x);
// assert_eq!(DirectiveType::Xact())
}
}
}

0 comments on commit 6f3356f

Please sign in to comment.