diff options
Diffstat (limited to 'src/compiler.rs')
| -rw-r--r-- | src/compiler.rs | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/src/compiler.rs b/src/compiler.rs new file mode 100644 index 0000000..59659f4 --- /dev/null +++ b/src/compiler.rs @@ -0,0 +1,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) +} |
