diff --git a/src/ast.rs b/src/ast.rs index 4441d32..85382b0 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -1,3 +1,6 @@ +//! +//! The AST module contains all structs and enums for the abstract syntax tree generated by the parser + #![allow(dead_code)] /// imagine interning or something here diff --git a/src/errors.rs b/src/errors.rs index dec0070..eeb2088 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -1,3 +1,6 @@ +//! +//! This modules handles error reporting in the interpreter + use std::fmt::Debug; #[derive(Debug, Copy, Clone, PartialOrd, PartialEq, Ord, Eq, Hash)] @@ -18,6 +21,10 @@ impl Span { pub fn single(start: usize) -> Self { Self { start, len: 1 } } + + pub fn dummy() -> Self { + Self { start: 0, len: 0 } + } } pub trait CompilerError { diff --git a/src/lex.rs b/src/lex.rs index bfdf205..7a926f9 100644 --- a/src/lex.rs +++ b/src/lex.rs @@ -1,3 +1,6 @@ +//! +//! The lex module lexes the source code into Tokens + use crate::errors::{CompilerError, Span}; use std::iter::Peekable; use std::str::CharIndices; diff --git a/src/parse.rs b/src/parse.rs index bfd9798..3677c65 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -43,7 +43,7 @@ impl<'code> Parser<'code> { fn statement(&mut self) -> ParseResult<'code, Stmt> { let expr = self.expression()?; - self.expect(TokenType::Semi); + self.expect(TokenType::Semi)?; Ok(Stmt::Expr(expr)) } @@ -96,7 +96,11 @@ impl<'code> Parser<'code> { } fn unary(&mut self) -> ParseResult<'code, Expr> { - todo!() + match self.next().ok_or(ParseErr::EOF)?.kind { + TokenType::Not => todo!(), + TokenType::Minus => todo!(), + _ => todo!(), + } } fn primary(&mut self) -> ParseResult<'code, Expr> { @@ -106,8 +110,20 @@ impl<'code> Parser<'code> { TokenType::False => Ok(Expr::Literal(Literal::Boolean(false))), TokenType::True => Ok(Expr::Literal(Literal::Boolean(true))), TokenType::Null => Ok(Expr::Literal(Literal::Null)), - TokenType::BraceO => todo!(), - TokenType::BracketO => todo!(), + TokenType::BraceO => { + self.expect(TokenType::BraceC)?; + Ok(Expr::Literal(Literal::Object)) + } + TokenType::BracketO => { + let mut elements = Vec::new(); + while self.peek().ok_or(ParseErr::EOF)?.kind != TokenType::BracketC { + let expr = self.expression()?; + elements.push(expr); + self.expect(TokenType::Comma)?; + } + self.expect(TokenType::BracketC); + Ok(Expr::Literal(Literal::Array(elements))) + } TokenType::ParenO => todo!(), _ => todo!(), } @@ -165,3 +181,82 @@ impl CompilerError for ParseErr<'_> { todo!() } } + +#[cfg(test)] +mod test { + use crate::lex::{Token, TokenType}; + use crate::parse::Parser; + + fn token(kind: TokenType) -> Token { + Token { + span: crate::errors::Span::dummy(), + kind, + } + } + + fn parser<'a, T: Into>>>(tokens: T) -> Parser<'a> { + Parser { + tokens: tokens.into().into_iter().peekable(), + } + } + + mod primary { + use crate::ast::{Expr, Literal}; + use crate::lex::{Token, TokenType}; + use crate::parse::test::{parser, token}; + + fn parse_primary<'a, T: Into>>>(tokens: T) -> Expr { + let mut parser = parser(tokens); + parser.primary().unwrap() + } + + #[test] + fn string() { + let tokens = [TokenType::Number(10.0)].map(token); + let literal = parse_primary(tokens); + assert_eq!(Expr::Literal(Literal::Number(10.0)), literal); + } + + #[test] + fn number() { + let tokens = [TokenType::String("uwu".to_string())].map(token); + let literal = parse_primary(tokens); + assert_eq!(Expr::Literal(Literal::String("uwu".to_string())), literal); + } + + #[test] + fn empty_object() { + let tokens = [TokenType::BraceO, TokenType::BraceC].map(token); + let literal = parse_primary(tokens); + assert_eq!(Expr::Literal(Literal::Object), literal); + } + + #[test] + fn empty_array() { + let tokens = [TokenType::BracketO, TokenType::BracketC].map(token); + let literal = parse_primary(tokens); + assert_eq!(Expr::Literal(Literal::Array(Vec::new())), literal); + } + + #[test] + fn r#false() { + let tokens = [TokenType::False].map(token); + let literal = parse_primary(tokens); + assert_eq!(Expr::Literal(Literal::Boolean(false)), literal); + } + + #[test] + fn r#true() { + let tokens = [TokenType::True].map(token); + let literal = parse_primary(tokens); + assert_eq!(Expr::Literal(Literal::Boolean(true)), literal); + } + + #[test] + fn null() { + let tokens = [TokenType::Null].map(token); + let literal = parse_primary(tokens); + assert_eq!(Expr::Literal(Literal::Null), literal); + } + } +}