Since REBOL is new to me, I continue to experiment with the syntax to see what feels right to me in terms of the fundamental criteria – low coupling and high cohesion. I simplified the high-level rule and put some of the processing in the lower level matching rules. I added some flexibility in ordering of terms in the input, but you have to have the description last; since it’s intended to allow any input it will greedily match the date. I think the date format needs to eventually change. I’m ignoring the definitions of the lowest level terms from here on (letter, digit, etc.) except to say that the rules for day and month now set local values:
day: [copy the-day [ [#"1" | #"2" | #"3"] [#"0" | #"1"] |
[#"1" | #"2"] digit | digit ] ]
month: [copy the-month [ "jan" | "feb" | "mar" | "apr" | "may" | "jun" |
"jul" | "aug" | "sep" | "oct" | "nov" | "dec" ] ]
It may not be proper style to be clearing things at the beginning of the
sentence rule, but it works and is clear. I got rid of the subject handling we had before, and I’m trying out a handler concept for tags. All we do when the rule completes now is print the parsed terms.
sentence: [( the-date: now/date
the-subject: copy ""
the-desc: copy ""
the-tags: copy  )
some [ [some ws] | ["on" some ws date] | subject | amount | copy the-desc desc]
(print [the-date the-desc the-subject the-amount the-tags])
I changed the main rule to use some around a choice, instead of a bunch of alternative choices. The terms are set by the individual rules like date and desc:
desc: [some [tag | some name-char | ws]]
tag: [copy a-tag [ #"#" some name-char ] (tag-handler a-tag append the-tags a-tag)]
subject: [copy the-subject [ #"@" letter any name-char ]]
amount: [copy the-amount [ opt sign some digit opt [ "." 0 2 digit ] ]
(the-amount: to decimal! the-amount)]
date: [[ day | month ] [ [some ws] | #"/" ] [ month | day ] (
the-date: either (current: to date! rejoin [the-day "-" the-month "-" default/year]) > (default/date + 200)
[to date! rejoin [ the-day "-" the-month "-" (default/year - 1) ]]
clear the-day clear the-month
You can see the tag-handler called in the tag rule. We’ll get to that. The date rule calculates the year automatically; if it’s more than 200 days in advance, we assume last year. My default tag-handler is expecting the current tag, and the accumulated tags block.
tag-handler: func [
print ["tag found" tag "/" tags "/"]
There’s multiple ways in REBOL for us to supply that tag-handler, which we’ll look at as our needs become clearer. Run the rule with a reasonably human sentence:
>> parse/all “@visa on 19 Dec -230.21 #statefarm #insurance for #condo interior contents” iAm/sentence
tag found #statefarm / #statefarm /
tag found #insurance / #statefarm #insurance /
tag found #condo / #statefarm #insurance #condo /
19-Dec-2011 #statefarm #insurance for #condo interior contents @visa -230 #statefarm #insurance #condo
Looking at it now, I might like moving the copy commands from the sub-rules back into sentence. I plan soon to import all my GnuCash transactions into a REBOL format I can query and add to. I’ll need to be able to query and edit them, and I’m hoping that it’s unnecessary to have a bunch of hierarchical expense and income accounts.
It hit me today that tagging allows “multiple inheritance” in contrast to hierarchies of organization.
Up until the last few years I’ve been doing my own taxes, and the only useful information I can recall needing is totals for certain categories of spending. Which forces me to categorize the transaction under only that applicable account. I’d rather tag it with meaningful attributes, among them #tax #deduction.