summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/journal.rs41
-rw-r--r--src/main.rs11
-rw-r--r--src/parser.rs124
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![],
+ }
+}