Skip to content
Snippets Groups Projects
Commit b02fd143 authored by Linus Palm's avatar Linus Palm
Browse files

Merge branch 'error_handling' into 'main'

Improved error handling

See merge request !1
parents 14e06f87 b271d940
Branches main
1 merge request!1Improved error handling
...@@ -17,13 +17,14 @@ impl<'a> C1Parser<'a> { ...@@ -17,13 +17,14 @@ impl<'a> C1Parser<'a> {
println!("Starting parsing"); println!("Starting parsing");
instance.program().unwrap(); instance.program()
Ok(())
} }
fn program(&mut self) -> ParseResult { fn program(&mut self) -> ParseResult {
self.functiondefinition().unwrap(); while self.lx.current_token().is_some() {
self.functiondefinition()?;
}
Ok(()) Ok(())
} }
...@@ -31,16 +32,14 @@ impl<'a> C1Parser<'a> { ...@@ -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) { 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.lx.eat();
self.check_and_eat_token(C1Token::Identifier).unwrap(); self.check_and_eat_token(C1Token::Identifier)?;
self.check_and_eat_token(C1Token::LeftParenthesis).unwrap(); self.check_and_eat_token(C1Token::LeftParenthesis)?;
self.check_and_eat_token(C1Token::RightParenthesis).unwrap(); self.check_and_eat_token(C1Token::RightParenthesis)?;
self.check_and_eat_token(C1Token::LeftBrace).unwrap(); self.check_and_eat_token(C1Token::LeftBrace)?;
self.statementlist().unwrap(); self.statementlist()?;
self.check_and_eat_token(C1Token::RightBrace).unwrap(); return self.check_and_eat_token(C1Token::RightBrace);
return Ok(());
} }
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 { fn statementlist(&mut self) -> ParseResult {
...@@ -73,7 +72,7 @@ impl<'a> C1Parser<'a> { ...@@ -73,7 +72,7 @@ impl<'a> C1Parser<'a> {
}*/ }*/
while !(self.lx.current_token() == Some(C1Token::RightBrace)) { while !(self.lx.current_token() == Some(C1Token::RightBrace)) {
self.block().unwrap(); self.block()?;
} }
Ok(()) Ok(())
...@@ -82,140 +81,130 @@ impl<'a> C1Parser<'a> { ...@@ -82,140 +81,130 @@ impl<'a> C1Parser<'a> {
fn block(&mut self) -> ParseResult { fn block(&mut self) -> ParseResult {
print!("block->"); print!("block->");
if self.lx.current_token() == Some(C1Token::LeftBrace){ if self.lx.current_token() == Some(C1Token::LeftBrace){
self.check_and_eat_token(C1Token::LeftBrace).unwrap(); self.check_and_eat_token(C1Token::LeftBrace)?;
self.statementlist().unwrap(); self.statementlist()?;
self.check_and_eat_token(C1Token::RightBrace).unwrap(); return self.check_and_eat_token(C1Token::RightBrace);
}else{ }else{
self.statement().unwrap(); return self.statement();
} }
Ok(())
} }
fn statement(&mut self) -> ParseResult { fn statement(&mut self) -> ParseResult {
print!("statement->"); print!("statement->");
match self.lx.current_token() { match self.lx.current_token() {
Some(C1Token::KwIf) => { Some(C1Token::KwIf) => {
self.ifstatement().unwrap(); return self.ifstatement();
Ok(())
}, },
Some(C1Token::KwReturn) => { Some(C1Token::KwReturn) => {
self.returnstatement().unwrap(); self.returnstatement()?;
self.check_and_eat_token(C1Token::Semicolon).unwrap(); return self.check_and_eat_token(C1Token::Semicolon);
Ok(())
}, },
Some(C1Token::KwPrintf) => { Some(C1Token::KwPrintf) => {
self.printfstatement().unwrap(); self.printfstatement()?;
self.check_and_eat_token(C1Token::Semicolon).unwrap(); return self.check_and_eat_token(C1Token::Semicolon);
Ok(())
}, },
Some(C1Token::Identifier) => { Some(C1Token::Identifier) => {
if self.lx.peek_token() == Some(C1Token::Assign) { if self.lx.peek_token() == Some(C1Token::Assign) {
self.statassignment().unwrap(); self.statassignment()?;
self.check_and_eat_token(C1Token::Semicolon).unwrap(); return self.check_and_eat_token(C1Token::Semicolon);
}else{ }else{
self.functioncall().unwrap(); self.functioncall()?;
self.check_and_eat_token(C1Token::Semicolon).unwrap(); 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 { fn functioncall(&mut self) -> ParseResult {
print!("functioncall->"); print!("functioncall->");
self.check_and_eat_token(C1Token::Identifier).unwrap(); self.check_and_eat_token(C1Token::Identifier)?;
self.check_and_eat_token(C1Token::LeftParenthesis).unwrap(); self.check_and_eat_token(C1Token::LeftParenthesis)?;
self.check_and_eat_token(C1Token::RightParenthesis).unwrap(); self.check_and_eat_token(C1Token::RightParenthesis)
Ok(())
} }
fn statassignment(&mut self) -> ParseResult { fn statassignment(&mut self) -> ParseResult {
print!("statassignment->"); print!("statassignment->");
self.check_and_eat_token(C1Token::Identifier).unwrap(); self.check_and_eat_token(C1Token::Identifier)?;
self.check_and_eat_token(C1Token::Assign).unwrap(); self.check_and_eat_token(C1Token::Assign)?;
self.assignment().unwrap(); self.assignment()
Ok(())
} }
fn returnstatement(&mut self) -> ParseResult { fn returnstatement(&mut self) -> ParseResult {
print!("returnstatement->"); print!("returnstatement->");
self.check_and_eat_token(C1Token::KwReturn).unwrap(); self.check_and_eat_token(C1Token::KwReturn)?;
self.assignment(); //TODO: Maybe? if self.lx.current_token() == Some(C1Token::Semicolon) {
Ok(()) return Ok(());
}
self.assignment()
} }
fn printfstatement(&mut self) -> ParseResult { fn printfstatement(&mut self) -> ParseResult {
print!("printfstatement->"); print!("printfstatement->");
self.check_and_eat_token(C1Token::KwPrintf).unwrap(); self.check_and_eat_token(C1Token::KwPrintf)?;
self.check_and_eat_token(C1Token::LeftParenthesis).unwrap(); self.check_and_eat_token(C1Token::LeftParenthesis)?;
self.assignment().unwrap(); self.assignment()?;
self.check_and_eat_token(C1Token::RightParenthesis).unwrap(); self.check_and_eat_token(C1Token::RightParenthesis)
Ok(())
} }
fn ifstatement(&mut self) -> ParseResult { fn ifstatement(&mut self) -> ParseResult {
print!("ifstatement->"); print!("ifstatement->");
self.check_and_eat_token(C1Token::KwIf).unwrap(); self.check_and_eat_token(C1Token::KwIf)?;
self.check_and_eat_token(C1Token::LeftParenthesis).unwrap(); self.check_and_eat_token(C1Token::LeftParenthesis)?;
self.assignment().unwrap(); self.assignment()?;
//TODO: self.check_and_eat_token(C1Token::RightParenthesis).unwrap(); self.check_and_eat_token(C1Token::RightParenthesis)?;
self.block().unwrap(); self.block()
Ok(())
} }
fn assignment(&mut self) -> ParseResult { fn assignment(&mut self) -> ParseResult {
print!("assignment->"); print!("assignment->");
println!("test: {:?} {:?}", self.lx.current_text(), self.lx.peek_text()); 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) { 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::Identifier)?;
self.check_and_eat_token(C1Token::Assign).unwrap(); self.check_and_eat_token(C1Token::Assign)?;
self.assignment().unwrap(); self.assignment()
return Ok(());
}else{ }else{
println!("assignment: Not Identifier"); println!("assignment: Not Identifier");
self.expr().unwrap(); self.expr()
return Ok(());
} }
} }
fn expr(&mut self) -> ParseResult { fn expr(&mut self) -> ParseResult {
print!("expr->"); print!("expr->");
self.simpexpr().unwrap(); self.simpexpr()?;
let tk = self.lx.current_token(); 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) { 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.lx.eat();
self.simpexpr().unwrap(); self.simpexpr()?;
}else{
return Ok(());
} }
self.check_and_eat_token(C1Token::RightParenthesis).unwrap();
Ok(()) Ok(())
} }
fn simpexpr(&mut self) -> ParseResult { fn simpexpr(&mut self) -> ParseResult {
print!("simpexpr->"); print!("simpexpr->");
if self.lx.current_token() == Some(C1Token::Minus){ 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) { 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.lx.eat();
self.term().unwrap(); self.term()?;
} }
Ok(()) Ok(())
} }
fn term(&mut self) -> ParseResult { fn term(&mut self) -> ParseResult {
print!("term->"); 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) { 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.lx.eat();
self.factor().unwrap(); self.factor()?;
} }
Ok(()) Ok(())
} }
...@@ -227,37 +216,32 @@ impl<'a> C1Parser<'a> { ...@@ -227,37 +216,32 @@ impl<'a> C1Parser<'a> {
match self.lx.current_token() { match self.lx.current_token() {
Some(C1Token::ConstInt) => { Some(C1Token::ConstInt) => {
self.check_and_eat_token(C1Token::ConstInt).unwrap(); self.check_and_eat_token(C1Token::ConstInt)
Ok(())
}, },
Some(C1Token::ConstFloat) => { Some(C1Token::ConstFloat) => {
self.check_and_eat_token(C1Token::ConstFloat).unwrap(); self.check_and_eat_token(C1Token::ConstFloat)
Ok(())
}, },
Some(C1Token::ConstBoolean) => { Some(C1Token::ConstBoolean) => {
self.check_and_eat_token(C1Token::ConstBoolean).unwrap(); self.check_and_eat_token(C1Token::ConstBoolean)
Ok(())
}, },
Some(C1Token::Identifier) => { Some(C1Token::Identifier) => {
if self.lx.peek_token() == Some(C1Token::LeftParenthesis) { if self.lx.peek_token() == Some(C1Token::LeftParenthesis) {
self.functioncall().unwrap(); return self.functioncall();
}else{ }else{
self.check_and_eat_token(C1Token::Identifier).unwrap(); return self.check_and_eat_token(C1Token::Identifier);
} }
Ok(())
}, },
Some(C1Token::LeftParenthesis) => { Some(C1Token::LeftParenthesis) => {
print!("factor left parenthesis->"); print!("factor left parenthesis->");
self.check_and_eat_token(C1Token::LeftParenthesis).unwrap(); self.check_and_eat_token(C1Token::LeftParenthesis)?;
self.assignment().unwrap(); self.assignment()?;
self.check_and_eat_token(C1Token::RightParenthesis).unwrap(); self.check_and_eat_token(C1Token::RightParenthesis)?;
Ok(()) 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> { ...@@ -267,7 +251,7 @@ impl<'a> C1Parser<'a> {
if self.lx.current_token() == Some(token) { if self.lx.current_token() == Some(token) {
Ok(()) Ok(())
} else { } 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> { ...@@ -281,7 +265,7 @@ impl<'a> C1Parser<'a> {
return Ok(()); return Ok(());
} }
println!("Wrong: {:?}", x); 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()), None => Err("No token".to_owned()),
} }
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment