parse math expressions
This commit is contained in:
parent
fcac4db1dc
commit
e2213a627b
3 changed files with 75 additions and 5 deletions
15
src/ast.rs
15
src/ast.rs
|
|
@ -8,6 +8,19 @@ pub enum Ident {
|
|||
Return(Symbol),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub enum BinOp {
|
||||
Add,
|
||||
Sub,
|
||||
Mul,
|
||||
Div,
|
||||
Mod,
|
||||
Pow,
|
||||
Eq,
|
||||
Lt,
|
||||
Le,
|
||||
}
|
||||
|
||||
// TODO: great display repr for this for testing (yes it's allowed)
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Ast {
|
||||
|
|
@ -26,7 +39,7 @@ pub enum Ast {
|
|||
/// `f x`
|
||||
App(Box<Ast>, Box<Ast>),
|
||||
/// `x + y` (only builtins, sorry)
|
||||
BinOp(Box<Ast>, fn(Val, Val) -> Val, Box<Ast>),
|
||||
BinOp(Box<Ast>, BinOp, Box<Ast>),
|
||||
/// `3`
|
||||
Num(f64),
|
||||
/// `(println bla; 3) #=> 3`
|
||||
|
|
|
|||
|
|
@ -3,10 +3,11 @@ use std::{fmt, process};
|
|||
use ariadne::{Color, Label, Report, ReportKind, Source};
|
||||
use chumsky::{
|
||||
input::{Stream, ValueInput},
|
||||
pratt::{infix, left, none, right},
|
||||
prelude::*,
|
||||
};
|
||||
|
||||
use crate::ast::{Ast, Ident};
|
||||
use crate::ast::{Ast, BinOp, Ident};
|
||||
|
||||
use logos::Logos;
|
||||
|
||||
|
|
@ -47,7 +48,7 @@ enum Token<'a> {
|
|||
#[token("fn")]
|
||||
Fn,
|
||||
|
||||
#[regex(r"[+*/%=-]")]
|
||||
#[regex(r"([+*/%=<>-]|\*\*|<=|>=)")]
|
||||
BinOp(&'a str),
|
||||
|
||||
#[regex(r"[a-zA-Z_][a-zA-Z_0-9']*")]
|
||||
|
|
@ -210,7 +211,45 @@ where
|
|||
})
|
||||
.labelled("function application");
|
||||
|
||||
app.or(non_app)
|
||||
let atom = app.or(non_app);
|
||||
|
||||
// %
|
||||
atom.pratt((
|
||||
infix(none(10), just(Token::BinOp("=")), |l, _, r, _| {
|
||||
Ast::BinOp(Box::new(l), BinOp::Eq, Box::new(r))
|
||||
}),
|
||||
infix(none(10), just(Token::BinOp("<")), |l, _, r, _| {
|
||||
Ast::BinOp(Box::new(l), BinOp::Lt, Box::new(r))
|
||||
}),
|
||||
infix(none(10), just(Token::BinOp("<=")), |l, _, r, _| {
|
||||
Ast::BinOp(Box::new(l), BinOp::Le, Box::new(r))
|
||||
}),
|
||||
// note that these two are flipped
|
||||
infix(none(10), just(Token::BinOp(">")), |l, _, r, _| {
|
||||
Ast::BinOp(Box::new(r), BinOp::Lt, Box::new(l))
|
||||
}),
|
||||
infix(none(10), just(Token::BinOp(">=")), |l, _, r, _| {
|
||||
Ast::BinOp(Box::new(r), BinOp::Le, Box::new(l))
|
||||
}),
|
||||
infix(right(3), just(Token::BinOp("%")), |l, _, r, _| {
|
||||
Ast::BinOp(Box::new(l), BinOp::Mod, Box::new(r))
|
||||
}),
|
||||
infix(right(3), just(Token::BinOp("**")), |l, _, r, _| {
|
||||
Ast::BinOp(Box::new(l), BinOp::Pow, Box::new(r))
|
||||
}),
|
||||
infix(left(2), just(Token::BinOp("*")), |l, _, r, _| {
|
||||
Ast::BinOp(Box::new(l), BinOp::Mul, Box::new(r))
|
||||
}),
|
||||
infix(right(2), just(Token::BinOp("/")), |l, _, r, _| {
|
||||
Ast::BinOp(Box::new(l), BinOp::Div, Box::new(r))
|
||||
}),
|
||||
infix(left(1), just(Token::BinOp("+")), |l, _, r, _| {
|
||||
Ast::BinOp(Box::new(l), BinOp::Add, Box::new(r))
|
||||
}),
|
||||
infix(left(1), just(Token::BinOp("-")), |l, _, r, _| {
|
||||
Ast::BinOp(Box::new(l), BinOp::Sub, Box::new(r))
|
||||
}),
|
||||
))
|
||||
})
|
||||
.labelled("expression")
|
||||
.separated_by(semicolon)
|
||||
|
|
|
|||
20
src/val.rs
20
src/val.rs
|
|
@ -1,4 +1,4 @@
|
|||
use std::fmt;
|
||||
use std::{fmt, ops};
|
||||
|
||||
use crate::{map::Map, symbol::Symbol};
|
||||
|
||||
|
|
@ -23,3 +23,21 @@ impl fmt::Debug for Val {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Add for Val {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
match (self, rhs) {
|
||||
(Val::Number(a), Val::Number(b)) => Val::Number(a + b),
|
||||
(f @ Val::Function { .. }, g @ Val::Function { .. }) => todo!(),
|
||||
(Val::Map(mut m1), Val::Map(m2)) => {
|
||||
for (k, v) in m2 {
|
||||
m1.insert(k, v);
|
||||
}
|
||||
Val::Map(m1)
|
||||
}
|
||||
(lhs, rhs) => panic!("how do i add these {lhs:?} {rhs:?}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue