Skip to content

Commit

Permalink
Merge pull request #383 from zhang-accounting/381-cannot-parse-commen…
Browse files Browse the repository at this point in the history
…t-lines-betwen-actual-postings

inconsistent space in postings and optional space in posting cost
  • Loading branch information
Kilerd authored Oct 18, 2024
2 parents c424339 + 0e13708 commit 0468db0
Show file tree
Hide file tree
Showing 19 changed files with 195 additions and 96 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/build-latest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ jobs:
- name: fake frontend build
run: mkdir -p dist
working-directory: ./frontend
- uses: actions/setup-python@v5
with:
python-version: '3.10'
- name: Run test
run: cargo test --features ${{matrix.features}}
wasm-test:
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@ jobs:
if: startsWith(matrix.os, 'ubuntu')
run: sudo apt install pkg-config libssl-dev

- uses: actions/setup-python@v5
with:
python-version: '3.10'

- name: cargo build
uses: houseabsolute/actions-rust-cross@v0
with:
Expand Down
31 changes: 14 additions & 17 deletions extensions/beancount/src/beancount.pest
Original file line number Diff line number Diff line change
Expand Up @@ -33,46 +33,43 @@ valuable_comment = { space* ~ comment_prefix ~ space* ~ comment_value }
comment_prefix = { ";" | "*" | "#" | "//" }
comment_value = { (!line ~ ANY)* }

transaction = { date ~ transaction_flag? ~ (space+ ~ quote_string){0, 2} ~ tags_or_links? ~ space* ~ comment? ~ transaction_detail }
transaction = { date ~ transaction_flag? ~ (space+ ~ quote_string){0, 2} ~ tags_or_links? ~ space* ~ comment? ~ transaction_lines }

transaction_flag = { space+ ~ ("!" | "*" | "#" | ASCII_ALPHA_UPPER) }

tags_or_links = { (space* ~ (tag | link))* }
tag = { "#" ~ unquote_string }
link = { "^" ~ unquote_string }

transaction_detail = _{ indentation_push ~ transaction_lines ~ DROP }
transaction_lines = { transaction_line ~ (transaction_next_line)* }
transaction_line = { (transaction_posting | key_value_line) ~ space* ~ valuable_comment? }
transaction_posting = { transaction_flag? ~ account_name ~ (space+ ~ posting_unit)? ~ metas? }
transaction_next_line = _{ indentation ~ transaction_line }
transaction_lines = { transaction_line+}
transaction_line = { indentation ~ (transaction_posting | key_value_line)? ~ space* ~ valuable_comment? }
transaction_posting = { transaction_flag? ~ account_name ~ (space+ ~ posting_unit)? }

posting_unit = { (posting_amount)? ~ posting_meta }
posting_amount = { number_expr ~ space+ ~ commodity_name }
posting_meta = { (space+ ~ posting_cost_prefix ~ space* ~ posting_cost? ~ price_cost_date? ~ space* ~ posting_cost_postfix)? ~ space* ~ posting_price? }
posting_amount = { number_expr ~ space* ~ commodity_name }
posting_meta = { (space* ~ posting_cost_prefix ~ space* ~ posting_cost? ~ price_cost_date? ~ space* ~ posting_cost_postfix)? ~ space* ~ posting_price? }


posting_cost_prefix = { "{" }
posting_cost_postfix = { "}" }
posting_cost = { number_expr ~ space+ ~ commodity_name }
posting_cost = { number_expr ~ space* ~ commodity_name }
price_cost_date = _{ space* ~ "," ~ space* ~ date }
posting_price = { posting_single_price | posting_total_price }

posting_single_price = { "@" ~ space+ ~ number_expr ~ space+ ~ commodity_name }
posting_total_price = { "@@" ~ space+ ~ number_expr ~ space+ ~ commodity_name }
posting_single_price = { "@" ~ space* ~ number_expr ~ space* ~ commodity_name }
posting_total_price = { "@@" ~ space* ~ number_expr ~ space* ~ commodity_name }

string_or_account = { account_name | string }

metas = { indentation_push ~ key_value_lines ~ DROP }
metas = { key_value_lines }

booking_method = { "\"" ~ ("STRICT" | "FIFO" | "LIFO" | "AVERAGE" | "AVERAGE_ONLY" | "NONE") ~ "\"" }

indentation = _{ line ~ PEEK_ALL }
indentation_push = _{ indentation ~ PUSH(space+) }
indentation = _{ line ~ space+ }

key_value_lines = _{ key_value_line_with_comment ~ (key_value_next_line)* }
key_value_next_line = _{ indentation ~ key_value_line_with_comment }
key_value_lines = _{ (line ~ space+ ~ key_value_line_with_comment)+ }
key_value_line_with_comment = _{ key_value_line ~ space* ~ comment? }
key_value_line = { string ~ space* ~ ":" ~ space* ~ string }
key_value_line_with_comment = _{ key_value_line ~ space* ~ comment? }

date = { date_only }
date_only = { ASCII_DIGIT{4} ~ "-" ~ ASCII_DIGIT{1, 2} ~ "-" ~ ASCII_DIGIT{1, 2} }
Expand Down
30 changes: 6 additions & 24 deletions extensions/beancount/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,20 +274,14 @@ impl BeancountParser {
Option<Flag>,
Account,
Option<(Option<Amount>, Option<(Option<PostingCost>, Option<SingleTotalPrice>)>)>,
Meta,
) = match_nodes!(input.into_children();
[account_name(account_name)] => (None, account_name, None, Meta::default()),
[account_name(account_name), posting_unit(unit)] => (None, account_name, Some(unit), Meta::default()),
[transaction_flag(flag), account_name(account_name)] => (flag, account_name, None, Meta::default()),
[transaction_flag(flag), account_name(account_name), posting_unit(unit)] => (flag, account_name, Some(unit), Meta::default()),

[account_name(account_name), metas(meta)] => (None, account_name, None, meta),
[account_name(account_name), posting_unit(unit), metas(meta)] => (None, account_name, Some(unit), meta),
[transaction_flag(flag), account_name(account_name), metas(meta)] => (flag, account_name, None, meta),
[transaction_flag(flag), account_name(account_name), posting_unit(unit), metas(meta)] => (flag, account_name, Some(unit), meta),
[account_name(account_name)] => (None, account_name, None),
[account_name(account_name), posting_unit(unit)] => (None, account_name, Some(unit)),
[transaction_flag(flag), account_name(account_name)] => (flag, account_name, None),
[transaction_flag(flag), account_name(account_name), posting_unit(unit)] => (flag, account_name, Some(unit)),
);

let (flag, account, unit, meta) = ret;
let (flag, account, unit) = ret;

let mut line = Posting {
flag,
Expand All @@ -296,7 +290,6 @@ impl BeancountParser {
cost: None,
price: None,
comment: None,
meta,
};

if let Some((amount, meta)) = unit {
Expand All @@ -316,7 +309,7 @@ impl BeancountParser {
[transaction_posting(posting), valuable_comment(c)] => (Some(posting.set_comment(c)), None),
[key_value_line(meta)] => (None, Some(meta)),
[key_value_line(meta), valuable_comment(_)] => (None, Some(meta)),

[valuable_comment(_)] => (None, None),
);
Ok(ret)
}
Expand Down Expand Up @@ -763,16 +756,6 @@ mod test {

use crate::parser::test::get_txn;

#[test]
fn should_parse_posting_meta() {
let directive = get_txn(indoc! {r#"
1970-01-01 "Payee" "Narration"
Assets:Bank
a: b
"#});
assert_eq!(directive.postings.first().unwrap().meta.get_one("a").cloned().unwrap().to_plain_string(), "b");
}

#[test]
fn should_parse_with_comment() {
let directive = get_txn(indoc! {r#"
Expand All @@ -783,7 +766,6 @@ mod test {
a: b
b: c ;123123
"#});
assert_eq!(directive.postings.first().unwrap().meta.get_one("a").cloned().unwrap().to_plain_string(), "b");
assert_eq!(directive.postings.get(1).unwrap().comment.as_ref().unwrap(), "123213");
}

Expand Down
27 changes: 27 additions & 0 deletions integration-tests/comments-between-postings/main.bean
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
option "operating_currency" "CNY"

1970-01-01 open Assets:BankCard CNY

1970-01-01 open Expenses:Food CNY

2023-12-06 "KFC" "VME50 Package"
; comment here
Assets:BankCard -50 CNY
Expenses:Food

2023-12-06 "KFC" "VME50 Package"
Assets:BankCard -50 CNY
; comment here
Expenses:Food
; comment here

2023-12-06 "KFC" "VME50 Package"
Assets:BankCard -50 CNY
Expenses:Food
; comment here

2023-12-06 "KFC" "VME50 Package"
Assets:BankCard -50 CNY
Expenses:Food
; comment here
; comment here
27 changes: 27 additions & 0 deletions integration-tests/comments-between-postings/main.zhang
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
option "operating_currency" "CNY"

1970-01-01 open Assets:BankCard CNY

1970-01-01 open Expenses:Food CNY

2023-12-06 "KFC" "VME50 Package"
; comment here
Assets:BankCard -50 CNY
Expenses:Food

2023-12-06 "KFC" "VME50 Package"
Assets:BankCard -50 CNY
; comment here
Expenses:Food
; comment here

2023-12-06 "KFC" "VME50 Package"
Assets:BankCard -50 CNY
Expenses:Food
; comment here

2023-12-06 "KFC" "VME50 Package"
Assets:BankCard -50 CNY
Expenses:Food
; comment here
; comment here
23 changes: 23 additions & 0 deletions integration-tests/comments-between-postings/validations.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[
{
"uri": "/api/journals",
"validations": [
[
"$.data.records[0].postings.length()",
2
],
[
"$.data.records[1].postings.length()",
2
],
[
"$.data.records[2].postings.length()",
2
],
[
"$.data.records[3].postings.length()",
2
]
]
}
]
11 changes: 11 additions & 0 deletions integration-tests/inconsistent-indent-for-postings/main.bean
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
option "operating_currency" "CNY"

1970-01-01 open Assets:BankCard CNY

1970-01-01 open Expenses:Food CNY

2023-12-06 * "KFC" "VME50 Package"
Expenses:Food -0.1CNY
Assets:BankCard 0.1 CNY
Assets:BankCard
Expenses:Food -0.1CNY
11 changes: 11 additions & 0 deletions integration-tests/inconsistent-indent-for-postings/main.zhang
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
option "operating_currency" "CNY"

1970-01-01 open Assets:BankCard CNY

1970-01-01 open Expenses:Food CNY

2023-12-06 * "KFC" "VME50 Package"
Expenses:Food -0.1CNY
Assets:BankCard 0.1 CNY
Assets:BankCard
Expenses:Food -0.1CNY
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[
{
"uri": "/api/journals",
"validations": [
[
"$.data.records[0].postings.length()",
4
]
]
}
]
10 changes: 10 additions & 0 deletions integration-tests/space-of-posting-uint-can-be-empty/main.bean
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
option "operating_currency" "CNY"

1970-01-01 open Assets:BankCard CNY

1970-01-01 open Expenses:Food CNY

2023-12-06 "KFC" "VME50 Package"
Expenses:A -0.1CNY
Expenses:Food -0.1CNY@1USD
Expenses:Food -0.1CNY@@1USD
10 changes: 10 additions & 0 deletions integration-tests/space-of-posting-uint-can-be-empty/main.zhang
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
option "operating_currency" "CNY"

1970-01-01 open Assets:BankCard CNY

1970-01-01 open Expenses:Food CNY

2023-12-06 "KFC" "VME50 Package"
Expenses:A -0.1CNY
Expenses:Food -0.1CNY@1USD
Expenses:Food -0.1CNY@@1USD
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[
{
"uri": "/api/journals",
"validations": [
[
"$.data.records[0].postings.length()",
3
]
]
}
]
1 change: 0 additions & 1 deletion zhang-ast/src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ pub struct Posting {
pub cost: Option<PostingCost>,
pub price: Option<SingleTotalPrice>,
pub comment: Option<String>,
pub meta: Meta,
}
impl Posting {
pub fn set_comment(mut self, comment: String) -> Self {
Expand Down
15 changes: 6 additions & 9 deletions zhang-core/src/data_type/text/exporter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ impl ZhangDataTypeExportable for Transaction {
let mut transaction = self
.postings
.into_iter()
.flat_map(|posting| posting.export())
.map(|posting| posting.export())
.map(|it| format!(" {}", it))
.collect_vec();
transaction.insert(0, header.into_iter().flatten().join(" "));
Expand All @@ -107,8 +107,8 @@ impl ZhangDataTypeExportable for Transaction {
}

impl ZhangDataTypeExportable for Posting {
type Output = Vec<String>;
fn export(self) -> Vec<String> {
type Output = String;
fn export(self) -> String {
// todo cost and price
let cost_string = self.cost.map(|it| it.export());
let vec1 = vec![
Expand All @@ -118,10 +118,7 @@ impl ZhangDataTypeExportable for Posting {
cost_string,
self.price.map(|it| it.export()),
];
let mut ret = self.meta.export().into_iter().map(|it| format!(" {}", it)).collect_vec();
ret.insert(0, vec1.into_iter().flatten().join(" "));

ret
vec1.into_iter().flatten().join(" ")
}
}

Expand Down Expand Up @@ -540,12 +537,12 @@ mod test {
);

assert_parse!(
"transaction posting with meta",
"transaction posting and meta",
indoc! {r#"
1970-01-01 * "Payee" "Narration" ^link1 ^link-2
Assets:123 -1 CNY
a: b
Expenses:TestCategory:One 1 CCC @@ 1 CNY
a: b
"#}
);
}
Expand Down
Loading

0 comments on commit 0468db0

Please sign in to comment.