Contributed by Simon Michaels. http://joyful.com/Ledger
fromStream: aStream
"
Parse a Ledger file.
example:
2007/10/7 longs drugs
expenses:business:phone $20
assets:cash $50
assets:wells-fargo:checking $0
grammar:
ledgerfile = entry*
entry = descriptionline, transactionline+
descriptionline = date, space, description, newline
transactionline = space, accountname, space, amount, newline
accountname = string [:, string]*
amount = currency, quantity
currency = $
quantity = number
"
| space space2 cr notcr date description descriptionline accountname
amount transactionline transactionlines entry ledger spaceandamount |
space := ' +' regex.
space2 := ' +' regex.
cr := Character cr asString.
notcr := '[^' , cr , ']'.
date := '(\d\d\d\d)/(\d\d?)/(\d\d?)' regex.
description := ('(\w' , notcr , '*)') regex.
accountname := ('[^: ' , cr , ']+(:[^: ' , cr , ']+)*') regex.
amount := '\$\d+(\.\d+)?' regex.
descriptionline := [aStream
match: date
and: space
and: description
and: cr
action: [:l | LedgerEntry withDate: l first description: l third]].
spaceandamount := [aStream
match: space2
and: amount
action: [:l | l]].
transactionline := [aStream
match: space
and: accountname
andMaybe: spaceandamount
and: cr
action: [:l | LedgerTransaction withAccount: l second amount: l fourth]].
transactionlines := [aStream
matchOneOrMore: transactionline
action: [:l | l]].
entry := [aStream
match: descriptionline
and: transactionlines
and: cr
action: [:l | l first transactions: l second]].
ledger := aStream
matchZeroOrMore: entry
action: [:l | Ledger withEntries: l].
^ ledger