diff --git a/src/frontend/mod.rs b/src/frontend/mod.rs index 565d9e9..a27d605 100644 --- a/src/frontend/mod.rs +++ b/src/frontend/mod.rs @@ -1,4 +1,4 @@ pub mod types; -mod lexer; +pub mod lexer; pub mod parser; pub mod err; \ No newline at end of file diff --git a/src/frontend/parser.rs b/src/frontend/parser.rs index 7359101..d20d164 100644 --- a/src/frontend/parser.rs +++ b/src/frontend/parser.rs @@ -12,7 +12,7 @@ use crate::{ pub struct Parser { tokens: Vec, - diagnostics: Diagnositics, + pub diagnostics: Diagnositics, pos: usize, } #[derive(Debug, Clone, PartialEq, Eq)] @@ -31,7 +31,9 @@ impl Parser { pos: 0, } } - pub fn parse(&mut self) {} + pub fn parse(&mut self) -> CompileUnit { + self.parse_compile_unit() + } fn peek(&self) -> Option<&Token> { self.tokens.get(self.pos) } @@ -366,10 +368,68 @@ impl Parser { assert!(self.peek().is_some()); let token = self.next().unwrap().clone(); match token.value { - TokenValue::Ident(name) => Some(Expr { - value: ExprValue::Var(name), - span: token.span, - }), + TokenValue::Ident(name) => { + if self + .peek() + .is_some_and(|t| matches!(t.value, TokenValue::LParen)) + { + self.advance(1); + let mut args = vec![]; + loop { + match self.peek() { + Some(t) if matches!(t.value, TokenValue::RParen) => { + let end_span = t.span; + self.advance(1); + return Some(Expr { + value: ExprValue::FuncCall(name, args), + span: Span::from_two(token.span, end_span), + }); + } + Some(_) => {} + None => { + self.diagnostics.add_from_frontend_error( + ParseError::ExpectButEof("`)`"), + token.span, + ); + return None; + } + } + args.push(self.parse_expr()?); + match self.peek() { + Some(t) if matches!(t.value, TokenValue::Comma) => { + self.advance(1); + } + Some(t) if matches!(t.value, TokenValue::RParen) => { + let end_span = t.span; + self.advance(1); + return Some(Expr { + value: ExprValue::FuncCall(name, args), + span: Span::from_two(token.span, end_span), + }); + } + Some(_) => { + let token = self.next().unwrap().clone(); + self.diagnostics.add_from_frontend_error( + ParseError::UnexpectedToken(token.value, "`,` or `)`"), + token.span, + ); + return None; + } + None => { + self.diagnostics.add_from_frontend_error( + ParseError::ExpectButEof("`)`"), + token.span, + ); + return None; + } + } + } + } + Some(Expr { + value: ExprValue::Var(name), + span: token.span, + }) + }, TokenValue::IntLit(value) => Some(Expr { value: ExprValue::IntLit(value), span: token.span, @@ -709,4 +769,4 @@ mod tests { test_case("0-3,14-25"); // test_case("0-3,14-25"); } -} \ No newline at end of file +}