diff --git a/src/ast.rs b/src/ast.rs index 85382b0..502f9cd 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -1,8 +1,9 @@ //! //! The AST module contains all structs and enums for the abstract syntax tree generated by the parser - #![allow(dead_code)] +use crate::errors::Span; + /// imagine interning or something here pub type Symbol = String; @@ -20,25 +21,28 @@ pub enum Stmt { If(IfStmt), Loop(Block), While(WhileStmt), - Break, + Break(Break), Return(Option), Expr(Expr), } #[derive(Debug, Clone, PartialEq)] pub struct Declaration { + pub span: Span, name: Symbol, init: Expr, } #[derive(Debug, Clone, PartialEq)] pub struct Assignment { + pub span: Span, pub lhs: Symbol, pub rhs: Expr, } #[derive(Debug, Clone, PartialEq)] pub struct FnDecl { + pub span: Span, pub name: Symbol, pub params: Vec, pub body: Block, @@ -46,6 +50,7 @@ pub struct FnDecl { #[derive(Debug, Clone, PartialEq)] pub struct IfStmt { + pub span: Span, pub condition: Expr, pub body: Block, pub else_part: Box, @@ -59,29 +64,59 @@ pub enum ElsePart { #[derive(Debug, Clone, PartialEq)] pub struct WhileStmt { + pub span: Span, pub cond: Expr, pub body: Block, } +#[derive(Debug, Clone, PartialEq)] +pub struct Break { + pub span: Span, +} + #[derive(Debug, Clone, PartialEq)] pub enum Expr { Literal(Literal), - UnaryOp, - BinaryOp, + UnaryOp(Box), + BinaryOp(Box), +} + +impl Expr { + pub fn span(&self) -> Span { + match self { + Expr::Literal(lit) => lit.span(), + Expr::UnaryOp(unary) => unary.span, + Expr::BinaryOp(binary) => binary.span, + } + } } #[derive(Debug, Clone, PartialEq)] pub enum Literal { - String(String), - Number(f64), - Array(Vec), - Object, - Boolean(bool), - Null, + String(String, Span), + Number(f64, Span), + Array(Vec, Span), + Object(Span), + Boolean(bool, Span), + Null(Span), +} + +impl Literal { + pub fn span(&self) -> Span { + match self { + Literal::String(_, span) => *span, + Literal::Number(_, span) => *span, + Literal::Array(_, span) => *span, + Literal::Object(span) => *span, + Literal::Boolean(_, span) => *span, + Literal::Null(span) => *span, + } + } } #[derive(Debug, Clone, PartialEq)] pub struct UnaryOp { + pub span: Span, pub expr: Expr, pub kind: UnaryOpKind, } @@ -94,6 +129,7 @@ pub enum UnaryOpKind { #[derive(Debug, Clone, PartialEq)] pub struct BinaryOp { + pub span: Span, pub lhs: Expr, pub rhs: Expr, pub kind: BinaryOpKind, @@ -115,9 +151,3 @@ pub enum BinaryOpKind { Div, Mod, } - -#[derive(Debug, Clone, PartialEq)] -pub enum Call { - Function(Expr, Vec), - Field(Expr, Vec), -} diff --git a/src/errors.rs b/src/errors.rs index eeb2088..243d79e 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -3,27 +3,53 @@ use std::fmt::Debug; -#[derive(Debug, Copy, Clone, PartialOrd, PartialEq, Ord, Eq, Hash)] -pub struct Span { - start: usize, - len: usize, -} +pub use span::Span; -impl Span { - pub fn new(start: usize, len: usize) -> Self { - Self { start, len } +mod span { + + #[derive(Debug, Copy, Clone, PartialOrd, PartialEq, Ord, Eq, Hash)] + pub struct Span { + pub start: usize, + pub end: usize, } - pub fn start_end(start: usize, end: usize) -> Self { - Self::new(start, end - start) - } + impl Span { + pub fn new(start: usize, len: usize) -> Self { + Self { + start, + end: start + len, + } + } - pub fn single(start: usize) -> Self { - Self { start, len: 1 } - } + pub fn start_end(start: usize, end: usize) -> Self { + Self::new(start, end) + } - pub fn dummy() -> Self { - Self { start: 0, len: 0 } + pub fn single(start: usize) -> Self { + Self { + start, + end: start + 1, + } + } + + pub fn dummy() -> Self { + Self { start: 0, end: 0 } + } + + /// Extends the span by the second one + /// The other one has to be after the current one + pub fn extend(&self, other: Span) -> Span { + debug_assert!(self.start <= other.start); + debug_assert!(self.end <= other.end); + Span { + start: self.start, + end: other.end, + } + } + + pub fn len(&self) -> usize { + self.end - self.start + } } } @@ -57,7 +83,7 @@ where "{}{}{}{}", " ".repeat(offset_on_line), RED, - "^".repeat(error.span().len), + "^".repeat(error.span().len()), RESET, ); if let Some(note) = error.note() { diff --git a/src/lex.rs b/src/lex.rs index 7a926f9..1cedbd6 100644 --- a/src/lex.rs +++ b/src/lex.rs @@ -126,7 +126,7 @@ impl<'code> Lexer<'code> { if self.expect(expect_char) { let _ = self.code.next(); // consume first one Token { - span: Span::new(start, 2), + span: Span::new(start, start + 2), kind: true_type, } } else { @@ -191,7 +191,7 @@ impl<'code> Iterator for Lexer<'code> { if self.expect('=') { let _ = self.code.next(); // consume =; break Token { - span: Span::new(start, 2), + span: Span::new(start, start + 2), kind: TokenType::BangEqual, }; } else { diff --git a/src/parse.rs b/src/parse.rs index 3677c65..3237c7b 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -96,23 +96,39 @@ impl<'code> Parser<'code> { } fn unary(&mut self) -> ParseResult<'code, Expr> { - match self.next().ok_or(ParseErr::EOF)?.kind { - TokenType::Not => todo!(), - TokenType::Minus => todo!(), + let next = self.next().ok_or(ParseErr::EOF)?; + match next.kind { + TokenType::Not => { + let expr = self.expression()?; + Ok(Expr::UnaryOp(Box::new(UnaryOp { + span: next.span, + expr, + kind: UnaryOpKind::Not, + }))) + } + TokenType::Minus => { + let expr = self.expression()?; + Ok(Expr::UnaryOp(Box::new(UnaryOp { + span: next.span, + expr, + kind: UnaryOpKind::Neg, + }))) + } _ => todo!(), } } fn primary(&mut self) -> ParseResult<'code, Expr> { - match self.next().ok_or(ParseErr::EOF)?.kind { - TokenType::String(literal) => Ok(Expr::Literal(Literal::String(literal))), - TokenType::Number(literal) => Ok(Expr::Literal(Literal::Number(literal))), - TokenType::False => Ok(Expr::Literal(Literal::Boolean(false))), - TokenType::True => Ok(Expr::Literal(Literal::Boolean(true))), - TokenType::Null => Ok(Expr::Literal(Literal::Null)), + let next = self.next().ok_or(ParseErr::EOF)?; + match next.kind { + TokenType::String(literal) => Ok(Expr::Literal(Literal::String(literal, next.span))), + TokenType::Number(literal) => Ok(Expr::Literal(Literal::Number(literal, next.span))), + TokenType::False => Ok(Expr::Literal(Literal::Boolean(false, next.span))), + TokenType::True => Ok(Expr::Literal(Literal::Boolean(true, next.span))), + TokenType::Null => Ok(Expr::Literal(Literal::Null(next.span))), TokenType::BraceO => { self.expect(TokenType::BraceC)?; - Ok(Expr::Literal(Literal::Object)) + Ok(Expr::Literal(Literal::Object(next.span))) } TokenType::BracketO => { let mut elements = Vec::new(); @@ -121,8 +137,11 @@ impl<'code> Parser<'code> { elements.push(expr); self.expect(TokenType::Comma)?; } - self.expect(TokenType::BracketC); - Ok(Expr::Literal(Literal::Array(elements))) + let closing_bracket = self.expect(TokenType::BracketC)?; + Ok(Expr::Literal(Literal::Array( + elements, + next.span.extend(closing_bracket.span), + ))) } TokenType::ParenO => todo!(), _ => todo!(), @@ -130,9 +149,9 @@ impl<'code> Parser<'code> { } fn object_literal(&mut self) -> ParseResult<'code, Expr> { - self.expect(TokenType::BraceO)?; - self.expect(TokenType::BraceC)?; - Ok(Expr::Literal(Literal::Object)) + let open_span = self.expect(TokenType::BraceO)?.span; + let close_span = self.expect(TokenType::BraceC)?.span; + Ok(Expr::Literal(Literal::Object(open_span.extend(close_span)))) } fn array_literal(&mut self) -> ParseResult<'code, Expr> { @@ -149,10 +168,10 @@ impl<'code> Parser<'code> { self.tokens.peek() } - fn expect(&mut self, kind: TokenType<'code>) -> ParseResult<'code, ()> { + fn expect(&mut self, kind: TokenType<'code>) -> ParseResult<'code, Token> { if let Some(token) = self.next() { if token.kind == kind { - Ok(()) + Ok(token) } else { Err(ParseErr::MismatchedKind { expected: kind }) } @@ -200,10 +219,17 @@ mod test { } } - mod primary { + mod unary { + use super::{parser, token}; use crate::ast::{Expr, Literal}; use crate::lex::{Token, TokenType}; - use crate::parse::test::{parser, token}; + } + + mod primary { + use super::{parser, token}; + use crate::ast::{Expr, Literal}; + use crate::errors::Span; + use crate::lex::{Token, TokenType}; fn parse_primary<'a, T: Into>>>(tokens: T) -> Expr { let mut parser = parser(tokens); @@ -214,49 +240,61 @@ mod 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); + assert_eq!(Expr::Literal(Literal::Number(10.0, Span::dummy())), 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); + assert_eq!( + Expr::Literal(Literal::String("uwu".to_string(), Span::dummy())), + 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); + assert_eq!(Expr::Literal(Literal::Object(Span::dummy())), 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); + assert_eq!( + Expr::Literal(Literal::Array(Vec::new(), Span::dummy())), + literal + ); } #[test] fn r#false() { let tokens = [TokenType::False].map(token); let literal = parse_primary(tokens); - assert_eq!(Expr::Literal(Literal::Boolean(false)), literal); + assert_eq!( + Expr::Literal(Literal::Boolean(false, Span::dummy())), + literal + ); } #[test] fn r#true() { let tokens = [TokenType::True].map(token); let literal = parse_primary(tokens); - assert_eq!(Expr::Literal(Literal::Boolean(true)), literal); + assert_eq!( + Expr::Literal(Literal::Boolean(true, Span::dummy())), + literal + ); } #[test] fn null() { let tokens = [TokenType::Null].map(token); let literal = parse_primary(tokens); - assert_eq!(Expr::Literal(Literal::Null), literal); + assert_eq!(Expr::Literal(Literal::Null(Span::dummy())), literal); } } }