This commit is contained in:
LunarAkai 2025-08-05 22:02:39 +02:00
commit d7795e52f9
10 changed files with 276 additions and 31 deletions

View file

@ -1,18 +1,33 @@
use crate::ast::Expression;
impl Expression {
pub fn eval(&self) -> isize {
impl<'src> Expression<'src> {
pub fn eval(&self) -> String {
match self {
Expression::Integer(n) => *n,
Expression::VariableName(_) => todo!(),
Expression::Integer(_) => todo!(),
Expression::Float(_) => todo!(),
Expression::String(_) => todo!(),
Expression::Bool(_) => todo!(),
Expression::Negatation(expression) => todo!(),
Expression::Add(expression, expression1) => todo!(),
Expression::Substract(expression, expression1) => todo!(),
Expression::Multiply(expression, expression1) => todo!(),
Expression::Divide(expression, expression1) => todo!(),
Expression::Var { name, rhs, then } => todo!(),
Expression::Negate(rhs) => -rhs.eval(),
Expression::Add(lhs, rhs) => lhs.eval() + rhs.eval(),
Expression::Substract(lhs, rhs) => lhs.eval() - rhs.eval(),
Expression::Multiply(lhs, rhs) => lhs.eval() * rhs.eval(),
Expression::Divide(lhs, rhs) => lhs.eval() / rhs.eval(),
Expression::Function { name, args, body, then } => todo!(),
}
}
}

View file

@ -1,12 +1,36 @@
pub mod evaluator;
use std::ops::Range;
use crate::ast::op::Op;
pub mod evaluator;
pub mod op;
/// Abstract Syntax Tree
#[derive(Debug)]
pub enum Expression {
Integer(isize),
Negate(Box<Expression>),
// Binary operators,
Add(Box<Expression>, Box<Expression>),
Substract(Box<Expression>, Box<Expression>),
Multiply(Box<Expression>, Box<Expression>),
Divide(Box<Expression>, Box<Expression>),
pub enum Expression<'src> {
VariableName(&'src str),
Integer(i64),
Float(f64),
String(String),
Bool(bool),
Negatation(Box<Expression<'src>>),
Add(Box<Expression<'src>>, Box<Expression<'src>>),
Substract(Box<Expression<'src>>, Box<Expression<'src>>),
Multiply(Box<Expression<'src>>, Box<Expression<'src>>),
Divide(Box<Expression<'src>>, Box<Expression<'src>>),
Var {
name: &'src str,
rhs: Box<Expression<'src>>,
then: Box<Expression<'src>>,
},
Function {
name: &'src str,
args: Vec<&'src str>,
body: Box<Expression<'src>>,
then: Box<Expression<'src>>,
}
}

19
src/ast/op.rs Normal file
View file

@ -0,0 +1,19 @@
#[derive(Debug, Clone)]
pub enum Op {
Add,
Subtract,
Multiply,
Divide,
}
impl Op {
pub fn eval(&self) -> String {
let text: &str = match self {
Op::Add => "+",
Op::Subtract => "-",
Op::Multiply => "*",
Op::Divide => "/",
};
text.to_string()
}
}

View file

@ -0,0 +1,29 @@
use std::collections::HashMap;
use inkwell::{builder::Builder, context::Context, module::Module, values::{FunctionValue, PointerValue}};
use crate::code_generation::Function;
pub struct Compiler<'a, 'ctx> {
pub context: &'ctx Context,
pub builder: &'a Builder<'ctx>,
pub module: &'a Module<'ctx>,
pub function: &'a Function,
variables: HashMap<String, PointerValue<'ctx>>,
fn_value_opt: Option<FunctionValue<'ctx>>
}
impl<'a, 'ctx> Compiler<'a, 'ctx> {
/// Gets a defined function given its name.
#[inline]
fn get_function(&self, name: &str) -> Option<FunctionValue<'ctx>> {
self.module.get_function(name)
}
/// Returns the `FunctionValue` representing the function being compiled.
#[inline]
fn fn_value(&self) -> FunctionValue<'ctx> {
self.fn_value_opt.unwrap()
}
}

View file

@ -0,0 +1,71 @@
pub mod compiler;
// LLVM Codegen
//--------------------------
// Parser
//-------------------------
use std::collections::HashMap;
use logos::Lexer;
use crate::tokens::Token;
/// Defines a primitive expression
#[derive(Debug)]
pub enum Expr {
Binary {
op: char,
left: Box<Expr>,
right: Box<Expr>,
},
Call {
fn_name: String,
args: Vec<Expr>,
},
Conditional {
cond: Box<Expr>,
consequence: Box<Expr>,
alternative: Box<Expr>,
},
For {
var_name: String,
start: Box<Expr>,
end: Box<Expr>,
step: Option<Box<Expr>>,
body: Box<Expr>,
},
Number(f64),
Variable(String),
VarIn {
variables: Vec<(String, Option<Expr>)>,
body: Box<Expr>,
}
}
/// Defines the prototype (name and parameters) of a function
#[derive(Debug)]
pub struct Prototype {
pub name: String,
pub args: Vec<String>,
pub is_op: bool,
pub prec: usize,
}
/// Defines a user-defined or external function
#[derive(Debug)]
pub struct Function {
pub prototype: Prototype,
pub body: Option<Expr>,
pub is_anon: bool,
}
pub struct Parser<'a> {
tokens: Vec<Token<'a>>,
pos: usize,
prec: &'a mut HashMap<char, i32>,
}

View file

@ -6,6 +6,7 @@ use crate::{parser::parser, tokens::Token};
mod tokens;
mod ast;
mod parser;
mod code_generation;
fn main() {
let lexer = Token::lexer("(1 + 1) * 3");

View file

@ -1,18 +1,17 @@
use chumsky::{prelude::{just, recursive}, recursive, select, IterParser, Parser};
use chumsky::{combinator::Or, prelude::{choice, just, recursive}, recursive, select, text::{self, ascii::ident}, IterParser, Parser};
use crate::{ast::Expression, tokens::Token};
#[allow(clippy::let_and_return)]
/* ANCHOR: parser */
pub fn parser<'src>(
) -> impl Parser<'src, &'src [Token<'src>], Expression, chumsky::extra::Err<chumsky::error::Simple<'src, Token<'src>>>>
) -> impl Parser<'src, &'src [Token<'src>], Expression<'src>, chumsky::extra::Err<chumsky::error::Simple<'src, Token<'src>>>>
{
recursive(
|p|
let expr = recursive(
|expr|
{
let atom = {
let parenthesized = p
let parenthesized = expr
.clone()
.delimited_by(just(Token::ParenBegin), just(Token::ParenEnd));
@ -25,7 +24,7 @@ pub fn parser<'src>(
let unary = just(Token::Substract)
.repeated()
.foldr(atom, |_op, rhs| Expression::Negate(Box::new(rhs)));
.foldr(atom, |_op, rhs| Expression::Negatation(Box::new(rhs)));
let binary_1 = unary.clone().foldl(
just(Token::Multiply)
@ -52,5 +51,7 @@ pub fn parser<'src>(
);
binary_2
})
});
expr
}

View file

@ -2,7 +2,7 @@ use logos::{Lexer, Logos};
#[derive(Logos, Debug, Clone, PartialEq)]
#[logos(skip r"[ \t\r\n\f]+")] // Skips whitespace
pub enum Token<'source> {
pub enum Token<'src> {
#[token("false", |_| false)]
#[token("true", |_| true)]
Bool(bool),
@ -37,11 +37,11 @@ pub enum Token<'source> {
#[token("}")]
BraceEnd,
#[regex("[0-9]+", |lex| lex.slice().parse::<isize>().unwrap())]
Integer(isize),
#[regex("[0-9]+", |lex| lex.slice().parse::<i64>().unwrap())]
Integer(i64),
#[regex(r"[_a-zA-Z][_0-9a-zA-Z]*")]
Ident(&'source str),
Ident(&'src str),
#[regex(r#""([^"\\\x00-\x1F]|\\(["\\bnfrt/]|u[a-fA-F0-9]{4}))*""#, |lex| lex.slice().to_owned())]
String(String),
@ -51,7 +51,7 @@ pub enum Token<'source> {
#[token("var")]
#[token("if")]
#[token("else")]
Keyword(&'source str),
Keyword(&'src str),
}