hey it can calculate 4 again xP
This commit is contained in:
parent
e769b891ab
commit
d253497b3e
11 changed files with 137 additions and 95 deletions
|
|
@ -6,7 +6,7 @@ Akai Lang (yeah I'm not creative and the name is still unused on github, sooo) i
|
|||
|
||||
## Planned Features
|
||||
- Object-Oriented
|
||||
- dynamic typing
|
||||
- dynamic typing / Type inference
|
||||
- LLVM Backend
|
||||
|
||||
## Hello World
|
||||
|
|
@ -15,3 +15,6 @@ fun helloWorld() {
|
|||
print("Hello World!")
|
||||
}
|
||||
```
|
||||
|
||||
## Shoutout to these amazing ressources that help(ed) me understand language design:
|
||||
- [https://mukulrathi.com/create-your-own-programming-language/intro-to-compiler/](https://mukulrathi.com/create-your-own-programming-language/intro-to-compiler/)
|
||||
71
src/language_frontend/abstract_syntax_tree/ast.rs
Normal file
71
src/language_frontend/abstract_syntax_tree/ast.rs
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/// Abstract Syntax Tree
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Expression<'src> {
|
||||
Ident(&'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>>,
|
||||
},
|
||||
|
||||
Unit,
|
||||
}
|
||||
|
||||
pub fn eval<'src>(
|
||||
expr: &'src Expression<'src>,
|
||||
vars: &mut Vec<(&'src str, f64)>,
|
||||
funcs: &mut Vec<(&'src str, &'src [&'src str], &'src Expression<'src>)>,
|
||||
) -> Result<f64, String> {
|
||||
match expr {
|
||||
Expression::Ident(_) => todo!(),
|
||||
|
||||
Expression::Integer(x) => Ok((*x) as f64),
|
||||
|
||||
Expression::Float(_) => todo!(),
|
||||
|
||||
Expression::String(_) => todo!(),
|
||||
|
||||
Expression::Bool(_) => todo!(),
|
||||
|
||||
Expression::Negatation(lhs) => todo!(),
|
||||
|
||||
Expression::Add(lhs, rhs) => Ok(eval(lhs, vars, funcs)? + eval(rhs, vars, funcs)?),
|
||||
|
||||
Expression::Substract(lhs, rhs) => Ok(eval(lhs, vars, funcs)? - eval(rhs, vars, funcs)?),
|
||||
|
||||
Expression::Multiply(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!(),
|
||||
|
||||
Expression::Function {
|
||||
name,
|
||||
args,
|
||||
body,
|
||||
then,
|
||||
} => todo!(),
|
||||
|
||||
Expression::Unit => todo!(),
|
||||
}
|
||||
}
|
||||
|
|
@ -9,10 +9,10 @@ pub enum Op {
|
|||
impl Op {
|
||||
pub fn eval(&self) -> String {
|
||||
let text: &str = match self {
|
||||
Op::Add => "+",
|
||||
Op::Subtract => "-",
|
||||
Op::Multiply => "*",
|
||||
Op::Divide => "/",
|
||||
Op::Add => "+",
|
||||
Op::Subtract => "-",
|
||||
Op::Multiply => "*",
|
||||
Op::Divide => "/",
|
||||
};
|
||||
text.to_string()
|
||||
}
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
/// Abstract Syntax Tree
|
||||
#[derive(Debug)]
|
||||
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>>,
|
||||
},
|
||||
|
||||
Unit
|
||||
}
|
||||
|
||||
impl<'src> Expression<'src> {
|
||||
pub fn evaluate(&self) -> String {
|
||||
match self {
|
||||
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::Function { name, args, body, then } => todo!(),
|
||||
|
||||
Expression::Unit => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
1
src/language_frontend/lexer/mod.rs
Normal file
1
src/language_frontend/lexer/mod.rs
Normal file
|
|
@ -0,0 +1 @@
|
|||
pub mod tokens;
|
||||
|
|
@ -53,5 +53,3 @@ pub enum Token<'src> {
|
|||
#[token("else")]
|
||||
Keyword(&'src str),
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
pub mod ast;
|
||||
pub mod abstract_syntax_tree;
|
||||
pub mod lexer;
|
||||
pub mod parser;
|
||||
pub mod tokens;
|
||||
|
|
@ -1,7 +1,14 @@
|
|||
use chumsky::{combinator::Or, prelude::{choice, just, recursive}, recursive, select, text::{self, ascii::ident}, IterParser, Parser};
|
||||
use chumsky::{
|
||||
IterParser, Parser,
|
||||
combinator::Or,
|
||||
prelude::{choice, just, recursive},
|
||||
recursive, select,
|
||||
text::{self, ascii::ident},
|
||||
};
|
||||
|
||||
use crate::{language_frontend::ast::ast::Expression, language_frontend::tokens::Token};
|
||||
use crate::{language_frontend::abstract_syntax_tree::ast::Expression, language_frontend::lexer::tokens::Token};
|
||||
|
||||
// goal of parsing is to construct an abstract syntax tree
|
||||
|
||||
#[allow(clippy::let_and_return)]
|
||||
pub fn parser<'src>() -> impl Parser<'src, &'src [Token<'src>], Expression<'src>> {
|
||||
|
|
@ -9,16 +16,16 @@ pub fn parser<'src>() -> impl Parser<'src, &'src [Token<'src>], Expression<'src>
|
|||
Token::Ident(ident) => ident
|
||||
};
|
||||
|
||||
let keyword = |kw: &'static str| select! {
|
||||
Token::Keyword(k) if k == kw => ()
|
||||
let keyword = |kw: &'static str| {
|
||||
select! {
|
||||
Token::Keyword(k) if k == kw => ()
|
||||
}
|
||||
};
|
||||
|
||||
let eq = just(Token::Equals);
|
||||
|
||||
let expr = recursive(
|
||||
|expr|
|
||||
{
|
||||
let atom = {
|
||||
let expr = recursive(|expr| {
|
||||
let atom = {
|
||||
let parenthesized = expr
|
||||
.clone()
|
||||
.delimited_by(just(Token::ParenBegin), just(Token::ParenEnd));
|
||||
|
|
@ -84,7 +91,7 @@ pub fn parser<'src>() -> impl Parser<'src, &'src [Token<'src>], Expression<'src>
|
|||
args,
|
||||
body: Box::new(body),
|
||||
then: Box::new(then),
|
||||
});
|
||||
});
|
||||
|
||||
var.or(r#fun).or(expr)
|
||||
});
|
||||
|
|
|
|||
37
src/main.rs
37
src/main.rs
|
|
@ -1,12 +1,23 @@
|
|||
use chumsky::Parser;
|
||||
use logos::Logos;
|
||||
|
||||
use crate::{language_frontend::parser::parser, language_frontend::tokens::Token};
|
||||
use crate::language_frontend::abstract_syntax_tree;
|
||||
use crate::{
|
||||
language_frontend::lexer::tokens::Token, language_frontend::parser::parser};
|
||||
|
||||
use crate::language_frontend::abstract_syntax_tree::ast::{eval, Expression};
|
||||
mod language_frontend;
|
||||
|
||||
/*
|
||||
Simple Compiler -> 4 Stages:
|
||||
- lex
|
||||
- parse
|
||||
- type-check
|
||||
- translate to machine instructions
|
||||
*/
|
||||
|
||||
fn main() {
|
||||
let lexer = Token::lexer("(1 + 1) * 3");
|
||||
let lexer = Token::lexer("1 + 1 * 3");
|
||||
|
||||
let mut tokens = vec![];
|
||||
for (token, span) in lexer.spanned() {
|
||||
|
|
@ -19,16 +30,28 @@ fn main() {
|
|||
}
|
||||
}
|
||||
|
||||
let ast = match parser().parse(&tokens).into_result() {
|
||||
Ok(expr) => {
|
||||
println!("[AST]\n{:#?}", expr);
|
||||
expr
|
||||
/*
|
||||
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() {
|
||||
Ok(ast) => match eval(&ast, &mut Vec::new(), &mut Vec::new()) {
|
||||
Ok(output) => println!("{output}"),
|
||||
Err(eval_err) => println!("Evaluation error: {eval_err}"),
|
||||
},
|
||||
Err(parse_errs) => parse_errs
|
||||
.into_iter()
|
||||
.for_each(|err| println!("Parse error: {err}")),
|
||||
};
|
||||
|
||||
println!("\n[result]\n{}", ast.evaluate());
|
||||
//println!("\n[result]\n{}", abstract_syntax_tree::ast::eval(absyntr, vars, funcs));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ class Cat derive Animal:
|
|||
|
||||
fun helloWorld() {
|
||||
// Variables either dynamically or statically typed
|
||||
// -> Type inference
|
||||
var String: test = "I'm a string"
|
||||
var foo = 12 // reads as int
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue