Did some things to make it more recursive, but still doesn't compile

recursive
Goren Barak 2023-11-28 14:59:08 -05:00
parent 4d4ab24382
commit 0b4e7deda0
7 changed files with 147 additions and 19 deletions

6
justfile Normal file
View File

@ -0,0 +1,6 @@
run:
cargo run -r
test:
cargo test
build:
cargo build -r

66
src/#main.rs# Normal file
View File

@ -0,0 +1,66 @@
#![allow(warnings)]
pub mod lex;
pub mod codegen;
use crate::codegen::fasm::*;
use crate::lex::tok::*;
use crate::parse::ast::*;
use crate::parse::parse::*;
use logos::Logos;
pub mod parse;
macro_rules! arrow {
($spaces:expr) => {
println!("{}↓", $spaces);
}
}
fn main() {
// let fc = fasm_codegen!(
// vec![
// Expr::VarDefinition(VarDefinition {name: "goren", value: Value::Number(10)}),
// Expr::MathExpr(Math {
// left: &Value::Var(VarReference { name: "goren"}),
// right: &Value::Number(17),
// operator: MathOperator::OP_MULT
// }
// ),
// Expr::FunDefinition(FunDefinition {
// name: "adder", contents: vec![
// Expr::MathExpr(
// Math {
// left: &Value::Param(ParamReference {param_number: 0}),
// right: &Value::Param(ParamReference {param_number: 1}),
// operator: MathOperator::OP_ADD
// }
// )
// ]
// }),
// Expr::FunCall(
// FunCall {
// name: "adder",
// params: vec![Value::Var(VarReference {name: "goren"}), Value::Number(6)]
// }
// ),
// Expr::Breakpoint
// ]
// );
// println!("{}", fc);
let parsed = "30 * 60";
let mut lexer = Token::lexer(parsed);
println!("\"{}\"", parsed);
arrow!(" ");
println!("{:?}", lex_str(parsed));
arrow!(" ");
let parsed = parse_math(lexer);
println!("{:?}", parsed);
arrow!(" ");
println!("{}", fasm_codegen!(&vec![parsed.unwrap()]));
}

View File

