jcornaz / beancount-parser Goto Github PK
View Code? Open in Web Editor NEWA beancount file parser library for rust
License: The Unlicense
A beancount file parser library for rust
License: The Unlicense
There are two big use cases for the Date
:
Both use cases, require comparing dates. Date
should implement Ord
.
The error currently only contains the line number.
It could be more helpful by explaining what was the context (e.g. directive type being parsed), what was expected (e.g. An account) and what was encountered instead.
Thanks for addressing all the other issues Jonathan.
Updating and continuing on, I see the precision syntax fail:
2013-09-10 balance Assets:US:Vanguard 305.205 ~ 0.002 RGAGX
Description
Currently, the library does not support the name_* options from Beancount, such as name_assets. These options allow users to customize the names of account types.
Beancount implementation: https://github.com/beancount/beancount/blob/d2d1e536c82281933b7bfc9cf3137f3698dcf4dc/beancount/parser/options.py#L245
https://beancount.github.io/docs/beancount_options_reference.html
Proposed Solution
To support the name_* options, the parsing logic in the library needs to be updated to dynamically handle the account types based on the options provided in the BeancountFile struct. Defaults should stay Expenses, Assets, Liabilities etc.
Example
option "name_assets" "Aktiva"
2024-03-29 balance Aktiva:Bank:Giro 123.45 USD
When authoring a beancounte file it is common to leave one posting without amount for most transactions, as beancount will automatically substitute the amount necessary to balance the transaction (so that the sum of all amounts in the transaction is 0).
When parsing a beancount file most tools need to do such automatic balancing before handling the transactions, so that they can know how much to add/remove on each account.
Even though this parser is not meant to support beancount logic, I think it does make sense to provide a convenient way to balance the transactions, because that's something almost every user of the parser will need, regardless of the tool they are building.
When it comes to the API, I am thinking about introducing a new BalancedTransaction
that would contain BalancedPosting
, with the latter having an Amount
instead of an Option<Amount>
. Or maybe make Transaction
and Posting
generic over the amount type (Option<Amount>
before balancing, and Amount
after balancing)
The conversion from Transaction
to BalancedTransaction
is fallible. In particular it will fail if there is more than one posting without amount.
I am leaning toward successfully converting from Transaction
to BalancedTransaction
if all postings have an amount regardless of what the balance is. As the purpose is not to verify that it balances to 0, but rather automatically balance if possible.
The beancount syntax allows marking transactions with tags. As I would like to filter transactions based on tags, I'd need to be able to read what are the tags defined on each transaction.
Currently the only associated Directive type is a transaction.
At minimum, there should be three additional directive types:
1.Account open & close.
2. Options. (Metadata, usually titles, precision display options, etc.)
I'm starting work on what will become beancount-rs
and I need to verify that accounts are open.
since the parser now supports escaping double quotes with slash (\"
), it only makes sense to support escaping slashes too (\\
)
The parser now supports tags on transactions (#9). However, as a user, I don't care where the tag comes from (declared on the transaction, or on the tag stack), I just want to get all the tags that apply to the transaction.
Therefore, the user may perceive the lack of support for tag stack as a bug.
This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.
These are blocked by an existing closed PR and will not be recreated unless you click a checkbox below.
Cargo.toml
miette 5.10
nom 7.1
nom_locate 4.2
thiserror 1.0
criterion 0.5.1
rstest 0.21.0
rust_decimal 1.35
miette 5.10
chumsky 0.9.3
.github/workflows/check.yml
actions/checkout v4
Swatinem/rust-cache v2
taiki-e/install-action v2
actions/checkout v4
Swatinem/rust-cache v2
taiki-e/install-action v2
.github/workflows/create-release.yml
actions/checkout v4
taiki-e/create-gh-release-action v1
Salut Jonathan,
I had a quick go at attempting to parse my large personal ledger with your Rust parser tonight -- gave it one hour to kick the tires -- and here's a quick patch of what I changed. I didn't manage to get it working, the string parser needs to get modified to allow escaping quotation marks (") with \"
.
Feel free to use or ignore.
If you can figure out how to invoke the right combinator magic to parser ", I'll resume testing soon.
lumia [git|main]:~/p/.../other/beancount-parser$ git diff
diff --git a/src/amount.rs b/src/amount.rs
index 146cf70..2b23169 100644
--- a/src/amount.rs
+++ b/src/amount.rs
@@ -153,9 +153,10 @@ fn literal<D: Decimal>(input: Span<'_>) -> IResult<'_, D> {
map_res(
recognize(tuple((
opt(char('-')),
- take_while1(|c: char| c.is_numeric() || c == '.'),
+ /* TODO(blais): Do beter, split this, no commas after period. */
+ take_while1(|c: char| c.is_numeric() || c == '.' || c == ','),
))),
- |s: Span<'_>| s.fragment().parse(),
+ |s: Span<'_>| s.fragment().replace(",", "").parse(),
)(input)
}
diff --git a/src/lib.rs b/src/lib.rs
old mode 100644
new mode 100755
index 7ff4863..5eff36f
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -461,6 +461,11 @@ fn empty_line(input: Span<'_>) -> IResult<'_, ()> {
fn string(input: Span<'_>) -> IResult<'_, &str> {
map(
+ // tuple((
+ // tag('"'),
+ // escaped_transform(none_of("\""), '\\', one_of('"')),
+ // tag('"'),
+ // )),
delimited(char('"'), take_till(|c: char| c == '"'), char('"')),
|s: Span<'_>| *s.fragment(),
)(input)
diff --git a/src/transaction.rs b/src/transaction.rs
index 397191e..8375f13 100644
--- a/src/transaction.rs
+++ b/src/transaction.rs
@@ -280,7 +280,7 @@ pub(super) fn parse_link(input: Span<'_>) -> IResult<'_, Link> {
map(
preceded(
char_tag('^'),
- take_while(|c: char| c.is_alphanumeric() || c == '-' || c == '_'),
+ take_while(|c: char| c.is_alphanumeric() || c == '-' || c == '_' || c == '.'),
),
|s: Span<'_>| Link((*s.fragment()).into()),
)(input)
I have a lot of postings like the following, due to not being in the U.S.
2022-09-09 "SR.HT" "Git hosting"
Expenses:Tech:Services:Git 50.00 USD @@ 67.98 CAD
Liabilities:Amex
I'm not sure if your parser supports this syntax. I don't see a test for it.
Also, if it does, this would be a great library to build on top of for a higher level ledger with web views, and digest tools.
Thanks for all the hard work! And to do it with no terms under to Unlicense; just amazing!
As a end-user, if there is an error in my beancount file, I would like to know at which line the error was found, so I have an easier time finding my mistakes.
Currently, the main Error
type contains no information. Needless to say, that is not very helpful ๐.
I think it should at least contain the line number.
Somehow this doesn't parse, results in a syntax error:
2022-12-27 balance Liabilities:US:BofA:Gold -(6,331.71 + 29.86) USD
A user who wants to verify that all transactions reference open accounts needs to get the open and close directives.
In your parser, after a string, if a space is not inserted, this returns a syntax error:
2019-05-25 * "DELLAPIETRASGOURMET BROOKLYN NY" "73011009146 DELLAPIETRASMEATS@GMA"#family
It's not super important, but my file contained a bunch of these (accidentally), but the Beancount C parser handles that.
from https://beancount.github.io/docs/beancount_language_syntax.html#costs-and-prices:
Amounts specified as either per-share or total prices or costs are always unsigned. It is an error to use a negative sign or a negative cost and Beancount will raise an error if you attempt to do so.
I want to build a tool to analyze my ledger and get insights about my assets and expenses. As I use multiple currencies, I would like my tool to provide currency translation. Therefore I need the price directive to get the commodity prices.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.