Compare commits
2 commits
99be8a16c7
...
8d2582756d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8d2582756d | ||
|
|
a3d9723a36 |
6 changed files with 65 additions and 63 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::parser::{BinaryOp, Expr, UnaryOp};
|
use crate::expr::{BinaryOp, Expr, UnaryOp};
|
||||||
|
|
||||||
pub struct Evaluator {
|
pub struct Evaluator {
|
||||||
ast: Expr
|
ast: Expr
|
||||||
|
|
|
||||||
45
src/expr.rs
Normal file
45
src/expr.rs
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum BinaryOp {
|
||||||
|
Add,
|
||||||
|
Sub,
|
||||||
|
Mul,
|
||||||
|
Div,
|
||||||
|
Mod
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum UnaryOp {
|
||||||
|
Neg
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn prefix_bp(op: &UnaryOp) -> u8 {
|
||||||
|
match op {
|
||||||
|
UnaryOp::Neg => 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn infix_bp(op: &BinaryOp) -> (u8, u8) {
|
||||||
|
match op {
|
||||||
|
BinaryOp::Add | BinaryOp::Sub => (1, 2),
|
||||||
|
BinaryOp::Mul | BinaryOp::Div | BinaryOp::Mod => (3, 4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum Expr {
|
||||||
|
Number(i64),
|
||||||
|
Ident(String),
|
||||||
|
EOL,
|
||||||
|
|
||||||
|
Binary {
|
||||||
|
op: BinaryOp,
|
||||||
|
left: Box<Expr>,
|
||||||
|
right: Box<Expr>
|
||||||
|
},
|
||||||
|
|
||||||
|
Unary {
|
||||||
|
op: UnaryOp,
|
||||||
|
right: Box<Expr>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
10
src/lexer.rs
10
src/lexer.rs
|
|
@ -54,11 +54,11 @@ impl Lexer {
|
||||||
Some(b'0' ..= b'9') => self.number(),
|
Some(b'0' ..= b'9') => self.number(),
|
||||||
Some(b'a' ..= b'z' | b'A' ..= b'Z') => self.ident(),
|
Some(b'a' ..= b'z' | b'A' ..= b'Z') => self.ident(),
|
||||||
|
|
||||||
Some(b'+') => {self.advance(); Some(Token::Add)},
|
Some(b'+') => {self.advance(); Some(Token::Plus)},
|
||||||
Some(b'-') => {self.advance(); Some(Token::Sub)},
|
Some(b'-') => {self.advance(); Some(Token::Minus)},
|
||||||
Some(b'*') => {self.advance(); Some(Token::Mul)},
|
Some(b'*') => {self.advance(); Some(Token::Asterisk)},
|
||||||
Some(b'/') => {self.advance(); Some(Token::Div)},
|
Some(b'/') => {self.advance(); Some(Token::Slash)},
|
||||||
Some(b'%') => {self.advance(); Some(Token::Mod)},
|
Some(b'%') => {self.advance(); Some(Token::Percent)},
|
||||||
|
|
||||||
Some(b'(') => {self.advance(); Some(Token::LParen)},
|
Some(b'(') => {self.advance(); Some(Token::LParen)},
|
||||||
Some(b')') => {self.advance(); Some(Token::RParen)},
|
Some(b')') => {self.advance(); Some(Token::RParen)},
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
use std::{fs::File, io::Read};
|
use std::{fs::File, io::Read};
|
||||||
|
|
||||||
mod token;
|
mod token;
|
||||||
|
mod expr;
|
||||||
mod lexer;
|
mod lexer;
|
||||||
use lexer::Lexer;
|
use lexer::Lexer;
|
||||||
mod parser;
|
mod parser;
|
||||||
|
|
@ -30,7 +31,7 @@ fn main() -> std::io::Result<()> {
|
||||||
loop {
|
loop {
|
||||||
let parsed = parser.parse();
|
let parsed = parser.parse();
|
||||||
match parsed {
|
match parsed {
|
||||||
parser::Expr::EOL => break,
|
expr::Expr::EOL => break,
|
||||||
_ => {
|
_ => {
|
||||||
println!("AST: {:?}", parsed);
|
println!("AST: {:?}", parsed);
|
||||||
let eval = Evaluator::new(parsed);
|
let eval = Evaluator::new(parsed);
|
||||||
|
|
|
||||||
|
|
@ -1,49 +1,5 @@
|
||||||
use crate::token::Token;
|
use crate::token::Token;
|
||||||
|
use crate::expr::{Expr, UnaryOp, BinaryOp, infix_bp, prefix_bp};
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum BinaryOp {
|
|
||||||
Add,
|
|
||||||
Sub,
|
|
||||||
Mul,
|
|
||||||
Div,
|
|
||||||
Mod
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum UnaryOp {
|
|
||||||
Neg
|
|
||||||
}
|
|
||||||
|
|
||||||
fn prefix_bp(op: &UnaryOp) -> u8 {
|
|
||||||
match op {
|
|
||||||
UnaryOp::Neg => 5
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn infix_bp(op: &BinaryOp) -> (u8, u8) {
|
|
||||||
match op {
|
|
||||||
BinaryOp::Add | BinaryOp::Sub => (1, 2),
|
|
||||||
BinaryOp::Mul | BinaryOp::Div | BinaryOp::Mod => (3, 4)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum Expr {
|
|
||||||
Number(i64),
|
|
||||||
Ident(String),
|
|
||||||
EOL,
|
|
||||||
|
|
||||||
Binary {
|
|
||||||
op: BinaryOp,
|
|
||||||
left: Box<Expr>,
|
|
||||||
right: Box<Expr>
|
|
||||||
},
|
|
||||||
|
|
||||||
Unary {
|
|
||||||
op: UnaryOp,
|
|
||||||
right: Box<Expr>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Parser {
|
pub struct Parser {
|
||||||
tokens: Vec<Token>,
|
tokens: Vec<Token>,
|
||||||
|
|
@ -90,7 +46,7 @@ impl Parser {
|
||||||
|
|
||||||
fn parse_prefix(&mut self) -> Expr {
|
fn parse_prefix(&mut self) -> Expr {
|
||||||
match self.peek() {
|
match self.peek() {
|
||||||
Some(Token::Sub) => {
|
Some(Token::Minus) => {
|
||||||
self.advance();
|
self.advance();
|
||||||
let op = UnaryOp::Neg;
|
let op = UnaryOp::Neg;
|
||||||
|
|
||||||
|
|
@ -108,11 +64,11 @@ impl Parser {
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let op = match self.peek() {
|
let op = match self.peek() {
|
||||||
Some(Token::Add) => BinaryOp::Add,
|
Some(Token::Plus) => BinaryOp::Add,
|
||||||
Some(Token::Sub) => BinaryOp::Sub,
|
Some(Token::Minus) => BinaryOp::Sub,
|
||||||
Some(Token::Mul) => BinaryOp::Mul,
|
Some(Token::Asterisk) => BinaryOp::Mul,
|
||||||
Some(Token::Div) => BinaryOp::Div,
|
Some(Token::Slash) => BinaryOp::Div,
|
||||||
Some(Token::Mod) => BinaryOp::Mod,
|
Some(Token::Percent) => BinaryOp::Mod,
|
||||||
_ => break
|
_ => break
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
10
src/token.rs
10
src/token.rs
|
|
@ -4,11 +4,11 @@ pub enum Token {
|
||||||
Ident(String),
|
Ident(String),
|
||||||
|
|
||||||
// Operators
|
// Operators
|
||||||
Add,
|
Plus,
|
||||||
Sub,
|
Minus,
|
||||||
Mul,
|
Asterisk,
|
||||||
Div,
|
Slash,
|
||||||
Mod,
|
Percent,
|
||||||
|
|
||||||
// Parentheses
|
// Parentheses
|
||||||
LParen,
|
LParen,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue