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),
|
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)
|
// TODO: great display repr for this for testing (yes it's allowed)
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Ast {
|
pub enum Ast {
|
||||||
|
|
@ -26,7 +39,7 @@ pub enum Ast {
|
||||||
/// `f x`
|
/// `f x`
|
||||||
App(Box<Ast>, Box<Ast>),
|
App(Box<Ast>, Box<Ast>),
|
||||||
/// `x + y` (only builtins, sorry)
|
/// `x + y` (only builtins, sorry)
|
||||||
BinOp(Box<Ast>, fn(Val, Val) -> Val, Box<Ast>),
|
BinOp(Box<Ast>, BinOp, Box<Ast>),
|
||||||
/// `3`
|
/// `3`
|
||||||
Num(f64),
|
Num(f64),
|
||||||
/// `(println bla; 3) #=> 3`
|
/// `(println bla; 3) #=> 3`
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,11 @@ use std::{fmt, process};
|
||||||
use ariadne::{Color, Label, Report, ReportKind, Source};
|
use ariadne::{Color, Label, Report, ReportKind, Source};
|
||||||
use chumsky::{
|
use chumsky::{
|
||||||
input::{Stream, ValueInput},
|
input::{Stream, ValueInput},
|
||||||
|
pratt::{infix, left, none, right},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::ast::{Ast, Ident};
|
use crate::ast::{Ast, BinOp, Ident};
|
||||||
|
|
||||||
use logos::Logos;
|
use logos::Logos;
|
||||||
|
|
||||||
|
|
@ -47,7 +48,7 @@ enum Token<'a> {
|
||||||
#[token("fn")]
|
#[token("fn")]
|
||||||
Fn,
|
Fn,
|
||||||
|
|
||||||
#[regex(r"[+*/%=-]")]
|
#[regex(r"([+*/%=<>-]|\*\*|<=|>=)")]
|
||||||
BinOp(&'a str),
|
BinOp(&'a str),
|
||||||
|
|
||||||
#[regex(r"[a-zA-Z_][a-zA-Z_0-9']*")]
|
#[regex(r"[a-zA-Z_][a-zA-Z_0-9']*")]
|
||||||
|
|
@ -210,7 +211,45 @@ where
|
||||||
})
|
})
|
||||||
.labelled("function application");
|
.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")
|
.labelled("expression")
|
||||||
.separated_by(semicolon)
|
.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};
|
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