mirror of
https://github.com/PaddiM8/kalker.git
synced 2024-11-07 16:34:21 +01:00
Created the foundation of an expression inverter. This is used to create a second *inverted* unit declaration, in order to cover both of the units.
This commit is contained in:
parent
eb20aae16f
commit
bff785bc1e
@ -1,6 +1,4 @@
|
||||
use crate::lexer::TokenKind;
|
||||
use crate::parser::CalcError;
|
||||
use crate::parser::Unit;
|
||||
|
||||
/// A tree structure of a statement.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
@ -23,20 +21,3 @@ pub enum Expr {
|
||||
FnCall(String, Vec<Expr>),
|
||||
Literal(String),
|
||||
}
|
||||
|
||||
impl TokenKind {
|
||||
pub fn is_unit(&self) -> bool {
|
||||
match self {
|
||||
TokenKind::Deg | TokenKind::Rad => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_unit(&self) -> Result<Unit, CalcError> {
|
||||
match self {
|
||||
TokenKind::Deg => Ok(Unit::Degrees),
|
||||
TokenKind::Rad => Ok(Unit::Radians),
|
||||
_ => Err(CalcError::InvalidUnit),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
52
kalk/src/inverter.rs
Normal file
52
kalk/src/inverter.rs
Normal file
@ -0,0 +1,52 @@
|
||||
use crate::ast::Expr;
|
||||
use crate::lexer::TokenKind;
|
||||
|
||||
impl Expr {
|
||||
pub fn invert(&self) -> Self {
|
||||
match self {
|
||||
Expr::Binary(left, op, right) => invert_binary(&left, op, &right),
|
||||
Expr::Unary(op, expr) => invert_unary(op, &expr),
|
||||
Expr::Unit(identifier, expr) => invert_unit(&identifier, &expr),
|
||||
Expr::Var(identifier) => invert_value(self),
|
||||
Expr::Group(expr) => invert_group(&expr),
|
||||
Expr::FnCall(identifier, expressions) => invert_fn_call(&identifier, expressions),
|
||||
Expr::Literal(value) => invert_value(self),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn invert_binary(left: &Expr, op: &TokenKind, right: &Expr) -> Expr {
|
||||
let op_inv = match op {
|
||||
TokenKind::Plus => TokenKind::Minus,
|
||||
TokenKind::Minus => TokenKind::Plus,
|
||||
TokenKind::Star => TokenKind::Slash,
|
||||
TokenKind::Slash => TokenKind::Star,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
Expr::Binary(Box::new(right.invert()), op_inv, Box::new(left.invert()))
|
||||
}
|
||||
|
||||
fn invert_unary(op: &TokenKind, expr: &Expr) -> Expr {
|
||||
match op {
|
||||
TokenKind::Minus => expr.clone(),
|
||||
TokenKind::Exclamation => unimplemented!(),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn invert_unit(identifier: &str, expr: &Expr) -> Expr {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn invert_group(expr: &Expr) -> Expr {
|
||||
invert_value(expr)
|
||||
}
|
||||
|
||||
fn invert_fn_call(identifier: &str, expressions: &Vec<Expr>) -> Expr {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn invert_value(expr: &Expr) -> Expr {
|
||||
Expr::Unary(TokenKind::Minus, Box::new(expr.clone()))
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
pub mod ast;
|
||||
mod interpreter;
|
||||
mod inverter;
|
||||
mod lexer;
|
||||
pub mod parser;
|
||||
mod prelude;
|
||||
|
@ -19,7 +19,12 @@ pub struct Context {
|
||||
pos: usize,
|
||||
symbol_table: SymbolTable,
|
||||
angle_unit: Unit,
|
||||
/// This is true whenever the parser is currently parsing a unit declaration.
|
||||
/// It is necessary to keep track of this since you cannot use variables in unit declarations.
|
||||
/// Unit names are instead treated as variables.
|
||||
parsing_unit_decl: bool,
|
||||
/// When a unit declaration is being parsed, this value will be set
|
||||
/// whenever a unit in the expression is found. Eg. unit a = 3b, it will be set to Some("b")
|
||||
unit_decl_base_unit: Option<String>,
|
||||
}
|
||||
|
||||
@ -176,9 +181,18 @@ fn parse_unit_decl_stmt(context: &mut Context) -> Result<Stmt, CalcError> {
|
||||
return Err(CalcError::InvalidUnit);
|
||||
};
|
||||
|
||||
// Automatically create a second unit decl with the expression inverted.
|
||||
// This will turn eg. unit a = 3b, into unit b = a/3
|
||||
// This is so that you only have to define `a`, and it will figure out the formula for `b` since it is used in the formula for `a`.
|
||||
let stmt_inv = Stmt::UnitDecl(
|
||||
base_unit.clone(),
|
||||
identifier.value.clone(),
|
||||
Box::new(def.invert()),
|
||||
);
|
||||
let stmt = Stmt::UnitDecl(identifier.value, base_unit, Box::new(def));
|
||||
|
||||
context.symbol_table.insert(stmt.clone());
|
||||
context.symbol_table.insert(stmt_inv);
|
||||
|
||||
Ok(stmt)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user