diff --git a/justfile b/justfile index a3bb6d6..5c1516e 100644 --- a/justfile +++ b/justfile @@ -2,4 +2,10 @@ run: cargo run test: - cargo test --verbose \ No newline at end of file + cargo test --verbose + +doc: + cargo doc --no-deps + +fmt: + cargo fmt \ No newline at end of file diff --git a/src/language_frontend/abstract_syntax_tree/ast.rs b/src/language_frontend/abstract_syntax_tree/ast.rs index 1b3f312..0ec3e5a 100644 --- a/src/language_frontend/abstract_syntax_tree/ast.rs +++ b/src/language_frontend/abstract_syntax_tree/ast.rs @@ -28,4 +28,4 @@ pub enum Expr { FunctionExpr(Function), Error, -} \ No newline at end of file +} diff --git a/src/language_frontend/abstract_syntax_tree/definitions.rs b/src/language_frontend/abstract_syntax_tree/definitions.rs index 4794dd4..3178139 100644 --- a/src/language_frontend/abstract_syntax_tree/definitions.rs +++ b/src/language_frontend/abstract_syntax_tree/definitions.rs @@ -7,10 +7,9 @@ pub type BlockStatement = Vec; pub type Span = Range; - #[derive(Clone, Debug, PartialEq)] pub enum Statement { - Var(Ident, Option) + Var(Ident, Option), } #[derive(Clone, Debug, PartialEq)] @@ -79,7 +78,6 @@ impl Value { } } - //--------------------------------------- // Structs //--------------------------------------- @@ -99,8 +97,7 @@ pub struct Condition { pub else_body: Option, } - -/// Example: `x = 5` +/// Example: `x = 5` #[derive(Clone, Debug, PartialEq)] pub struct Assignment { pub target: Box, @@ -112,7 +109,7 @@ pub struct Assignment { pub struct Var { pub ty: Option, pub ident: String, - pub value: Box + pub value: Box, } /// Example: `x++` @@ -131,30 +128,29 @@ pub struct Binary { } /// Represents the Structure of a `Function` in AkaiLang -/// +/// /// Examples: ///```AkaiLang ///fun helloWorld() { /// print("Hello World") ///} -///``` +///``` ///
-/// +/// ///```AkaiLang ///fun returnsIntPlusOne(i: int): int { /// -> i + 1 ///} -///``` +///``` #[derive(Clone, Debug, PartialEq)] pub struct Function { pub name: Rc, pub params: Vec<(Ident, Type)>, pub return_type: Option, pub body: Vec, - pub body_expr: Option + pub body_expr: Option, } - #[derive(Clone, Debug, PartialEq)] pub struct Call { pub callee: Box, diff --git a/src/language_frontend/abstract_syntax_tree/parser.rs b/src/language_frontend/abstract_syntax_tree/parser.rs index e058c94..e807a00 100644 --- a/src/language_frontend/abstract_syntax_tree/parser.rs +++ b/src/language_frontend/abstract_syntax_tree/parser.rs @@ -1,31 +1,50 @@ use chumsky::{ - combinator::Or, error::Rich, extra, input::{Input, Stream, ValueInput}, prelude::{choice, end, just, nested_delimiters, recursive, skip_then_retry_until, via_parser}, primitive::select, recursive, select, select_ref, span::{self, SimpleSpan}, text::{self, ascii::{ident, keyword}, newline, whitespace}, Boxed, ConfigIterParser, IterParser, ParseResult, Parser + Boxed, ConfigIterParser, IterParser, ParseResult, Parser, + combinator::Or, + error::Rich, + extra, + input::{Input, Stream, ValueInput}, + prelude::{choice, end, just, nested_delimiters, recursive, skip_then_retry_until, via_parser}, + primitive::select, + recursive, select, select_ref, + span::{self, SimpleSpan}, + text::{ + self, + ascii::{ident, keyword}, + newline, whitespace, + }, }; -use logos::{source, Logos}; +use logos::{Logos, source}; -use crate::language_frontend::{abstract_syntax_tree::{ast::Expr, definitions::*}, lexer::tokens::Token}; +use crate::language_frontend::{ + abstract_syntax_tree::{ast::Expr, definitions::*}, + lexer::tokens::Token, +}; // goal of parsing is to construct an abstract syntax tree -pub fn parse(source: &str) ->Result, Vec>> { - let token_iter = Token::lexer(source).spanned().map(|(token, span)| (token.unwrap_or(Token::Error), span.into())); +pub fn parse(source: &str) -> Result, Vec>> { + let token_iter = Token::lexer(source) + .spanned() + .map(|(token, span)| (token.unwrap_or(Token::Error), span.into())); let end_of_input: SimpleSpan = (0..source.len()).into(); let token_stream = Stream::from_iter(token_iter) // Tell chumsky to split the (Token, SimpleSpan) stream into its parts so that it can handle the spans for us // This involves giving chumsky an 'end of input' span: we just use a zero-width span at the end of the string - .map((0..end_of_input.into_iter().len()).into(), |(t, s): (_, _)| (t, s)); + .map( + (0..end_of_input.into_iter().len()).into(), + |(t, s): (_, _)| (t, s), + ); parser().parse(token_stream).into_result() } - -fn parser<'src, I>() - -> impl Parser<'src, I, Vec, extra::Err>> -where +fn parser<'src, I>() -> impl Parser<'src, I, Vec, extra::Err>> +where I: ValueInput<'src, Token = Token, Span = SimpleSpan>, { let ident = select! { Token::Identifier(s) => s, }; - /* + /* let block = recursive(|block| { let indent = just(Token::NewLine) .ignore_then(just(Token::Indent)) @@ -41,8 +60,9 @@ where Token::FloatLiteral(x) => Expr::FloatLiteral(x), Token::IntLiteral(x) => Expr::IntLiteral(x), } - .or(expr.clone().delimited_by(just(Token::LParen), just(Token::RParen))); - + .or(expr + .clone() + .delimited_by(just(Token::LParen), just(Token::RParen))); let mul_div = atom.clone().foldl( choice(( @@ -52,12 +72,14 @@ where .then(atom) .then_ignore(just(Token::NewLine).or_not()) .repeated(), - |lhs, (op, rhs)| Expr::BinaryExpr ( Binary { - lhs: Box::new(lhs), - operator: op, - rhs: Box::new(rhs), + |lhs, (op, rhs)| { + Expr::BinaryExpr(Binary { + lhs: Box::new(lhs), + operator: op, + rhs: Box::new(rhs), + }) }, - )); + ); let add_sub = mul_div.clone().foldl( choice(( @@ -67,12 +89,14 @@ where .then(mul_div) .then_ignore(just(Token::NewLine).or_not()) .repeated(), - |lhs, (op, rhs)| Expr::BinaryExpr ( Binary { - lhs: Box::new(lhs), - operator: op, - rhs: Box::new(rhs), + |lhs, (op, rhs)| { + Expr::BinaryExpr(Binary { + lhs: Box::new(lhs), + operator: op, + rhs: Box::new(rhs), + }) }, - )); + ); add_sub }); @@ -82,35 +106,35 @@ where .then_ignore(just(Token::Assign)) .then(expr.clone()) .then_ignore(just(Token::NewLine).or_not()) - .map(|(name, rhs)| Expr::VarExpr ( Var { - ty: None, - ident: name, - value: Box::new(rhs), - } - )); + .map(|(name, rhs)| { + Expr::VarExpr(Var { + ty: None, + ident: name, + value: Box::new(rhs), + }) + }); /* let fun = just(Token::Fun) .ignore_then(ident.clone()) .then_ignore(just(Token::LParen)) .then_ignore(just(Token::RParen)) - .map(|(((name, args), ret), (body, body_expr))| Expr::Function(Function { + .map(|(((name, args), ret), (body, body_expr))| Expr::Function(Function { name, - params: args, - return_type: ret, - body, - body_expr + params: args, + return_type: ret, + body, + body_expr })); */ var.or(expr) }); decl.repeated().collect() - } #[cfg(test)] mod tests { use super::*; - + #[test] fn test_unary_expr() { let negate_two = parse("-2"); @@ -118,7 +142,7 @@ mod tests { assert_eq!( negate_two.clone().unwrap(), vec![Expr::UnaryExpr(Unary { - operator: UnaryOp::Minus, + operator: UnaryOp::Minus, operand: Box::new(Expr::IntLiteral(2)), })] ) @@ -130,9 +154,9 @@ mod tests { assert!(sum.is_ok()); assert_eq!( sum.clone().unwrap(), - vec![Expr::BinaryExpr(Binary { - lhs: Box::new(Expr::IntLiteral(1)), - operator: BinaryOp::Add, + vec![Expr::BinaryExpr(Binary { + lhs: Box::new(Expr::IntLiteral(1)), + operator: BinaryOp::Add, rhs: Box::new(Expr::IntLiteral(2)) })] ) @@ -144,11 +168,11 @@ mod tests { assert!(var_without_expl_type.is_ok()); assert_eq!( var_without_expl_type.clone().unwrap(), - vec![Expr::VarExpr(Var { - ty: None, - ident: String::from("x"), - value: Box::new(Expr::IntLiteral(12)) - })] + vec![Expr::VarExpr(Var { + ty: None, + ident: String::from("x"), + value: Box::new(Expr::IntLiteral(12)) + })] ) } -} \ No newline at end of file +} diff --git a/src/language_frontend/lexer/tokens.rs b/src/language_frontend/lexer/tokens.rs index fe4711c..19728f6 100644 --- a/src/language_frontend/lexer/tokens.rs +++ b/src/language_frontend/lexer/tokens.rs @@ -1,6 +1,6 @@ use std::fmt; -use logos::{Logos}; +use logos::Logos; #[derive(Logos, Debug, Clone, PartialEq)] #[regex(r"[\t\f]+", logos::skip)] @@ -12,7 +12,7 @@ pub enum Token { // Keywords #[token("fun")] Fun, - + #[token("class")] Class, @@ -40,19 +40,18 @@ pub enum Token { #[token("enum")] Enum, - // Types #[token("int")] - IntType, + IntType, #[token("float")] - FloatType, + FloatType, #[token("bool")] - BoolType, + BoolType, #[token("String")] - StringType, + StringType, // Literals #[regex(r#""([^"\\]|\\.)*""#, |lex| lex.slice().to_owned())] @@ -71,7 +70,7 @@ pub enum Token { // Operators #[token("=")] Assign, - + #[token("==")] Equals, @@ -108,7 +107,6 @@ pub enum Token { #[token("||")] Or, - // Punctiuation #[token("(")] LParen, @@ -138,18 +136,15 @@ pub enum Token { Dot, // Special - #[regex(r"\n")] NewLine, #[regex(r"//[^\r]*", logos::skip)] #[regex(r"/\*([^*]|\*[^/])*\*/", logos::skip)] Comment, - + #[regex(r"[ \t\f]+", logos::skip)] Whitespace, - - Eof, @@ -207,4 +202,4 @@ impl fmt::Display for Token { Token::Error => write!(f, ""), } } -} \ No newline at end of file +} diff --git a/src/main.rs b/src/main.rs index a11075d..cfa7a42 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,14 +1,14 @@ -use chumsky::input::{Input, Stream}; use chumsky::Parser; +use chumsky::input::{Input, Stream}; use logos::Logos; mod language_frontend; - use crate::{ - language_frontend::lexer::tokens::Token, language_frontend::abstract_syntax_tree::parser::parse}; + language_frontend::abstract_syntax_tree::parser::parse, language_frontend::lexer::tokens::Token, +}; -use crate::language_frontend::abstract_syntax_tree::ast::{Expr}; +use crate::language_frontend::abstract_syntax_tree::ast::Expr; /* Simple Compiler -> 4 Stages: @@ -27,10 +27,10 @@ fn main() { println!("{:?}", sourcecode); - match parse(&sourcecode) { + match parse(&sourcecode) { Ok(res) => println!("{:#?}", res), Err(e) => { panic!("{:#?}", e) } - }; + }; }