summaryrefslogtreecommitdiffstats
path: root/src/parser.rs
blob: 68b1c11929fa80db4adc158c41382c5d6869a2af (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
use crate::journal::Journal;

use std::fs;

extern crate time;

use time::Date;


#[derive(Debug, Eq, PartialEq, Clone)]
pub enum Token<'s> {
    Word(&'s str), Num(&'s str),
    DecimalSep(char),
    Newline, Space, Indent,
    OpenKet(char), CloseKet(char),
    Quote, Marker(char), CommentMarker,
}


struct Lexer<'s> {
    text: &'s str,
    tokens: Vec<Token<'s>>
}

impl<'s> Lexer<'s> {
    fn new(input: &str) -> Lexer {
        Lexer {
            text: input,
            tokens: Vec::new(),
        }
    }

    fn lex(&mut self) {
        #[derive(Clone,Copy)]
        enum Predicate {
            Alphabetic,
            Numeric,
        }

        let mut start = 0;
        let mut lastp: Option<Predicate> = None;

        for (i, ch) in self.text.char_indices() {
            let token: Option<Token> = match ch {
                '\t'            => Some(Token::Indent),
                '\n'            => Some(Token::Newline),
                c if c.is_whitespace() => Some(Token::Space),

                '"'             => Some(Token::Quote),
                ',' | '.'       => Some(Token::DecimalSep(ch)),

                '(' | '[' | '{' => Some(Token::OpenKet(ch)),
                ')' | ']' | '}' => Some(Token::CloseKet(ch)),

                ';' | '#' | '%' => Some(Token::CommentMarker),
                '*' | '!' | '@' | '-' | '/' | ':' => Some(Token::Marker(ch)),

                c if c.is_alphabetic() => {
                    lastp = Some(Predicate::Alphabetic);
                    None
                },
                c if c.is_numeric()    => {
                    lastp = Some(Predicate::Numeric);
                    None
                },
                _ => {
                    println!("Invalid syntax token: {}", ch);
                    None
                }
            };

            if let Some(t) = token {
                if let Some(p) = lastp {
                    if i != start {
                        self.tokens.push(match p {
                            Predicate::Alphabetic => Token::Word(&self.text[start..i]),
                            Predicate::Numeric => Token::Num(&self.text[start..i]),
                        });
                    }
                }

                self.tokens.push(t);
                start = i +1;
            }
        }
    }

    fn tokenize(input: & str) -> Vec<Token> {
        let mut lexer = Lexer::new(input);
        lexer.lex();

        lexer.tokens
    }
}


struct Parser {

}

pub fn parse(name: &str) -> Journal {
    let text = fs::read_to_string(name).expect("Cannot open file");

    println!("{:?}", text);

    for token in Lexer::tokenize(&text) {
        println!("{:?}", token);
    }

    Journal {
        accounts: vec![],
        commodities: vec![],
        transactions: vec![],
    }
}