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
|
## Planned Features
|
||||||
- Object-Oriented
|
- Object-Oriented
|
||||||
- dynamic typing
|
- dynamic typing / Type inference
|
||||||
- LLVM Backend
|
- LLVM Backend
|
||||||
|
|
||||||
## Hello World
|
## Hello World
|
||||||
|
|
@ -14,4 +14,7 @@ Akai Lang (yeah I'm not creative and the name is still unused on github, sooo) i
|
||||||
fun helloWorld() {
|
fun helloWorld() {
|
||||||
print("Hello World!")
|
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!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
pub mod ast;
|
pub mod ast;
|
||||||
pub mod op;
|
pub mod op;
|
||||||
|
|
@ -9,11 +9,11 @@ pub enum Op {
|
||||||
impl Op {
|
impl Op {
|
||||||
pub fn eval(&self) -> String {
|
pub fn eval(&self) -> String {
|
||||||
let text: &str = match self {
|
let text: &str = match self {
|
||||||
Op::Add => "+",
|
Op::Add => "+",
|
||||||
Op::Subtract => "-",
|
Op::Subtract => "-",
|
||||||
Op::Multiply => "*",
|
Op::Multiply => "*",
|
||||||
Op::Divide => "/",
|
Op::Divide => "/",
|
||||||
};
|
};
|
||||||
text.to_string()
|
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;
|
||||||
|
|
@ -39,7 +39,7 @@ pub enum Token<'src> {
|
||||||
|
|
||||||
#[regex("[0-9]+", |lex| lex.slice().parse::<i64>().unwrap())]
|
#[regex("[0-9]+", |lex| lex.slice().parse::<i64>().unwrap())]
|
||||||
Integer(i64),
|
Integer(i64),
|
||||||
|
|
||||||
#[regex(r"[_a-zA-Z][_0-9a-zA-Z]*")]
|
#[regex(r"[_a-zA-Z][_0-9a-zA-Z]*")]
|
||||||
Ident(&'src str),
|
Ident(&'src str),
|
||||||
|
|
||||||
|
|
@ -53,5 +53,3 @@ pub enum Token<'src> {
|
||||||
#[token("else")]
|
#[token("else")]
|
||||||
Keyword(&'src str),
|
Keyword(&'src str),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
pub mod ast;
|
pub mod abstract_syntax_tree;
|
||||||
|
pub mod lexer;
|
||||||
pub mod parser;
|
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)]
|
#[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>> {
|
||||||
|
|
@ -9,16 +16,16 @@ pub fn parser<'src>() -> impl Parser<'src, &'src [Token<'src>], Expression<'src>
|
||||||
Token::Ident(ident) => ident
|
Token::Ident(ident) => ident
|
||||||
};
|
};
|
||||||
|
|
||||||
let keyword = |kw: &'static str| select! {
|
let keyword = |kw: &'static str| {
|
||||||
Token::Keyword(k) if k == kw => ()
|
select! {
|
||||||
|
Token::Keyword(k) if k == kw => ()
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let eq = just(Token::Equals);
|
let eq = just(Token::Equals);
|
||||||
|
|
||||||
let expr = recursive(
|
let expr = recursive(|expr| {
|
||||||
|expr|
|
let atom = {
|
||||||
{
|
|
||||||
let atom = {
|
|
||||||
let parenthesized = expr
|
let parenthesized = expr
|
||||||
.clone()
|
.clone()
|
||||||
.delimited_by(just(Token::ParenBegin), just(Token::ParenEnd));
|
.delimited_by(just(Token::ParenBegin), just(Token::ParenEnd));
|
||||||
|
|
@ -63,7 +70,7 @@ 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.clone())
|
||||||
.then_ignore(eq.clone())
|
.then_ignore(eq.clone())
|
||||||
.then(decl.clone())
|
.then(decl.clone())
|
||||||
.then(decl.clone())
|
.then(decl.clone())
|
||||||
|
|
@ -84,10 +91,10 @@ pub fn parser<'src>() -> impl Parser<'src, &'src [Token<'src>], Expression<'src>
|
||||||
args,
|
args,
|
||||||
body: Box::new(body),
|
body: Box::new(body),
|
||||||
then: Box::new(then),
|
then: Box::new(then),
|
||||||
});
|
});
|
||||||
|
|
||||||
var.or(r#fun).or(expr)
|
var.or(r#fun).or(expr)
|
||||||
});
|
});
|
||||||
|
|
||||||
decl
|
decl
|
||||||
}
|
}
|
||||||
|
|
|
||||||
39
src/main.rs
39
src/main.rs
|
|
@ -1,12 +1,23 @@
|
||||||
use chumsky::Parser;
|
use chumsky::Parser;
|
||||||
use logos::Logos;
|
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;
|
mod language_frontend;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Simple Compiler -> 4 Stages:
|
||||||
|
- lex
|
||||||
|
- parse
|
||||||
|
- type-check
|
||||||
|
- translate to machine instructions
|
||||||
|
*/
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let lexer = Token::lexer("(1 + 1) * 3");
|
let lexer = Token::lexer("1 + 1 * 3");
|
||||||
|
|
||||||
let mut tokens = vec![];
|
let mut tokens = vec![];
|
||||||
for (token, span) in lexer.spanned() {
|
for (token, span) in lexer.spanned() {
|
||||||
|
|
@ -19,16 +30,28 @@ fn main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let ast = match parser().parse(&tokens).into_result() {
|
/*
|
||||||
Ok(expr) => {
|
match parser().parse(&tokens).into_result() {
|
||||||
println!("[AST]\n{:#?}", expr);
|
Ok(expr) => match eval(&ast, &mut Vec::new(), &mut Vec::new()) {
|
||||||
expr
|
Ok(output) => println!("{output}"),
|
||||||
|
Err(eval_err) => println!("Evaluation error: {eval_err}"),
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("parse error: {:#?}", e);
|
println!("parse error: {:#?}", e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
}; */
|
||||||
|
|
||||||
println!("\n[result]\n{}", ast.evaluate());
|
|
||||||
|
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{}", abstract_syntax_tree::ast::eval(absyntr, vars, funcs));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ class Cat derive Animal:
|
||||||
|
|
||||||
fun helloWorld() {
|
fun helloWorld() {
|
||||||
// Variables either dynamically or statically typed
|
// Variables either dynamically or statically typed
|
||||||
|
// -> Type inference
|
||||||
var String: test = "I'm a string"
|
var String: test = "I'm a string"
|
||||||
var foo = 12 // reads as int
|
var foo = 12 // reads as int
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue