Website Summary Files Commits Branches @commit @diff @stats
path: root / assembler / src / parser / syntax.rs
blob: fedb78d2ce2e11f559d17b5d8468bbea318ccf3a (plain) (blame)
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
use crate::{ Word, lexer::Token };
use super::{ Program, Address, Instruction };

impl Program {
    pub(crate) fn new(tokens: Vec<Token>, absolute_start: usize) -> Program {
        let mut prog = Program {absolute_start, ..Default::default() };

        let mut op_name = String::new();
        let mut op_args = Vec::new();
        let mut value = Address::None;
        let mut symbol_def = String::new();

        for token in tokens {
            match token {
                /* Names (lvalue) */
                Token::Operator(name) => {
                    if ! op_name.is_empty() {
                        prog.instructions.push(Instruction {
                            name: op_name,
                            args: op_args.clone(),
                        });
                    }
                    op_name = name;
                    op_args.clear();
                },
                Token::Label(name) => {
                    // Predicting the index
                    let index = prog.instructions.len() + !op_name.is_empty() as usize;
                    prog.definitions.insert(name, Address::Instruction(index));
                },
                Token::SymbolDef(name) => symbol_def = name,

                /* Values (rvalue) */
                Token::Address(num) => {
                    value = Address::Memory(num as usize);
                },
                Token::Number(num) => {
                    prog.constants.push(num);
                    value = Address::Constants(prog.constants.len() - 1);
                },
                Token::String(str) => {
                    let index = prog.constants.len();
                    for c in str.chars() {
                        prog.constants.push(c as Word);
                    }
                    prog.constants.push(0); // terminating null
                    value = Address::Constants(index);
                },
                Token::Symbol(name) => {
                    value = Address::Definitions(name);
                },
            }

            if value != Address::None {
                if ! symbol_def.is_empty() {
                    prog.definitions.insert(symbol_def.clone(), value.take());
                    symbol_def.clear();
                }
                else {
                    op_args.push(value.take());
                }
            }
        }

        if ! op_name.is_empty() {
            prog.instructions.push(Instruction {
                name: op_name,
                args: op_args.clone(),
            });
        }

        prog
    }
}