From b271d940594e3f875195ab1e6d8295e04acbb88c Mon Sep 17 00:00:00 2001 From: Linus Palm <linuspalmde@gmail.com> Date: Wed, 15 Jun 2022 16:00:11 +0200 Subject: [PATCH] Improved error handling --- src/C1_parser.rs | 158 +++++++++++++++++++++-------------------------- 1 file changed, 71 insertions(+), 87 deletions(-) diff --git a/src/C1_parser.rs b/src/C1_parser.rs index 127809a..1cb3c75 100644 --- a/src/C1_parser.rs +++ b/src/C1_parser.rs @@ -17,13 +17,14 @@ impl<'a> C1Parser<'a> { println!("Starting parsing"); - instance.program().unwrap(); - - Ok(()) + instance.program() } fn program(&mut self) -> ParseResult { - self.functiondefinition().unwrap(); + while self.lx.current_token().is_some() { + self.functiondefinition()?; + } + Ok(()) } @@ -31,16 +32,14 @@ impl<'a> C1Parser<'a> { if self.lx.current_token() == Some(C1Token::KwInt) || self.lx.current_token() == Some(C1Token::KwVoid) || self.lx.current_token() == Some(C1Token::KwBoolean) || self.lx.current_token() == Some(C1Token::KwFloat) { self.lx.eat(); - self.check_and_eat_token(C1Token::Identifier).unwrap(); - self.check_and_eat_token(C1Token::LeftParenthesis).unwrap(); - self.check_and_eat_token(C1Token::RightParenthesis).unwrap(); - self.check_and_eat_token(C1Token::LeftBrace).unwrap(); - self.statementlist().unwrap(); - self.check_and_eat_token(C1Token::RightBrace).unwrap(); - - return Ok(()); + self.check_and_eat_token(C1Token::Identifier)?; + self.check_and_eat_token(C1Token::LeftParenthesis)?; + self.check_and_eat_token(C1Token::RightParenthesis)?; + self.check_and_eat_token(C1Token::LeftBrace)?; + self.statementlist()?; + return self.check_and_eat_token(C1Token::RightBrace); } - return Err(format!("Expected token group 'type' but found {:?}", self.lx.current_token())); + return Err(format!("Expected token group 'type' in line {} but found {:?}", self.lx.current_line_number().unwrap(), self.lx.current_token())); } fn statementlist(&mut self) -> ParseResult { @@ -73,7 +72,7 @@ impl<'a> C1Parser<'a> { }*/ while !(self.lx.current_token() == Some(C1Token::RightBrace)) { - self.block().unwrap(); + self.block()?; } Ok(()) @@ -82,140 +81,130 @@ impl<'a> C1Parser<'a> { fn block(&mut self) -> ParseResult { print!("block->"); if self.lx.current_token() == Some(C1Token::LeftBrace){ - self.check_and_eat_token(C1Token::LeftBrace).unwrap(); - self.statementlist().unwrap(); - self.check_and_eat_token(C1Token::RightBrace).unwrap(); + self.check_and_eat_token(C1Token::LeftBrace)?; + self.statementlist()?; + return self.check_and_eat_token(C1Token::RightBrace); }else{ - self.statement().unwrap(); + return self.statement(); } - Ok(()) } fn statement(&mut self) -> ParseResult { print!("statement->"); match self.lx.current_token() { Some(C1Token::KwIf) => { - self.ifstatement().unwrap(); - Ok(()) + return self.ifstatement(); }, Some(C1Token::KwReturn) => { - self.returnstatement().unwrap(); - self.check_and_eat_token(C1Token::Semicolon).unwrap(); - Ok(()) + self.returnstatement()?; + return self.check_and_eat_token(C1Token::Semicolon); }, Some(C1Token::KwPrintf) => { - self.printfstatement().unwrap(); - self.check_and_eat_token(C1Token::Semicolon).unwrap(); - Ok(()) + self.printfstatement()?; + return self.check_and_eat_token(C1Token::Semicolon); }, Some(C1Token::Identifier) => { if self.lx.peek_token() == Some(C1Token::Assign) { - self.statassignment().unwrap(); - self.check_and_eat_token(C1Token::Semicolon).unwrap(); + self.statassignment()?; + return self.check_and_eat_token(C1Token::Semicolon); }else{ - self.functioncall().unwrap(); - self.check_and_eat_token(C1Token::Semicolon).unwrap(); + self.functioncall()?; + return self.check_and_eat_token(C1Token::Semicolon); } - Ok(()) }, - _ => Err(format!("Expected token group 'statement' but found {:?}", self.lx.current_token().unwrap())), + _ => Err(format!("Expected token group 'statement' in line {} but found {:?}", self.lx.current_line_number().unwrap(), self.lx.current_token().unwrap())), } } fn functioncall(&mut self) -> ParseResult { print!("functioncall->"); - self.check_and_eat_token(C1Token::Identifier).unwrap(); - self.check_and_eat_token(C1Token::LeftParenthesis).unwrap(); - self.check_and_eat_token(C1Token::RightParenthesis).unwrap(); - Ok(()) + self.check_and_eat_token(C1Token::Identifier)?; + self.check_and_eat_token(C1Token::LeftParenthesis)?; + self.check_and_eat_token(C1Token::RightParenthesis) } fn statassignment(&mut self) -> ParseResult { print!("statassignment->"); - self.check_and_eat_token(C1Token::Identifier).unwrap(); - self.check_and_eat_token(C1Token::Assign).unwrap(); - self.assignment().unwrap(); - Ok(()) + self.check_and_eat_token(C1Token::Identifier)?; + self.check_and_eat_token(C1Token::Assign)?; + self.assignment() } fn returnstatement(&mut self) -> ParseResult { print!("returnstatement->"); - self.check_and_eat_token(C1Token::KwReturn).unwrap(); - self.assignment(); //TODO: Maybe? - Ok(()) + self.check_and_eat_token(C1Token::KwReturn)?; + if self.lx.current_token() == Some(C1Token::Semicolon) { + return Ok(()); + } + + self.assignment() } fn printfstatement(&mut self) -> ParseResult { print!("printfstatement->"); - self.check_and_eat_token(C1Token::KwPrintf).unwrap(); - self.check_and_eat_token(C1Token::LeftParenthesis).unwrap(); - self.assignment().unwrap(); - self.check_and_eat_token(C1Token::RightParenthesis).unwrap(); - Ok(()) + self.check_and_eat_token(C1Token::KwPrintf)?; + self.check_and_eat_token(C1Token::LeftParenthesis)?; + self.assignment()?; + self.check_and_eat_token(C1Token::RightParenthesis) } fn ifstatement(&mut self) -> ParseResult { print!("ifstatement->"); - self.check_and_eat_token(C1Token::KwIf).unwrap(); - self.check_and_eat_token(C1Token::LeftParenthesis).unwrap(); - self.assignment().unwrap(); - //TODO: self.check_and_eat_token(C1Token::RightParenthesis).unwrap(); - self.block().unwrap(); - Ok(()) + self.check_and_eat_token(C1Token::KwIf)?; + self.check_and_eat_token(C1Token::LeftParenthesis)?; + self.assignment()?; + self.check_and_eat_token(C1Token::RightParenthesis)?; + self.block() } fn assignment(&mut self) -> ParseResult { print!("assignment->"); println!("test: {:?} {:?}", self.lx.current_text(), self.lx.peek_text()); if self.lx.current_token() == Some(C1Token::Identifier) && self.lx.peek_token() == Some(C1Token::Assign) { - self.check_and_eat_token(C1Token::Identifier).unwrap(); - self.check_and_eat_token(C1Token::Assign).unwrap(); - self.assignment().unwrap(); - return Ok(()); + self.check_and_eat_token(C1Token::Identifier)?; + self.check_and_eat_token(C1Token::Assign)?; + self.assignment() }else{ println!("assignment: Not Identifier"); - self.expr().unwrap(); - return Ok(()); + self.expr() } } fn expr(&mut self) -> ParseResult { print!("expr->"); - self.simpexpr().unwrap(); + self.simpexpr()?; let tk = self.lx.current_token(); if tk == Some(C1Token::Equal) || tk == Some(C1Token::NotEqual) || tk == Some(C1Token::Less) || tk == Some(C1Token::LessEqual) || tk == Some(C1Token::Greater) || tk == Some(C1Token::GreaterEqual) { self.lx.eat(); - self.simpexpr().unwrap(); - }else{ - return Ok(()); + self.simpexpr()?; } - self.check_and_eat_token(C1Token::RightParenthesis).unwrap(); + Ok(()) } fn simpexpr(&mut self) -> ParseResult { print!("simpexpr->"); if self.lx.current_token() == Some(C1Token::Minus){ - self.check_and_eat_token(C1Token::Minus).unwrap(); + self.check_and_eat_token(C1Token::Minus)?; } - self.term().unwrap(); + self.term()?; while self.lx.current_token() == Some(C1Token::Plus) || self.lx.current_token() == Some(C1Token::Minus) || self.lx.current_token() == Some(C1Token::Or) { self.lx.eat(); - self.term().unwrap(); + self.term()?; } Ok(()) } fn term(&mut self) -> ParseResult { print!("term->"); - self.factor().unwrap(); + self.factor()?; while self.lx.current_token() == Some(C1Token::Asterisk) || self.lx.current_token() == Some(C1Token::Slash) || self.lx.current_token() == Some(C1Token::And) { self.lx.eat(); - self.factor().unwrap(); + self.factor()?; } Ok(()) } @@ -227,37 +216,32 @@ impl<'a> C1Parser<'a> { match self.lx.current_token() { Some(C1Token::ConstInt) => { - self.check_and_eat_token(C1Token::ConstInt).unwrap(); - Ok(()) + self.check_and_eat_token(C1Token::ConstInt) }, Some(C1Token::ConstFloat) => { - self.check_and_eat_token(C1Token::ConstFloat).unwrap(); - Ok(()) + self.check_and_eat_token(C1Token::ConstFloat) }, Some(C1Token::ConstBoolean) => { - self.check_and_eat_token(C1Token::ConstBoolean).unwrap(); - Ok(()) + self.check_and_eat_token(C1Token::ConstBoolean) }, Some(C1Token::Identifier) => { if self.lx.peek_token() == Some(C1Token::LeftParenthesis) { - self.functioncall().unwrap(); + return self.functioncall(); }else{ - self.check_and_eat_token(C1Token::Identifier).unwrap(); + return self.check_and_eat_token(C1Token::Identifier); } - - Ok(()) }, Some(C1Token::LeftParenthesis) => { print!("factor left parenthesis->"); - self.check_and_eat_token(C1Token::LeftParenthesis).unwrap(); - self.assignment().unwrap(); - self.check_and_eat_token(C1Token::RightParenthesis).unwrap(); + self.check_and_eat_token(C1Token::LeftParenthesis)?; + self.assignment()?; + self.check_and_eat_token(C1Token::RightParenthesis)?; Ok(()) }, - _ => Err(format!("Expected token group 'factor' but found {:?}", self.lx.current_token().unwrap())), + _ => Err(format!("Expected token group 'factor' in line {} but found {:?}", self.lx.current_line_number().unwrap(), self.lx.current_token().unwrap())), } } @@ -267,7 +251,7 @@ impl<'a> C1Parser<'a> { if self.lx.current_token() == Some(token) { Ok(()) } else { - Err(format!("Expected token {:?}", token)) + Err(format!("Expected token {:?} in line {}", token, self.lx.current_line_number().unwrap())) } } @@ -281,7 +265,7 @@ impl<'a> C1Parser<'a> { return Ok(()); } println!("Wrong: {:?}", x); - return Err(format!("Expected token {:?} but found {:?}", token, x)); + return Err(format!("Expected token {:?} in line {} but found {:?}", token, self.lx.current_line_number().unwrap(), x)); }, None => Err("No token".to_owned()), } -- GitLab