diff options
Diffstat (limited to '')
-rw-r--r-- | src/journal.rs | 41 | ||||
-rw-r--r-- | src/main.rs | 11 | ||||
-rw-r--r-- | src/parser.rs | 124 |
3 files changed, 176 insertions, 0 deletions
diff --git a/src/journal.rs b/src/journal.rs new file mode 100644 index 0000000..d608bd0 --- /dev/null +++ b/src/journal.rs @@ -0,0 +1,41 @@ +#[allow(dead_code)] +pub struct Commodity { + name: String, +} + +#[allow(dead_code)] +pub struct Account { + name: String, + commodity: Commodity, +} + +#[allow(dead_code)] +pub struct Posting { + account: Account, + amount: i64, + commodity: Commodity, +} + +#[allow(dead_code)] +pub struct Transaction { + text: String, + payee: String, + postings: Vec<Posting>, +} + +#[allow(dead_code)] +pub struct Journal { + pub commodities: Vec<Commodity>, + pub accounts: Vec<Account>, + pub transactions: Vec<Transaction>, +} + + + +impl Commodity { + fn new(name: &str) -> Commodity { + Commodity { + name: name.to_string() + } + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..884cbe5 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,11 @@ +mod journal; +mod parser; + +use std::env; + + +fn main() { + if let Some(fname) = env::args().nth(1) { + parser::parse(&fname); + } +} diff --git a/src/parser.rs b/src/parser.rs new file mode 100644 index 0000000..c57fe14 --- /dev/null +++ b/src/parser.rs @@ -0,0 +1,124 @@ +use crate::journal::Journal; + +use std::fs; +use std::iter::Peekable; + +extern crate itertools; +extern crate time; + +use itertools::Itertools; +use time::Date; + + +#[derive(Debug, Eq, PartialEq, Clone)] +pub enum Token { + Word(String), + DateSep, + AccountSep, + DecimalSep, + Newline, + Space, + Indent, + Marker(char), + Comment(char), + Numeric(String), +} + +pub struct Lexer<I: Iterator<Item=char>> { + iter: Peekable<I> +} + +impl<I: Iterator<Item=char>> Lexer<I> { + pub fn new(iter: I) -> Lexer<I> { + Lexer { + iter: iter.peekable() + } + } +} + +impl<I: Iterator<Item=char>> Iterator for Lexer<I> { + type Item = Token; + + fn next(&mut self) -> Option<Token> { + // let ch = *self.iter.peek().unwrap_or(&'`'); + let ch = self.iter.peek() + match ch { + /* alphanumeric */ + c if c.is_alphabetic() => { + Some(Token::Word(self.iter.by_ref() + .peeking_take_while(|&c| c.is_alphabetic()).collect())) }, + c if c.is_numeric() => { + Some(Token::Numeric(self.iter.by_ref() + .peeking_take_while(|&c| c.is_numeric()).collect())) + }, + /* whitespace */ + ' ' => { + self.iter.next(); + Some(Token::Space) + }, + '\n' => { + self.iter.next(); + Some(Token::Newline) + }, + '\t' => { + self.iter.next(); + Some(Token::Indent) + }, + /* separators */ + '/' => { + self.iter.next(); + Some(Token::DateSep) + }, + ':' => { + self.iter.next(); + Some(Token::AccountSep) + }, + ',' | '.' => { + self.iter.next(); + Some(Token::DecimalSep) + }, + /* comments */ + ';' | '#' | '%' => { + self.iter.next(); + Some(Token::Comment(ch)) + }, + /* markers */ + '*' | '!' | '@' | '-' => { + self.iter.next(); + Some(Token::Marker(ch)) + }, + '`' => { + println!("--"); + None + }, + _ => self.next(), + } + } +} + + +pub fn lex(text: &str) -> Vec<Token> { + Lexer::new(text.chars()).collect() +} + + + +struct Parser { + +} + +pub fn parse(name: &str) -> Journal { + let text = fs::read_to_string(name).expect("Cannot open file"); + + println!("{:?}", text); + + for token in lex(&text) { + println!("{:?}", token); + } + + Journal { + accounts: vec![], + commodities: vec![], + transactions: vec![], + } +} |