From c6e5a5d686739012365e62c97e9bced3c676aa7e Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun, 31 Oct 2021 12:29:17 +0100 Subject: [PATCH] fix top level --- grammar.txt | 6 +++-- src/ast.rs | 2 +- src/lib.rs | 25 +++++++++++--------- src/parse.rs | 64 +++++++++++++++++++++++++++++++++++++++------------- test.sl | 10 +------- 5 files changed, 68 insertions(+), 39 deletions(-) diff --git a/grammar.txt b/grammar.txt index 6db35bc..a124c5c 100644 --- a/grammar.txt +++ b/grammar.txt @@ -1,9 +1,11 @@ # todo: calls (property access and function calls) - ::= + ::= - ::= "{" { } "}" + ::= { } + + ::= "{" "}" ::= | diff --git a/src/ast.rs b/src/ast.rs index 502f9cd..a7fa4d7 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -8,7 +8,7 @@ use crate::errors::Span; pub type Symbol = String; #[derive(Debug, Clone, PartialEq)] -pub struct Program(pub Block); +pub struct Program(pub Vec); #[derive(Debug, Clone, PartialEq)] pub struct Block(pub Vec); diff --git a/src/lib.rs b/src/lib.rs index 091f944..0a39e24 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,24 +7,27 @@ mod parse; pub fn run_program(program: &str) { let lexer = lex::Lexer::lex(program); let (success, errors) = lexer.partition::, _>(|result| result.is_ok()); - // - // // terrible, but works - // let tokens = success.into_iter().collect::>(); - // let _ast = parse::parse(tokens.unwrap()); if errors.is_empty() { + let tokens = success.into_iter().collect::, _>>().unwrap(); + println!( - "{:#?}", - success - .into_iter() - .map(Result::unwrap) - .map(|token| token.kind) - .collect::>() + "{:?}", + tokens.iter().map(|token| &token.kind).collect::>() ); + + let ast = parse::parse(tokens); + + match ast { + Ok(ast) => println!("{:#?}", ast), + Err(err) => { + eprintln!("{:?}", err) + } + } } else { errors .into_iter() .map(Result::unwrap_err) - .for_each(|err| crate::errors::display_error(program, err)); + .for_each(|err| errors::display_error(program, err)); } } diff --git a/src/parse.rs b/src/parse.rs index ef483e8..9eca7c4 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -35,25 +35,25 @@ macro_rules! parse_bin_op { impl<'code> Parser<'code> { fn program(&mut self) -> ParseResult<'code, Program> { - Ok(Program(self.block()?)) + Ok(Program(self.statement_list()?)) } - fn block(&mut self) -> ParseResult<'code, Block> { + fn statement_list(&mut self) -> ParseResult<'code, Vec> { let mut stmts = Vec::new(); loop { - if let Some(Token { - kind: TokenType::BraceC, - .. - }) = self.peek() - { + if let Some(TokenType::BraceC) | None = self.peek().map(|token| &token.kind) { let _ = self.next(); - return Ok(Block(stmts)); + return Ok(stmts); } let stmt = self.statement()?; stmts.push(stmt); } } + fn block(&mut self) -> ParseResult<'code, Block> { + Ok(Block(self.statement_list()?)) + } + fn statement(&mut self) -> ParseResult<'code, Stmt> { let expr = self.expression()?; self.expect(TokenType::Semi)?; @@ -167,13 +167,12 @@ impl<'code> Parser<'code> { kind: UnaryOpKind::Neg, }))) } - Some(_) => self.primary(), - None => todo!(), + _ => self.primary(), } } fn primary(&mut self) -> ParseResult<'code, Expr> { - let next = self.next().ok_or(ParseErr::EOF)?; + let next = self.next().ok_or(ParseErr::EOF("primary"))?; 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))), @@ -194,7 +193,7 @@ impl<'code> Parser<'code> { fn array_literal(&mut self, open_span: Span) -> ParseResult<'code, Expr> { let mut elements = Vec::new(); - while self.peek().ok_or(ParseErr::EOF)?.kind != TokenType::BracketC { + while self.peek().ok_or(ParseErr::EOF("array literal"))?.kind != TokenType::BracketC { let expr = self.expression()?; elements.push(expr); self.expect(TokenType::Comma)?; @@ -226,7 +225,7 @@ impl<'code> Parser<'code> { Err(ParseErr::MismatchedKind { expected: kind }) } } else { - Err(ParseErr::EOF) + Err(ParseErr::ExpectedToken(kind)) } } } @@ -234,8 +233,8 @@ impl<'code> Parser<'code> { #[derive(Debug)] pub enum ParseErr<'code> { MismatchedKind { expected: TokenType<'code> }, - InvalidToken(TokenType<'code>), - EOF, + ExpectedToken(TokenType<'code>), + EOF(&'static str), } impl CompilerError for ParseErr<'_> { @@ -260,7 +259,7 @@ mod test { mod prelude { pub(super) use super::{parser, test_literal_bin_op, test_number_literal, token}; - pub(super) use crate::ast::{BinaryOpKind, Expr, Literal}; + pub(super) use crate::ast::{BinaryOp, BinaryOpKind, Expr, Literal}; pub(super) use crate::errors::Span; pub(super) use crate::lex::{Token, TokenType}; } @@ -304,6 +303,39 @@ mod test { assert_eq!(Expr::Literal(Literal::Number(10.0, Span::dummy())), unary); } + mod expr { + use super::prelude::*; + use TokenType::*; + + fn parse_expr(tokens: Vec) -> Expr { + let mut parser = parser(tokens); + parser.expression().unwrap() + } + + #[test] + fn add_multiply() { + let tokens = [Number(10.0), Plus, Number(20.0), Asterisk, Number(100.0)] + .map(token) + .into(); + let expr = parse_expr(tokens); + assert_eq!( + Expr::BinaryOp(Box::new(BinaryOp { + span: Span::dummy(), + lhs: Expr::Literal(Literal::Number(10.0, Span::dummy())), + rhs: Expr::BinaryOp(Box::new(BinaryOp { + span: Span::dummy(), + lhs: Expr::Literal(Literal::Number(20.0, Span::dummy())), + rhs: Expr::Literal(Literal::Number(100.0, Span::dummy())), + + kind: BinaryOpKind::Mul + })), + kind: BinaryOpKind::Add + })), + expr + ); + } + } + mod logical_or { use super::prelude::*; diff --git a/test.sl b/test.sl index 00b3654..f020cd3 100644 --- a/test.sl +++ b/test.sl @@ -1,9 +1 @@ -fn main() { - let number = 57234875; - let number2 = 5325; - let is_equal = number == number2; - - if !is_equal { - - } -} +1 + 2 * 10; \ No newline at end of file