https://github.com/cfsamson/qa-parser
QuickAccount Parser - parsing library for a financial reporting DSL
https://github.com/cfsamson/qa-parser
Last synced: 2 months ago
JSON representation
QuickAccount Parser - parsing library for a financial reporting DSL
- Host: GitHub
- URL: https://github.com/cfsamson/qa-parser
- Owner: cfsamson
- Created: 2020-02-29T21:10:31.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2020-02-29T22:01:40.000Z (over 5 years ago)
- Last Synced: 2025-02-09T22:22:40.663Z (4 months ago)
- Language: Rust
- Size: 10.7 KB
- Stars: 1
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# QuickAccount Parser - A parser for a financial reporting DSL
Library for parsing a small DLS for financial reporting. The specific needs for such a DSL is
probably country specific but this DLS is based on account numbers beeing in a specific
range for each major "account group".To be able to let users configure reports dynamically we let them specify ranges of accounts
and group them togheher and specify a label for both a header (optional) and a group.```
Sales (
3010..3010 => Webshop
3010..4000 => Other sales
) => Sum sales
```This will typically be represented in a report as:
```
SALES
Webshop xxxx
Other sales xxxx
-------------------
Sum sales xxxx
===================
```The "title" is optional:
```
(
3010..3010 => Webshop
3010..4000 => Other sales
) => Sum sales
```Would (typically) be represented as:
```
Webshop xxxx
Other sales xxxx
-------------------
Sum sales xxxx
===================
```The groups can be nested to as many levels as you want (in the highly unlikely scnario that you
create nesting above a few houndred levels this might cause a stack overflow since we parse
these recursively):```
Other costs (
6000..6010 => Leasing
(
6020..6100 => Office supplies
6100..6200 => Consumables
) => Sum misc. costs
) => Sum other costs
```Would typically be:
```
OTHER COSTS
Leasing xxxx
Office supplies xxxx
Consumables xxxx
------------------------
Sum misc. costs xxxx
-----------------------------
Sum other costs xxxx
=============================
```The full DSL looks like this
```
Sales (
3010..3010 => Webshop
3010..4000 => Other sales
) => Sum sales(
4000..5000 => Material
) => Sum material(
5000..5000 => Direct labor
5010..6000 => Other labor costs
) => Sum labor costsOther costs (
6000..6010 => Leasing
(
6020..6100 => Office supplies
6100..6200 => Consumables
) => Sum miscellaneous costs
) => Sum other costs
```## Syntax tree
The DSL will be parsed into a syntax tree. Since the DSL and the syntax is so small
it's easier to just show it here. The eaxmple above will get parsed into a syntax tree
looking like this:```rust
[
Span {
name: Some("Sales"),
ranges: [
Range {
title: "Webshop",
from: 3010,
to: 3010,
},
Range {
title: "Other sales",
from: 3010,
to: 4000,
},
],
subspans: [],
sum_type: SumTotal(Some("Sum sales")),
},
Span {
name: None,
ranges: [
Range {
title: "Material",
from: 4000,
to: 5000,
},
],
subspans: [],
sum_type: SumTotal(Some("Sum material")),
},
Span {
name: None,
ranges: [
Range {
title: "Direct labor",
from: 5000,
to: 5000,
},
Range {
title: "Other labor costs",
from: 5010,
to: 6000,
},
],
subspans: [],
sum_type: SumTotal(Some("Sum labor costs")),
},
Span {
name: Some("Other costs"),
ranges: [
Range {
title: "Leasing",
from: 6000,
to: 6010,
},
],
subspans: [
Span {
name: None,
ranges: [
Range {
title: "Office supplies",
from: 6020,
to: 6100,
},
Range {
title: "Consumables",
from: 6100,
to: 6200,
},
],
subspans: [],
sum_type: SubTotal(Some("Sum miscellaneous costs")),
},
],
sum_type: SumTotal(Some("Sum other costs")),
},
]
```## Error reporting
The error reporting tries to mimick that of Rusts:
```rust
let test = "
(
6000..6010 => Leasing
(
6020.6100 => Office Supplies
6100..6200 => Consumables
) => Sum miscellaneous costs
) == Sum other costs
";let mut parser = Parser::new(test);
match parser.parse() {
Ok(_) => (),
Err(e) => println!("{}", e),
}
```Gives an error message looking like this:
```
line: 5, pos: 22
6020.6100 => Office Supplies
---------------------^ERROR: Invalid range syntax
```## Development status
Note that while this correctly parses the example above it's not extensively tested for all
edge cases so if you use this library make sure to add your own tests and confirm that it
works the way you expect it.