From e233ff1cfc7b1f1231fbd672cd9ecc07af40f05f Mon Sep 17 00:00:00 2001 From: Alek Ratzloff Date: Fri, 8 May 2020 16:19:01 -0400 Subject: [PATCH] Clean up warnings, update next_body, add more tests Signed-off-by: Alek Ratzloff --- src/main.rs | 36 +----------- src/syn/lexer.rs | 1 + src/syn/parser.rs | 137 +++++++++++++++++++++++++++++----------------- src/syn/span.rs | 6 +- 4 files changed, 95 insertions(+), 85 deletions(-) diff --git a/src/main.rs b/src/main.rs index eb5de2e..af57342 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,9 +3,7 @@ mod syn; use std::{ convert::TryFrom, fs, - io::{stdout, Write}, - path::{Path, PathBuf}, - process, + path::PathBuf, }; use structopt::StructOpt; @@ -34,35 +32,7 @@ fn main() -> Result<()> { let opt = Options::from_args(); let text = fs::read_to_string(&opt.input)?; - let parser = Parser::try_from(text.as_str())?; - /* - let object = assemble::assemble_path(&opt.input)?; - - if opt.compile_only { - let outfile = opt.out.clone().unwrap_or_else(|| { - let mut outfile = opt.input.clone(); - assert!(outfile.set_extension("obj")); - outfile - }); - let bytes = object.to_bytes(); - let mut writer = get_writer(&outfile)?; - writer.write(&bytes)?; - Ok(()) - } else if opt.disassemble { - let outfile = opt - .out - .as_ref() - .map(|p| p.as_path()) - .unwrap_or_else(|| Path::new("-")); - let mut writer = get_writer(&outfile)?; - object.disasm(&mut writer)?; - Ok(()) - } else { - let mut state = State::new(); - state.load_object(object, opt.max_mem.unwrap_or(DEFAULT_MAX_MEM))?; - let status = state.exec()?; - process::exit((status & 0xffff_ffff) as i32); - } - */ + let mut parser = Parser::try_from(text.as_str())?; + println!("{:#?}", parser.next_body()?); Ok(()) } diff --git a/src/syn/lexer.rs b/src/syn/lexer.rs index 9e38dfe..8706e97 100644 --- a/src/syn/lexer.rs +++ b/src/syn/lexer.rs @@ -165,6 +165,7 @@ impl<'t> Lexer<'t> { }); }; + let start = self.pos; self.pos.adv_str(token_text); let end = self.pos; diff --git a/src/syn/parser.rs b/src/syn/parser.rs index d2c8795..0f9d915 100644 --- a/src/syn/parser.rs +++ b/src/syn/parser.rs @@ -75,6 +75,20 @@ impl<'t> Parser<'t> { // Statement parsing //////////////////////////////////////////////////////////////////////////////// impl<'t> Parser<'t> { + /// Gets the remaining list of statements in this file, expecting EOF at the end. + pub fn next_body(&mut self) -> Result> { + let body = self.next_block_body()?; + if let Some(token) = self.curr_token { + return Err(Error::ExpectedGot { + expected: "EOF, statement, or expression".to_string(), + got: token.kind().to_string(), + pos: token.span().start, + }); + } + + Ok(body) + } + pub fn next_stmt(&mut self) -> Result> { // skip any leading EOL tokens while self.match_any_token_kind(&EOL)?.is_some() {} @@ -87,7 +101,6 @@ impl<'t> Parser<'t> { let expr = self.next_expr()?; if self.match_token_kind(TokenKind::Eq)?.is_some() { let rhs = self.next_expr()?; - self.expect_eol_or_eof("end-of-line after assignment")?; let span = expr.span().union(rhs.span()); Ok(Some(Stmt::Assign(AssignStmt { lhs: expr, @@ -95,7 +108,6 @@ impl<'t> Parser<'t> { span, }))) } else { - // TODO catch EOF self.expect_eol_or_eof("end-of-line after expression")?; Ok(Some(Stmt::Expr(expr))) } @@ -105,18 +117,20 @@ impl<'t> Parser<'t> { } /// Parses a list of statements until it reaches a right curly brace. - pub fn next_body(&mut self) -> Result> { + fn next_block_body(&mut self) -> Result> { let mut body = Vec::new(); + // end of body token if self.is_token_kind(TokenKind::RBrace) { - // end of body token + self.expect_eol_or_eof("end-of-line after assignment")?; return Ok(body); } while let Some(stmt) = self.next_stmt()? { body.push(stmt); + + // end of body token if self.is_token_kind(TokenKind::RBrace) { - // end of body token break; } } @@ -230,7 +244,10 @@ impl<'t> Parser<'t> { .into() } TokenKind::LBrace => { - let body = self.next_body()?; + // turn on newline parsing because we're going to start parsing statements again + let prev_skip = self.set_skip_newlines(false)?; + let body = self.next_block_body()?; + self.set_skip_newlines(prev_skip)?; let end_token = self.expect_token_kind(TokenKind::RBrace, "end of block (right curly brace)")?; let span = token.span().union(end_token.span()); @@ -266,7 +283,8 @@ impl<'t> Parser<'t> { let mut list = self.next_expr_list(TokenKind::RParen)?; self.set_skip_newlines(prev_skip)?; - let end_token = self.expect_token_kind(TokenKind::RParen, "end of tuple")?; + let end_token = + self.expect_token_kind(TokenKind::RParen, "end of tuple")?; let span = token.span().union(end_token.span()); list.insert(0, first); Expr::Base( @@ -318,11 +336,18 @@ impl<'t> Parser<'t> { // check that the LHS is a tuple of idents, and get the parameters as well. let mut params: Vec; match expr { - Expr::Base(BaseExpr { kind: BaseExprKind::Tuple(ref tuple), .. }) => { + Expr::Base(BaseExpr { + kind: BaseExprKind::Tuple(ref tuple), + .. + }) => { // Multi-parameter case params = Vec::with_capacity(tuple.len()); for param_expr in tuple.iter() { - if let Expr::Base(BaseExpr { kind: BaseExprKind::Ident, span, }) = ¶m_expr { + if let Expr::Base(BaseExpr { + kind: BaseExprKind::Ident, + span, + }) = ¶m_expr + { let name = span.text_at(self.lexer.text()); params.push(name.to_string()); } else { @@ -335,7 +360,10 @@ impl<'t> Parser<'t> { } } } - Expr::Base(BaseExpr { kind: BaseExprKind::Ident, span }) => { + Expr::Base(BaseExpr { + kind: BaseExprKind::Ident, + span, + }) => { // Single parameter case params = vec![span.text_at(self.lexer.text()).to_string()] } @@ -352,13 +380,14 @@ impl<'t> Parser<'t> { // function definition let rhs = self.next_expr()?; let span = expr.span().union(rhs.span()); - // TODO : get params from tuple expr - it's a little funky to do it at this stage but I - // think it will be fine - Ok(Expr::Fun(FunExpr { - params, - expr: rhs, - span, - }.into())) + Ok(Expr::Fun( + FunExpr { + params, + expr: rhs, + span, + } + .into(), + )) } else { Ok(expr) } @@ -799,54 +828,28 @@ mod test { #[test] fn test_fun_expr() { test_parser!( - Parser::try_from( - r#"() -> ()"# - ) - .unwrap(), + Parser::try_from(r#"() -> ()"#).unwrap(), next_expr, - fun_expr( - vec![], - base_expr(BaseExprKind::Tuple(vec![])) - ) + fun_expr(vec![], base_expr(BaseExprKind::Tuple(vec![]))) ); test_parser!( - Parser::try_from( - r#"() -> 1"# - ) - .unwrap(), + Parser::try_from(r#"() -> 1"#).unwrap(), next_expr, - fun_expr( - vec![], - base_expr(BaseExprKind::Num), - ) + fun_expr(vec![], base_expr(BaseExprKind::Num),) ); test_parser!( - Parser::try_from( - r#"(a) -> 1"# - ) - .unwrap(), + Parser::try_from(r#"(a) -> 1"#).unwrap(), next_expr, - fun_expr( - vec![ - String::from("a"), - ], - base_expr(BaseExprKind::Num), - ) + fun_expr(vec![String::from("a"),], base_expr(BaseExprKind::Num),) ); test_parser!( - Parser::try_from( - r#"(a, b) -> a + b"# - ) - .unwrap(), + Parser::try_from(r#"(a, b) -> a + b"#).unwrap(), next_expr, fun_expr( - vec![ - String::from("a"), - String::from("b"), - ], + vec![String::from("a"), String::from("b"),], bin_expr( base_expr(BaseExprKind::Ident), BinOp::Plus, @@ -1170,6 +1173,38 @@ mod test { }) } + #[test] + #[should_panic] + fn test_stray_right_brace_body() { + let mut parser = Parser::try_from( + r" + } + ", + ) + .unwrap(); + parser.next_body().unwrap(); + } + + #[test] + fn test_block_body() { + test_parser!( + Parser::try_from( + r" + a = 1 + b = :sym + foo() + " + ) + .unwrap(), + next_block_body, + vec![ + assign_stmt(base_expr(BaseExprKind::Ident), base_expr(BaseExprKind::Num),), + assign_stmt(base_expr(BaseExprKind::Ident), base_expr(BaseExprKind::Sym),), + Stmt::Expr(fun_call_expr(base_expr(BaseExprKind::Ident), vec![],)) + ] + ); + } + #[test] fn test_assign_stmt() { test_parser!( diff --git a/src/syn/span.rs b/src/syn/span.rs index b347086..d87ee8d 100644 --- a/src/syn/span.rs +++ b/src/syn/span.rs @@ -49,7 +49,11 @@ impl Pos { pub fn next_char(&self, c: char) -> Self { Pos { source: self.source + 1, - line: self.line, + line: if c == '\n' { + self.line + 1 + } else { + self.line + }, col: self.col + 1, byte: self.byte + self.len, len: c.len_utf8(),