@ -4,7 +4,7 @@ use crate::parse::ast::*;
macro_rules! fasm_codegen { macro_rules! fasm_codegen {
// Macro to make calling fasm_codegen function easier. // Macro to make calling fasm_codegen function easier.
($exprs:expr) => { ($exprs:expr) => {
fasm_codegen(&$exprs, true) fasm_codegen($exprs, true)
}; };
(fun: $exprs:expr) => { (fun: $exprs:expr) => {

View File

@ -85,7 +85,7 @@ pub enum Token {
String, // A string literal. String, // A string literal.
#[regex("[0-9]+", |lex| lex.slice().parse().ok())] #[regex("[0-9]+", |lex| lex.slice().parse().ok())]
Number(u64), // An integer. Number(u64), // An integer.
#[regex(r#"[^[0-9]^"^-^[ \t\n\f]^\.^=^(^)^{^}.^,^;]+[^"^-^=^\..^[ \t\n\f]^(^)^{^}^,^;]*"#)] #[regex(r#"[^[0-9]^"^-^[ \t\n\f]^\.^=^(^)^{^}.^,^;^[+-/*%]]+[^"^-^=^\..^[ \t\n\f]^(^)^{^}^,^;^[+-/*%]]*"#)]
Identifier, // An identifier. Identifier, // An identifier.
#[token("true")] #[token("true")]
True, // true True, // true
@ -96,7 +96,6 @@ pub enum Token {
} }
pub fn lex_str(this: &str) -> Vec<(Token, &str)> { pub fn lex_str(this: &str) -> Vec<(Token, &str)> {
println!("\"{}\"", this);
let mut buf = Vec::new(); let mut buf = Vec::new();
let mut lexer = Token::lexer(this); let mut lexer = Token::lexer(this);
while let Some(Ok(token)) = lexer.next() { while let Some(Ok(token)) = lexer.next() {

View File

@ -10,6 +10,12 @@ use logos::Logos;
pub mod parse; pub mod parse;
macro_rules! arrow {
($spaces:expr) => {
println!("{}", $spaces);
}
}
fn main() { fn main() {
// let fc = fasm_codegen!( // let fc = fasm_codegen!(
// vec![ // vec![
@ -45,9 +51,17 @@ fn main() {
// println!("{}", fc); // println!("{}", fc);
let parsed = "hello(hi)"; let parsed = "30 * 60";
let mut lexer = Token::lexer(parsed); let mut lexer = Token::lexer(parsed);
println!("\"{}\"", parsed);
arrow!(" ");
println!("{:?}", lex_str(parsed)); println!("{:?}", lex_str(parsed));
println!("{:?}", parse_fun_call(lexer)); arrow!(" ");
let parsed = parse_math(lexer);
println!("{:?}", parsed);
arrow!(" ");
println!("{}", fasm_codegen!(&vec![parsed.unwrap()]));
} }

View File

@ -8,15 +8,16 @@ pub enum Expr<'a> {
VarDefinition(VarDefinition<'a>), VarDefinition(VarDefinition<'a>),
Return(Vec<Expr<'a>>), Return(Vec<Expr<'a>>),
If(IfCondition<'a>), If(IfCondition<'a>),
Breakpoint Breakpoint
} }
// MATH EXPRESSION // MATH EXPRESSION
#[derive(Debug, Copy, Clone)] #[derive(Debug, Clone)]
pub struct Math<'a> { pub struct Math<'a> {
pub left: &'a Value<'a>, pub left: Rc<Value<'a>>,
pub right: &'a Value<'a>, pub right: Rc<Value<'a>>,
pub operator: MathOperator pub operator: MathOperator
} }
@ -73,12 +74,7 @@ pub struct ParamReference {
pub param_number: u64, pub param_number: u64,
} }
#[derive(Debug, Copy, Clone)] // CONDITIONS
pub enum Value<'a> {
Var(VarReference<'a>),
Param(ParamReference),
Number(u64),
}
#[derive(Debug)] #[derive(Debug)]
pub struct IfCondition<'a> { pub struct IfCondition<'a> {
@ -94,6 +90,16 @@ pub enum COND_OP {
NE, NE,
} }
// VALUE
#[derive(Debug, Copy, Clone)]
pub enum Value<'a> {
Var(VarReference<'a>),
Param(ParamReference),
Number(u64),
}
impl<'a> Value<'a> { impl<'a> Value<'a> {
pub fn unwrap(&self) -> String { pub fn unwrap(&self) -> String {
match self { match self {

View File

@ -1,13 +1,39 @@
use super::ast::*; use super::ast::*;
use crate::lex::tok::*; use crate::lex::tok::*;
use logos::Lexer; use logos::Lexer;
use std::rc::Rc;
#[macro_export]
macro_rules! unwrap { macro_rules! unwrap {
($var:expr) => { ($var:expr) => {
$var.next().unwrap().unwrap() $var.next().unwrap().unwrap()
} }
} }
#[macro_export]
macro_rules! parse_value {
($parse:expr) => {
parse_value(&($parse.next(), $parse.slice()))
}
}
pub fn parse_math(mut tokens: Lexer<Token>) -> Option<Expr> {
// Is it a Value? → Is it an operator? → Is it a value?
if let Some(left) = parse_value!(tokens) {
if let Some(operator) = match_operator(&mut tokens) {
if let Some(right) = parse_value!(tokens) {
let left = Rc::new(left);
let right = Rc::new(right);
return Some(Expr::MathExpr(Math {left: left, right: right, operator}))
}
}
}
None
}
pub fn parse_var_declaration(mut tokens: Lexer<Token>) -> Option<Expr> { pub fn parse_var_declaration(mut tokens: Lexer<Token>) -> Option<Expr> {
let mut tok = None; let mut tok = None;
if unwrap!(tokens) == Let { if unwrap!(tokens) == Let {
@ -31,13 +57,13 @@ pub fn parse_var_declaration(mut tokens: Lexer<Token>) -> Option<Expr> {
tok tok
} }
pub fn parse_value<'a>(token: (Option<Result<Token, ()>>, &'a str)) -> Option<Value<'a>> { pub fn parse_value<'a>(token: &(Option<Result<Token, ()>>, &'a str)) -> Option<Value<'a>> {
if let Some(Ok(tt)) = token.0 { if let Some(Ok(tt)) = &token.0 {
let mut value = None; let mut value = None;
if let Number(n) = tt { if let Number(n) = tt {
value = Some(Value::Number(n)); value = Some(Value::Number(*n));
} else if tt == Identifier { } else if *tt == Identifier {
value = Some(Value::Var(VarReference { name: token.1 })); value = Some(Value::Var(VarReference { name: token.1 }));
} }
@ -58,7 +84,7 @@ pub fn parse_fun_call(mut tokens: Lexer<Token>) -> Option<Expr> {
let name = tokens.slice(); let name = tokens.slice();
if unwrap!(tokens) == LeftParen { if unwrap!(tokens) == LeftParen {
let mut params = Vec::new(); let mut params = Vec::new();
while let Some(value) = parse_value((tokens.next(), tokens.slice())) { while let Some(value) = parse_value!(tokens) {
params.push(value); params.push(value);
} }
tok = Some(Expr::FunCall(FunCall {name, params: params.clone()})); tok = Some(Expr::FunCall(FunCall {name, params: params.clone()}));
@ -67,3 +93,14 @@ pub fn parse_fun_call(mut tokens: Lexer<Token>) -> Option<Expr> {
tok tok
} }
pub fn match_operator(tokens: &mut Lexer<Token>) -> Option<MathOperator> {
match unwrap!(tokens) {
Plus => Some(MathOperator::OP_ADD),
Minus => Some(MathOperator::OP_SUB),
Slash => Some(MathOperator::OP_DIV),
Star => Some(MathOperator::OP_MULT),
Percent => Some(MathOperator::OP_MOD),
_ => None
}
}