diff --git a/src/main.rs b/src/main.rs index cfa8770..419d0e7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,5 @@ +#![feature(box_patterns)] + mod util; mod v1; mod v2; diff --git a/src/v1/mod.rs b/src/v1/mod.rs index 69a0f3f..00162fc 100644 --- a/src/v1/mod.rs +++ b/src/v1/mod.rs @@ -2,38 +2,30 @@ use std::io::{stdout, BufRead, BufReader}; mod parser; -use parser::{Module, Node, NodeContainer, Statement, TokenCursor}; +use parser::{Module, Node, ParserErrors, Statement, TokenCursor}; pub fn parse_file(file: &str) { - let node = Node::::parse(&mut TokenCursor::from(file)); - match node.inner { - Err(err) => err.write_for(&mut stdout(), file).unwrap(), - Ok(module) => { - println!("{module:#?}"); - print_errors(module.children(), file) - }, + let mut errors = ParserErrors::new(); + let node = Node::::parse(&mut TokenCursor::from(file), &mut errors); + if let Ok(module) = node.as_ref() { + println!("{module:#?}"); }; -} - -pub fn print_errors(nodes: Vec>>, file: &str) { - for node in &nodes { - if let Err(err) = &node.inner { - err.write_for(&mut stdout(), file).unwrap(); - } - } - for node in nodes { - print_errors(node.children(), file) + for err in errors.errs { + err.write_for(&mut stdout(), file).unwrap(); } } pub fn run_stdin() { for line in BufReader::new(std::io::stdin()).lines() { + let mut errors = ParserErrors::new(); let str = &line.expect("failed to read line"); let mut cursor = TokenCursor::from(&str[..]); let out = &mut stdout(); - match Node::::parse(&mut cursor).inner { - Ok(expr) => println!("{:?}", expr), - Err(err) => err.write_for(out, str).unwrap(), + if let Ok(expr) = Node::::parse(&mut cursor, &mut errors).as_ref() { + println!("{:?}", expr); + } + for err in errors.errs { + err.write_for(&mut stdout(), str).unwrap(); } } } diff --git a/src/v1/parser/body.rs b/src/v1/parser/body.rs index c42e5c8..80f4ce2 100644 --- a/src/v1/parser/body.rs +++ b/src/v1/parser/body.rs @@ -1,7 +1,8 @@ use std::fmt::{Debug, Write}; use super::{ - token::{Keyword, Symbol, Token}, Node, NodeContainer, Parsable + token::{Keyword, Symbol, Token}, + Node, Parsable, ParserErrors, }; use crate::util::Padder; @@ -19,8 +20,19 @@ pub enum Statement { Expr(Node), } +impl Statement { + pub fn ended_with_error(&self) -> bool { + let expr = match self { + Statement::Let(_, e) => e, + Statement::Return(e) => e, + Statement::Expr(e) => e, + }; + expr.is_err() || expr.as_ref().is_ok_and(|e| e.ended_with_error()) + } +} + impl Parsable for Body { - fn parse(cursor: &mut TokenCursor) -> Result { + fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> Result { let mut statements = Vec::new(); let statement_end = &[Symbol::Semicolon, Symbol::CloseCurly]; cursor.expect_sym(Symbol::OpenCurly)?; @@ -28,54 +40,51 @@ impl Parsable for Body { cursor.next(); return Ok(Self { statements }); } + let mut expect_semi = false; loop { let next = cursor.expect_peek()?; if next.is_symbol(Symbol::CloseCurly) { cursor.next(); return Ok(Self { statements }); } - statements.push(Node::parse(cursor)); - let next = cursor.expect_next()?; - match next.token { - Token::Symbol(Symbol::Semicolon) => continue, - Token::Symbol(Symbol::CloseCurly) => return Ok(Self { statements }), - _ => { - let start = next.span.start; - cursor - .seek(|t| t.is_symbol_and(|s| statement_end.contains(&s))) - .ok_or(ParserError::unexpected_end())?; - let end = cursor.prev_end(); - let next = cursor.expect_next()?; - let span = start.to(end); - statements.push(Node::err(ParserError { - msg: "Unexpected tokens".to_string(), - spans: vec![span], - }, span)); - if next.is_symbol(Symbol::CloseCurly) { - return Ok(Self { statements }); - } - } + if next.is_symbol(Symbol::Semicolon) { + cursor.next(); + expect_semi = false; + continue; + } else if expect_semi { + errors.add(ParserError { + msg: "expected ';'".to_string(), + spans: vec![cursor.next_pos().char_span()], + }); } + let statement: Node = Node::parse(cursor, errors); + expect_semi = true; + if statement.is_err() || statement.as_ref().is_ok_and(|s| s.ended_with_error()) { + let res = cursor + .seek(|t| t.is_symbol_and(|s| statement_end.contains(&s))) + .ok_or(ParserError::unexpected_end())?; + } + statements.push(statement); } } } impl Parsable for Statement { - fn parse(cursor: &mut TokenCursor) -> Result { + fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> Result { let next = cursor.expect_peek()?; Ok(match next.token { Token::Keyword(Keyword::Let) => { cursor.next(); let name = cursor.expect_ident()?; cursor.expect_sym(Symbol::Equals)?; - let expr = Node::parse(cursor); + let expr = Node::parse(cursor, errors); Self::Let(name, expr) } Token::Keyword(Keyword::Return) => { cursor.next(); - Self::Return(Node::parse(cursor)) + Self::Return(Node::parse(cursor, errors)) } - _ => Self::Expr(Node::parse(cursor)), + _ => Self::Expr(Node::parse(cursor, errors)), }) } } @@ -120,19 +129,3 @@ impl Debug for Body { Ok(()) } } - -impl NodeContainer for Body { - fn children(&self) -> Vec>> { - self.statements.iter().map(|f| f.containerr()).collect() - } -} - -impl NodeContainer for Statement { - fn children(&self) -> Vec>> { - match self { - Statement::Let(_, e) => vec![e.containerr()], - Statement::Return(e) => vec![e.containerr()], - Statement::Expr(e) => vec![e.containerr()], - } - } -} diff --git a/src/v1/parser/error.rs b/src/v1/parser/error.rs index 3a6e44a..79c6d55 100644 --- a/src/v1/parser/error.rs +++ b/src/v1/parser/error.rs @@ -39,7 +39,7 @@ impl ParserError { let t = &inst.token; ParserError::from_instances( &[inst], - format!("Unexpected token {t:?}; expected {expected}"), + format!("unexpected token {t:?}; expected {expected}"), ) } pub fn write_for(&self, writer: &mut impl std::io::Write, file: &str) -> std::io::Result<()> { @@ -53,6 +53,9 @@ impl ParserError { } impl ParserErrors { + pub fn new() -> Self { + Self { errs: Vec::new() } + } pub fn add(&mut self, err: ParserError) { self.errs.push(err); } diff --git a/src/v1/parser/expr.rs b/src/v1/parser/expr.rs index acaabb4..dedafb8 100644 --- a/src/v1/parser/expr.rs +++ b/src/v1/parser/expr.rs @@ -1,15 +1,18 @@ use std::fmt::{Debug, Write}; use super::token::{Symbol, Token}; -use super::{Body, Node, NodeContainer, Parsable, ParserError, TokenCursor, Val}; +use super::{Body, Node, Parsable, ParserError, ParserErrors, TokenCursor, Val}; + +pub type ExprNode = Node>; #[derive(Clone)] pub enum Expr { Val(Node), Ident(String), - BinaryOp(Operator, Node>, Node>), + BinaryOp(Operator, ExprNode, ExprNode), Block(Node), - Call(Node>, Vec>), + Call(ExprNode, Vec>), + Group(ExprNode), } #[derive(Debug, PartialEq, Eq, Clone, Copy)] @@ -21,29 +24,44 @@ pub enum Operator { LessThan, GreaterThan, Access, + Assign, +} + +impl Expr { + pub fn ended_with_error(&self) -> bool { + match self { + Expr::Val(_) => false, + Expr::Ident(_) => false, + Expr::BinaryOp(_, _, e) => e.is_err() || e.as_ref().is_ok_and(|e| e.ended_with_error()), + Expr::Block(b) => b.is_err(), + Expr::Call(_, _) => false, + Expr::Group(_) => false, + } + } } impl Parsable for Expr { - fn parse(cursor: &mut TokenCursor) -> Result { + fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> Result { let start = cursor.next_pos(); - let Some(next) = cursor.peek() else { - return Ok(Expr::Val(Node::new( - Val::Unit, - cursor.next_pos().char_span(), - ))); - }; + let next = cursor.expect_peek()?; let mut e1 = if next.is_symbol(Symbol::OpenParen) { cursor.next(); - let expr = Node::parse(cursor); - if expr.is_ok() { - cursor.expect_sym(Symbol::CloseParen)?; - } else { + if cursor.expect_peek()?.is_symbol(Symbol::CloseParen) { + cursor.next(); + return Ok(Expr::Val(Node::new( + Val::Unit, + cursor.next_pos().char_span(), + ))); + } + let expr = Node::parse(cursor, errors).bx(); + if expr.is_err() { cursor.seek_sym(Symbol::CloseParen); } - expr.take()? + cursor.expect_sym(Symbol::CloseParen)?; + Self::Group(expr) } else if next.is_symbol(Symbol::OpenCurly) { - Self::Block(Node::parse(cursor)) - } else if let Some(val) = Node::maybe_parse(cursor) { + Self::Block(Node::parse(cursor, errors)) + } else if let Some(val) = Node::maybe_parse(cursor, errors) { Self::Val(val) } else { let next = cursor.peek().unwrap(); @@ -54,10 +72,7 @@ impl Parsable for Expr { Self::Ident(name) } _ => { - return Ok(Expr::Val(Node::new( - Val::Unit, - cursor.next_pos().char_span(), - ))) + return Err(ParserError::unexpected_token(next, "an expression")); } } }; @@ -66,7 +81,7 @@ impl Parsable for Expr { }; while next.is_symbol(Symbol::OpenParen) { cursor.next(); - let inner = Node::parse(cursor); + let inner = Node::parse(cursor, errors); cursor.expect_sym(Symbol::CloseParen)?; let end = cursor.prev_end(); e1 = Self::Call(Node::new(Box::new(e1), start.to(end)), vec![inner]); @@ -79,18 +94,18 @@ impl Parsable for Expr { Ok(if let Some(mut op) = Operator::from_token(&next.token) { cursor.next(); let mut n1 = Node::new(Box::new(e1), start.to(end)); - let mut n2 = Node::::parse(cursor); - if let Ok(Self::BinaryOp(op2, n21, n22)) = &*n2 { + let mut n2 = Node::parse(cursor, errors).bx(); + if let Ok(box Self::BinaryOp(op2, n21, n22)) = n2.as_ref() { if op.presedence() > op2.presedence() { n1 = Node::new( Box::new(Self::BinaryOp(op, n1, n21.clone())), start.to(n21.span.end), ); op = *op2; - n2 = n22.clone().unbx(); + n2 = n22.clone(); } } - Self::BinaryOp(op, n1, n2.bx()) + Self::BinaryOp(op, n1, n2) } else { e1 }) @@ -100,13 +115,14 @@ impl Parsable for Expr { impl Operator { pub fn presedence(&self) -> u32 { match self { - Operator::LessThan => 0, - Operator::GreaterThan => 0, - Operator::Add => 1, - Operator::Sub => 2, - Operator::Mul => 3, - Operator::Div => 4, - Operator::Access => 5, + Operator::Assign => 0, + Operator::LessThan => 1, + Operator::GreaterThan => 1, + Operator::Add => 2, + Operator::Sub => 3, + Operator::Mul => 4, + Operator::Div => 5, + Operator::Access => 6, } } pub fn str(&self) -> &str { @@ -118,6 +134,7 @@ impl Operator { Self::LessThan => "<", Self::GreaterThan => ">", Self::Access => ".", + Self::Assign => "=", } } pub fn from_token(token: &Token) -> Option { @@ -132,6 +149,7 @@ impl Operator { Symbol::Asterisk => Operator::Mul, Symbol::Slash => Operator::Div, Symbol::Dot => Operator::Access, + Symbol::Equals => Operator::Assign, _ => { return None; } @@ -139,13 +157,14 @@ impl Operator { } pub fn pad(&self) -> bool { match self { - Operator::Add => true, - Operator::Sub => true, - Operator::Mul => true, - Operator::Div => true, - Operator::LessThan => true, - Operator::GreaterThan => true, - Operator::Access => false, + Self::Add => true, + Self::Sub => true, + Self::Mul => true, + Self::Div => true, + Self::LessThan => true, + Self::GreaterThan => true, + Self::Access => false, + Self::Assign => true, } } } @@ -177,22 +196,8 @@ impl Debug for Expr { } f.write_char(')')?; } + Expr::Group(inner) => inner.fmt(f)?, } Ok(()) } } - -impl NodeContainer for Expr { - fn children(&self) -> Vec>> { - match self { - Expr::Val(_) => Vec::new(), - Expr::Ident(_) => Vec::new(), - Expr::BinaryOp(_, e1, e2) => vec![e1.container(), e2.container()], - Expr::Block(b) => vec![b.containerr()], - Expr::Call(e1, rest) => [e1.container()] - .into_iter() - .chain(rest.iter().map(|e| e.containerr())) - .collect(), - } - } -} diff --git a/src/v1/parser/mod.rs b/src/v1/parser/mod.rs index a9cd93a..bad485e 100644 --- a/src/v1/parser/mod.rs +++ b/src/v1/parser/mod.rs @@ -29,14 +29,14 @@ pub struct Function { } impl Parsable for Module { - fn parse(cursor: &mut TokenCursor) -> Result { + fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> Result { let mut functions = Vec::new(); loop { let Some(next) = cursor.peek() else { return Ok(Self { functions }); }; if next.is_keyword(Keyword::Fn) { - functions.push(Node::parse(cursor)); + functions.push(Node::parse(cursor, errors)); } else { return Err(ParserError::unexpected_token(next, "fn")); } @@ -45,12 +45,12 @@ impl Parsable for Module { } impl Parsable for Function { - fn parse(cursor: &mut TokenCursor) -> Result { + fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> Result { cursor.expect_kw(Keyword::Fn)?; let name = cursor.expect_ident()?; cursor.expect_sym(Symbol::OpenParen)?; cursor.expect_sym(Symbol::CloseParen)?; - let body = Node::parse(cursor); + let body = Node::parse(cursor, errors); Ok(Self { name, body }) } } @@ -65,14 +65,3 @@ impl Debug for Function { } } -impl NodeContainer for Module { - fn children(&self) -> Vec>> { - self.functions.iter().map(|f| f.containerr()).collect() - } -} - -impl NodeContainer for Function { - fn children(&self) -> Vec>> { - vec![self.body.containerr()] - } -} diff --git a/src/v1/parser/node.rs b/src/v1/parser/node.rs index 9009377..1746a26 100644 --- a/src/v1/parser/node.rs +++ b/src/v1/parser/node.rs @@ -3,39 +3,29 @@ use std::{ ops::{Deref, DerefMut}, }; -use super::{FileSpan, ParserError, TokenCursor}; +use super::{FileSpan, ParserError, ParserErrors, TokenCursor}; #[derive(Clone)] pub struct Node { - pub inner: Result, + pub inner: Result, pub span: FileSpan, } pub trait Parsable: Sized { - fn parse(cursor: &mut TokenCursor) -> Result; + fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> Result; } pub trait MaybeParsable: Sized { - fn maybe_parse(cursor: &mut TokenCursor) -> Result, ParserError>; -} - -pub trait NodeContainer { - fn children(&self) -> Vec>>; -} - -impl NodeContainer for Node> { - fn children(&self) -> Vec>> { - match &self.inner { - Ok(v) => v.children(), - Err(_) => Vec::new(), - } - } + fn maybe_parse( + cursor: &mut TokenCursor, + errors: &mut ParserErrors, + ) -> Result, ParserError>; } impl Node { - pub fn parse(cursor: &mut TokenCursor) -> Self { + pub fn parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> Self { let start = cursor.next_pos(); - let inner = T::parse(cursor); + let inner = T::parse(cursor, errors).map_err(|e| errors.add(e)); let end = cursor.prev_end(); Self { inner, @@ -45,11 +35,14 @@ impl Node { } impl Node { - pub fn maybe_parse(cursor: &mut TokenCursor) -> Option { + pub fn maybe_parse(cursor: &mut TokenCursor, errors: &mut ParserErrors) -> Option { let start = cursor.next_pos(); - let inner = match T::maybe_parse(cursor) { + let inner = match T::maybe_parse(cursor, errors) { Ok(v) => Ok(v?), - Err(e) => Err(e), + Err(e) => { + errors.add(e); + Err(()) + } }; let end = cursor.prev_end(); Some(Self { @@ -66,15 +59,6 @@ impl Node { span, } } - pub fn err(inner: ParserError, span: FileSpan) -> Self { - Self { - inner: Err(inner), - span, - } - } - pub fn take(self) -> Result { - self.inner - } pub fn bx(self) -> Node> { Node { inner: self.inner.map(|v| Box::new(v)), @@ -83,15 +67,6 @@ impl Node { } } -impl Node { - pub fn containerr(&self) -> Node> { - Node { - inner: self.clone().inner.map(|v| Box::new(v) as Box), - span: self.span, - } - } -} - impl Node> { pub fn unbx(self) -> Node { Node { @@ -100,17 +75,8 @@ impl Node> { } } } -impl Node> { - pub fn container(&self) -> Node> { - Node { - inner: self.clone().inner.map(|v| v as Box), - span: self.span, - } - } -} - impl Deref for Node { - type Target = Result; + type Target = Result; fn deref(&self) -> &Self::Target { &self.inner } diff --git a/src/v1/parser/token/file.rs b/src/v1/parser/token/file.rs index 7bbcc97..6402f4a 100644 --- a/src/v1/parser/token/file.rs +++ b/src/v1/parser/token/file.rs @@ -26,7 +26,7 @@ impl FilePos { } const BEFORE: usize = 1; -const AFTER: usize = 1; +const AFTER: usize = 0; impl FileSpan { pub fn at(pos: FilePos) -> Self { @@ -70,11 +70,11 @@ impl FileSpan { "^".repeat(self.end.col + 1) )?; } - for i in 0..AFTER { - if let Some(next) = lines.next() { - writeln!(writer, "{:>width$} | {}", self.end.line + i + 1, next)?; - } - } + // for i in 0..AFTER { + // if let Some(next) = lines.next() { + // writeln!(writer, "{:>width$} | {}", self.end.line + i + 1, next)?; + // } + // } Ok(()) } } diff --git a/src/v1/parser/token/mod.rs b/src/v1/parser/token/mod.rs index 6b489a4..59e25f6 100644 --- a/src/v1/parser/token/mod.rs +++ b/src/v1/parser/token/mod.rs @@ -17,7 +17,7 @@ pub enum Token { Keyword(Keyword), } -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct TokenInstance { pub token: Token, pub span: FileSpan, diff --git a/src/v1/parser/token/symbol.rs b/src/v1/parser/token/symbol.rs index 6565a47..5db8b14 100644 --- a/src/v1/parser/token/symbol.rs +++ b/src/v1/parser/token/symbol.rs @@ -27,6 +27,7 @@ pub enum Symbol { CloseAngle, SingleQuote, DoubleQuote, + Bang, } impl Symbol { @@ -57,6 +58,7 @@ impl Symbol { '.' => Self::Dot, '\'' => Self::SingleQuote, '"' => Self::DoubleQuote, + '!' => Self::Bang, _ => return None, }) } @@ -88,30 +90,30 @@ impl Symbol { } pub fn str(&self) -> &str { match self { - Symbol::Semicolon => ";", - Symbol::Colon => ":", - Symbol::DoubleColon => "::", - Symbol::Equals => "=", - Symbol::DoubleEquals => "==", - Symbol::Arrow => "->", - Symbol::DoubleArrow => "=>", - Symbol::Plus => "+", - Symbol::Minus => "-", - Symbol::Asterisk => "*", - Symbol::Slash => "/", - Symbol::DoubleSlash => "//", - Symbol::Dot => ".", - Symbol::OpenParen => "(", - Symbol::CloseParen => ")", - Symbol::OpenCurly => "{", - Symbol::CloseCurly => "}", - Symbol::OpenSquare => "[", - Symbol::CloseSquare => "]", - Symbol::OpenAngle => "<", - Symbol::CloseAngle => ">", - Symbol::SingleQuote => "'", - Symbol::DoubleQuote => "\"", - + Self::Semicolon => ";", + Self::Colon => ":", + Self::DoubleColon => "::", + Self::Equals => "=", + Self::DoubleEquals => "==", + Self::Arrow => "->", + Self::DoubleArrow => "=>", + Self::Plus => "+", + Self::Minus => "-", + Self::Asterisk => "*", + Self::Slash => "/", + Self::DoubleSlash => "//", + Self::Dot => ".", + Self::OpenParen => "(", + Self::CloseParen => ")", + Self::OpenCurly => "{", + Self::CloseCurly => "}", + Self::OpenSquare => "[", + Self::CloseSquare => "]", + Self::OpenAngle => "<", + Self::CloseAngle => ">", + Self::SingleQuote => "'", + Self::DoubleQuote => "\"", + Self::Bang => "!", } } } diff --git a/src/v1/parser/val.rs b/src/v1/parser/val.rs index 1674478..27457fc 100644 --- a/src/v1/parser/val.rs +++ b/src/v1/parser/val.rs @@ -1,4 +1,4 @@ -use super::{CharCursor, MaybeParsable, NodeContainer, ParserError, Symbol, Token, TokenCursor}; +use super::{CharCursor, MaybeParsable, ParserError, ParserErrors, Symbol, Token, TokenCursor}; use std::fmt::Debug; #[derive(Clone, PartialEq, Eq)] @@ -17,7 +17,7 @@ pub struct Number { } impl MaybeParsable for Val { - fn maybe_parse(cursor: &mut TokenCursor) -> Result, ParserError> { + fn maybe_parse(cursor: &mut TokenCursor, _: &mut ParserErrors) -> Result, ParserError> { let inst = cursor.expect_peek()?; let mut res = match &inst.token { Token::Symbol(Symbol::SingleQuote) => { diff --git a/test.lang b/test.lang index 6cfc18a..17c58a8 100644 --- a/test.lang +++ b/test.lang @@ -10,6 +10,9 @@ fn main() { return 5 + a; + r = )!!; + r = !3; + r = 3 + !; let b = (test2.func)(3 + 4)(8)("a"); let x = { return 5;