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
|
use crate::tokenizer::{Token, TokenStream};
use crate::vm::{Value, Block, Op};
struct Compiler {
curr: usize,
tokens: TokenStream,
}
impl Compiler {
pub fn new(tokens: TokenStream) -> Self {
Self {
curr: 0,
tokens,
}
}
fn error(&self, msg: &str) -> ! {
println!("ERROR: {}", msg);
panic!();
}
fn peek(&self) -> Token {
if self.tokens.len() < self.curr {
crate::tokenizer::Token::EOF
} else {
self.tokens[self.curr].0.clone()
}
}
fn eat(&mut self) -> Token {
let t = self.peek();
self.curr += 1;
t
}
fn value(&mut self) -> Value {
match self.eat() {
Token::Float(f) => { Value::Float(f) },
Token::Int(f) => { Value::Int(f) }
_ => { self.error("Invalid value.") }
}
}
fn expression(&mut self, block: &mut Block) {
let a = self.value();
block.add(Op::Constant(a));
loop {
println!("{:?}", self.peek());
let op = match self.eat() {
Token::Plus => Op::Add,
Token::Minus => Op::Sub,
Token::Star => Op::Mul,
Token::Slash => Op::Div,
_ => { break; }
};
let b = self.value();
block.add(Op::Constant(b));
block.add(op);
}
}
pub fn compile(&mut self, name: &str) -> Block {
let mut block = Block::new(name);
self.expression(&mut block);
block.add(Op::Print);
block.add(Op::Return);
block
}
}
pub fn compile(name: &str, tokens: TokenStream) -> Block {
Compiler::new(tokens).compile(name)
}
|