diff options
| -rw-r--r-- | src/compiler.rs | 77 | ||||
| -rw-r--r-- | src/main.rs | 18 | ||||
| -rw-r--r-- | src/tokenizer.rs | 8 | ||||
| -rw-r--r-- | src/vm.rs | 20 | ||||
| -rw-r--r-- | tests/simple.tdy | 11 |
5 files changed, 107 insertions, 27 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) +} diff --git a/src/main.rs b/src/main.rs index 72fb8a1..c9a7602 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,23 +1,11 @@ mod tokenizer; mod vm; +mod compiler; fn main() { - /* let tokens = tokenizer::file_to_tokens("tests/simple.tdy"); - for token in tokens.iter() { - println!("| {:?}", token); - } - */ + let block = compiler::compile("main", tokens); - let mut blocks = vm::Block::new("main"); - blocks.add(vm::Op::Constant(vm::Value::Bool(true))); - blocks.add(vm::Op::Print); - blocks.add(vm::Op::Constant(vm::Value::Int(123))); - blocks.add(vm::Op::Constant(vm::Value::Int(123))); - blocks.add(vm::Op::Add); - blocks.add(vm::Op::Print); - blocks.add(vm::Op::Return); - - vm::run_block(blocks); + vm::run_block(block); } diff --git a/src/tokenizer.rs b/src/tokenizer.rs index efea700..cb2d7b8 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -1,7 +1,7 @@ use std::fs; use logos::{Logos, Span}; -#[derive(Logos, Debug, PartialEq)] +#[derive(Logos, Debug, PartialEq, Clone)] pub enum Token { #[regex(r"[[:alpha:]][[:alnum:]]*", |lex| lex.slice().to_string())] Identifier(String), @@ -94,11 +94,15 @@ pub enum Token { #[regex(r"[ \t\r]", logos::skip)] Whitespace, + EOF, + #[error] Error, } -pub fn file_to_tokens(filename: &str) -> Vec<(Token, Span)> { +pub type PlacedToken = (Token, Span); +pub type TokenStream = Vec<PlacedToken>; +pub fn file_to_tokens(filename: &str) -> TokenStream { let content = fs::read_to_string(filename).unwrap(); let lexer = Token::lexer(&content); lexer.spanned().collect() @@ -112,6 +112,26 @@ impl VM { } Op::Mul => { + let b = self.stack.pop().unwrap(); + let a = self.stack.pop().unwrap(); + match (a, b) { + (Value::Float(a), Value::Float(b)) => self.stack.push(Value::Float(b * a)), + (Value::Int(a), Value::Int(b)) => self.stack.push(Value::Int(b * a)), + _ => unimplemented!("Cannot mul '{:?}' and '{:?}'.", a, b), + } + } + + Op::Div => { + let b = self.stack.pop().unwrap(); + let a = self.stack.pop().unwrap(); + match (a, b) { + (Value::Float(a), Value::Float(b)) => self.stack.push(Value::Float(b / a)), + (Value::Int(a), Value::Int(b)) => self.stack.push(Value::Int(b / a)), + _ => unimplemented!("Cannot mul '{:?}' and '{:?}'.", a, b), + } + } + + Op::Mul => { todo!(); } diff --git a/tests/simple.tdy b/tests/simple.tdy index d962330..d248afd 100644 --- a/tests/simple.tdy +++ b/tests/simple.tdy @@ -1,10 +1 @@ -1234 -1234.123 - -a.b - -if abcde { - a = true - c++ -} -b = false +1 + 1 * 2 |
