hey it can calculate 4 again xP

This commit is contained in:
LunarAkai 2025-08-07 01:37:01 +02:00
commit 8a44d045ae
7 changed files with 50 additions and 36 deletions

3
.gitignore vendored
View file

@ -1,2 +1,3 @@
/target /target
*.sh *.sh
sample.akai

View file

@ -2,19 +2,23 @@
#[derive(Debug)] #[derive(Debug)]
pub enum Expression<'src> { pub enum Expression<'src> {
// Identifier
Ident(&'src str), Ident(&'src str),
// Types
Integer(i64), Integer(i64),
Float(f64), Float(f64),
String(String), String(String),
Bool(bool), Bool(bool),
// Operations
Negatation(Box<Expression<'src>>), Negatation(Box<Expression<'src>>),
Add(Box<Expression<'src>>, Box<Expression<'src>>), Add(Box<Expression<'src>>, Box<Expression<'src>>),
Substract(Box<Expression<'src>>, Box<Expression<'src>>), Substract(Box<Expression<'src>>, Box<Expression<'src>>),
Multiply(Box<Expression<'src>>, Box<Expression<'src>>), Multiply(Box<Expression<'src>>, Box<Expression<'src>>),
Divide(Box<Expression<'src>>, Box<Expression<'src>>), Divide(Box<Expression<'src>>, Box<Expression<'src>>),
// Keywords
Var { Var {
name: &'src str, name: &'src str,
rhs: Box<Expression<'src>>, rhs: Box<Expression<'src>>,
@ -37,16 +41,24 @@ pub fn eval<'src>(
funcs: &mut Vec<(&'src str, &'src [&'src str], &'src Expression<'src>)>, funcs: &mut Vec<(&'src str, &'src [&'src str], &'src Expression<'src>)>,
) -> Result<f64, String> { ) -> Result<f64, String> {
match expr { match expr {
Expression::Ident(_) => todo!(), Expression::Ident(name) => {
if let Some((_, val)) = vars.iter().rev().find(|(var, _)| var == name) {
Ok(*val)
} else {
Err(format!("Cannot find variable `{name}` in scope"))
}
},
Expression::Integer(x) => Ok((*x) as f64), // Types
Expression::Integer(x) => Ok((*x) as f64), // todo
Expression::Float(_) => todo!(), Expression::Float(x) => Ok(*x),
Expression::String(_) => todo!(), Expression::String(_) => todo!(),
Expression::Bool(_) => todo!(), Expression::Bool(_) => todo!(),
// Operations
Expression::Negatation(lhs) => todo!(), Expression::Negatation(lhs) => todo!(),
Expression::Add(lhs, rhs) => Ok(eval(lhs, vars, funcs)? + eval(rhs, vars, funcs)?), Expression::Add(lhs, rhs) => Ok(eval(lhs, vars, funcs)? + eval(rhs, vars, funcs)?),
@ -57,14 +69,26 @@ pub fn eval<'src>(
Expression::Divide(lhs, rhs) => Ok(eval(lhs, vars, funcs)? / eval(rhs, vars, funcs)?), Expression::Divide(lhs, rhs) => Ok(eval(lhs, vars, funcs)? / eval(rhs, vars, funcs)?),
Expression::Var { name, rhs, then } => todo!(), // Keywords
Expression::Var { name, rhs, then } => {
let rhs = eval(rhs, vars, funcs)?;
vars.push((*name, rhs));
let output = eval(then, vars, funcs);
vars.pop();
output
},
Expression::Function { Expression::Function {
name, name,
args, args,
body, body,
then, then,
} => todo!(), } => {
funcs.push((name, args, body));
let output = eval(then, vars, funcs);
funcs.pop();
output
},
Expression::Unit => todo!(), Expression::Unit => todo!(),
} }

View file

@ -1,2 +1,3 @@
pub mod ast; pub mod ast;
pub mod op; pub mod op;
pub mod parser;

View file

@ -1,9 +1,5 @@
use chumsky::{ use chumsky::{
IterParser, Parser, combinator::Or, prelude::{choice, just, recursive}, recursive, select, select_ref, text::{self, ascii::ident, whitespace}, IterParser, Parser
combinator::Or,
prelude::{choice, just, recursive},
recursive, select,
text::{self, ascii::ident},
}; };
use crate::{language_frontend::abstract_syntax_tree::ast::Expression, language_frontend::lexer::tokens::Token}; use crate::{language_frontend::abstract_syntax_tree::ast::Expression, language_frontend::lexer::tokens::Token};
@ -12,8 +8,8 @@ use crate::{language_frontend::abstract_syntax_tree::ast::Expression, language_f
#[allow(clippy::let_and_return)] #[allow(clippy::let_and_return)]
pub fn parser<'src>() -> impl Parser<'src, &'src [Token<'src>], Expression<'src>> { pub fn parser<'src>() -> impl Parser<'src, &'src [Token<'src>], Expression<'src>> {
let ident = select! { let ident = select_ref! {
Token::Ident(ident) => ident Token::Ident(ident) => *ident
}; };
let keyword = |kw: &'static str| { let keyword = |kw: &'static str| {
@ -41,6 +37,8 @@ pub fn parser<'src>() -> impl Parser<'src, &'src [Token<'src>], Expression<'src>
.repeated() .repeated()
.foldr(atom, |_op, rhs| Expression::Negatation(Box::new(rhs))); .foldr(atom, |_op, rhs| Expression::Negatation(Box::new(rhs)));
// "Punktrechnung vor Strichrechnung :nerd:"
let binary_1 = unary.clone().foldl( let binary_1 = unary.clone().foldl(
just(Token::Multiply) just(Token::Multiply)
.or(just(Token::Divide)) .or(just(Token::Divide))
@ -70,9 +68,9 @@ pub fn parser<'src>() -> impl Parser<'src, &'src [Token<'src>], Expression<'src>
let decl = recursive(|decl| { let decl = recursive(|decl| {
let r#var = keyword("var") let r#var = keyword("var")
.ignore_then(ident.clone()) .ignore_then(ident)
.then_ignore(eq.clone()) .then_ignore(eq.clone())
.then(decl.clone()) .then(expr.clone())
.then(decl.clone()) .then(decl.clone())
.map(|((name, rhs), then)| Expression::Var { .map(|((name, rhs), then)| Expression::Var {
name, name,
@ -82,10 +80,10 @@ pub fn parser<'src>() -> impl Parser<'src, &'src [Token<'src>], Expression<'src>
let r#fun = keyword("fun") let r#fun = keyword("fun")
.ignore_then(ident.clone()) .ignore_then(ident.clone())
.then(ident.clone().repeated().collect()) .then(ident.repeated().collect::<Vec<_>>())
.then_ignore(eq.clone()) .then_ignore(eq.clone())
.then(decl.clone()) .then(expr.clone())
.then(decl.clone()) .then(decl)
.map(|(((name, args), body), then)| Expression::Function { .map(|(((name, args), body), then)| Expression::Function {
name, name,
args, args,

View file

@ -37,9 +37,12 @@ pub enum Token<'src> {
#[token("}")] #[token("}")]
BraceEnd, BraceEnd,
#[regex("[0-9]+", |lex| lex.slice().parse::<i64>().unwrap())] #[regex(r"[+-]?[0-9]+", |lex| lex.slice().parse::<i64>().unwrap(), priority = 3)]
Integer(i64), Integer(i64),
#[regex(r"[+-]?([0-9]*[.])?[0-9]+", |lex| lex.slice().parse::<f64>().unwrap())]
Float(f64),
#[regex(r"[_a-zA-Z][_0-9a-zA-Z]*")] #[regex(r"[_a-zA-Z][_0-9a-zA-Z]*")]
Ident(&'src str), Ident(&'src str),

View file

@ -1,3 +1,2 @@
pub mod abstract_syntax_tree; pub mod abstract_syntax_tree;
pub mod lexer; pub mod lexer;
pub mod parser;

View file

@ -1,11 +1,11 @@
use chumsky::Parser; use chumsky::Parser;
use logos::Logos; use logos::Logos;
use crate::language_frontend::abstract_syntax_tree;
use crate::{ use crate::{
language_frontend::lexer::tokens::Token, language_frontend::parser::parser}; language_frontend::lexer::tokens::Token, language_frontend::abstract_syntax_tree::parser::parser};
use crate::language_frontend::abstract_syntax_tree::ast::{eval, Expression}; use crate::language_frontend::abstract_syntax_tree::ast::{eval, Expression};
mod language_frontend; mod language_frontend;
/* /*
@ -17,7 +17,8 @@ Simple Compiler -> 4 Stages:
*/ */
fn main() { fn main() {
let lexer = Token::lexer("1 + 1 * 3"); let sourcecode = std::fs::read_to_string("sample.akai").unwrap();
let lexer = Token::lexer(&sourcecode);
let mut tokens = vec![]; let mut tokens = vec![];
for (token, span) in lexer.spanned() { for (token, span) in lexer.spanned() {
@ -30,19 +31,6 @@ fn main() {
} }
} }
/*
match parser().parse(&tokens).into_result() {
Ok(expr) => match eval(&ast, &mut Vec::new(), &mut Vec::new()) {
Ok(output) => println!("{output}"),
Err(eval_err) => println!("Evaluation error: {eval_err}"),
}
Err(e) => {
println!("parse error: {:#?}", e);
return;
}
}; */
match parser().parse(&tokens).into_result() { match parser().parse(&tokens).into_result() {
Ok(ast) => match eval(&ast, &mut Vec::new(), &mut Vec::new()) { Ok(ast) => match eval(&ast, &mut Vec::new(), &mut Vec::new()) {
Ok(output) => println!("{output}"), Ok(output) => println!("{output}"),