Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • compilerbau-sose22-ag28/cb-3
1 result
Show changes
Commits on Source (2)
......@@ -131,7 +131,7 @@ pub enum C1Token {
#[regex(r"[ \t\f]+", logos::skip)]
Whitespace,
#[regex(r"[\n]")]
#[regex(r"(\r\n|\r|\n)")]
Linebreak,
// Logos requires one token variant to handle errors,
......
mod lexer;
mod parser;
// Type definition for the Result that is being used by the parser. You may change it to anything
// you want
......@@ -8,5 +9,4 @@ pub use lexer::C1Lexer;
pub use lexer::C1Token;
// You will need a re-export of your C1Parser definition. Here is an example:
// mod parser;
// pub use parser::C1Parser;
pub use parser::C1Parser;
use crate::{C1Lexer, C1Token, ParseResult};
pub struct C1Parser<'a> {
lx: C1Lexer<'a>,
}
impl C1Parser<'_> {
pub fn parse(text: &'_ str) -> ParseResult {
let mut parser: C1Parser = C1Parser { lx: C1Lexer::new(text) };
return Ok(parser.program());
}
fn program(&mut self) {
while self.lx.current_token().is_some() {
let _ = self.functiondefinition();
}
}
fn functiondefinition(&mut self) -> ParseResult {
self.statement_type()?;
self.check_and_eat_token(Some(C1Token::Identifier))?;
self.check_and_eat_token(Some(C1Token::LeftParenthesis))?;
self.check_and_eat_token(Some(C1Token::RightParenthesis))?;
self.check_and_eat_token(Some(C1Token::LeftBrace))?;
self.statementlist()?;
self.check_and_eat_token(Some(C1Token::RightBrace))
}
fn statement_type(&mut self) -> ParseResult {
return match self.lx.current_token() {
Some(C1Token::KwBoolean) | Some(C1Token::KwFloat) | Some(C1Token::KwInt) | Some(C1Token::KwVoid) => {
self.eat();
Result::Ok(())
},
_ => Result::Err(self.error_format()),
};
}
fn statementlist(&mut self) -> ParseResult {
print!("statementlist->");
if self.lx.current_token() == Some(C1Token::RightBrace) {
return Result::Ok(());
}
self.block()?;
self.statementlist()
}
fn block(&mut self) -> ParseResult {
print!("block->");
if self.current_matches(C1Token::LeftBrace) {
self.eat();
self.statementlist()?;
return self.check_and_eat_token(Some(C1Token::RightBrace));
}
self.statement()
}
fn statement(&mut self) -> ParseResult {
print!("statement->");
return match self.lx.current_token() {
Some(C1Token::KwIf) => self.ifstatement(),
Some(C1Token::KwReturn) => {
self.returnstatement()?;
self.check_and_eat_token(Some(C1Token::Semicolon))
},
Some(C1Token::KwPrintf) => {
self.printfstatement()?;
self.check_and_eat_token(Some(C1Token::Semicolon))
},
Some(C1Token::Identifier) => {
if self.next_matches(C1Token::LeftParenthesis) {
self.functioncall()?;
return self.check_and_eat_token(Some(C1Token::Semicolon));
} else if self.next_matches(C1Token::Assign) {
self.statassignment()?;
return self.check_and_eat_token(Some(C1Token::Semicolon));
}
Result::Err(self.error_format())
},
_ => Result::Err(self.error_format()),
};
}
fn ifstatement(&mut self) -> ParseResult {
self.check_and_eat_token(Some(C1Token::KwIf))?;
self.check_and_eat_token(Some(C1Token::LeftParenthesis))?;
self.assignment()?;
self.check_and_eat_token(Some(C1Token::RightParenthesis))?;
self.block()
}
fn returnstatement(&mut self) -> ParseResult {
self.check_and_eat_token(Some(C1Token::KwReturn))?;
self.returnstatement_alt()
}
fn returnstatement_alt(&mut self) -> ParseResult {
if self.current_matches(C1Token::Semicolon) {
return Result::Ok(());
};
self.assignment()
}
fn printfstatement(&mut self) -> ParseResult {
self.check_and_eat_token(Some(C1Token::KwPrintf))?;
self.check_and_eat_token(Some(C1Token::LeftParenthesis))?;
self.assignment()?;
self.check_and_eat_token(Some(C1Token::RightParenthesis))
}
fn statassignment(&mut self) -> ParseResult {
self.check_and_eat_token(Some(C1Token::Identifier))?;
self.check_and_eat_token(Some(C1Token::Assign))?;
self.assignment()
}
fn functioncall(&mut self) -> ParseResult {
self.check_and_eat_token(Some(C1Token::Identifier))?;
self.check_and_eat_token(Some(C1Token::LeftParenthesis))?;
self.check_and_eat_token(Some(C1Token::RightParenthesis))
}
fn assignment(&mut self) -> ParseResult {
if self.current_matches(C1Token::Identifier) {
if self.next_matches(C1Token::Assign) {
return self.assignment();
}
}
self.expr()
}
fn expr(&mut self) -> ParseResult {
print!("simplexpr->");
self.simpexpr()?;
self.expr_2()
}
fn expr_2(&mut self) -> ParseResult {
if self.current_matches(C1Token::Semicolon) || self.current_matches(C1Token::RightParenthesis) {
return Result::Ok(());
}
self.compare()?;
self.simpexpr()
}
fn compare(&mut self) -> ParseResult {
return match self.lx.current_token() {
Some(C1Token::Equal) | Some(C1Token::NotEqual) | Some(C1Token::Less) | Some(C1Token::LessEqual) | Some(C1Token::GreaterEqual) | Some(C1Token::Greater) => {
self.eat();
Result::Ok(())
},
_ => Result::Err(self.error_format()),
}
}
fn simpexpr(&mut self) -> ParseResult {
self.minus()?;
self.term()?;
self.simpexpr_2()
}
fn simpexpr_2(&mut self) -> ParseResult {
match self.lx.current_token() {
Some(C1Token::Plus) | Some(C1Token::Minus) | Some(C1Token::Or) => {
self.lowop()?;
self.term()?;
self.simpexpr_2()
},
_ => Result::Ok(()),
}
}
fn minus(&mut self) -> ParseResult {
if self.current_matches(C1Token::Minus) {
self.eat();
};
return Result::Ok(());
}
fn lowop(&mut self) -> ParseResult {
return match self.lx.current_token() {
Some(C1Token::Plus) | Some(C1Token::Minus) | Some(C1Token::Or) => {
self.eat();
Result::Ok(())
},
_ => Result::Err(self.error_format()),
};
}
fn term(&mut self) -> ParseResult {
self.factor()?;
self.term_2()
}
fn term_2(&mut self) -> ParseResult {
return match self.lx.current_token() {
Some(C1Token::Asterisk) | Some(C1Token::Slash) | Some(C1Token::And) => {
self.highop()?;
self.factor()?;
self.term_2()
},
_ => Result::Ok(()),
}
}
fn highop(&mut self) -> ParseResult {
return match self.lx.current_token() {
Some(C1Token::Asterisk) | Some(C1Token::Slash) | Some(C1Token::And) => {
self.eat();
Result::Ok(())
},
_ => Result::Err(self.error_format()),
};
}
fn factor(&mut self) -> ParseResult {
print!("factor->");
return match self.lx.current_token() {
Some(C1Token::ConstFloat) | Some(C1Token::ConstInt) | Some(C1Token::ConstBoolean) => {
self.eat();
Result::Ok(())
},
Some(C1Token::Identifier) => {
if self.next_matches(C1Token::LeftParenthesis) {
return self.functioncall();
}
self.eat();
Result::Ok(())
},
Some(C1Token::LeftParenthesis) => {
self.eat();
self.assignment()?;
self.check_and_eat_token(Some(C1Token::RightParenthesis))
},
_ => Result::Err(self.error_format()),
}
}
//konsumiert aktuelles Token
fn eat(&mut self) {
self.lx.eat();
}
//Fehler wird zurückgegeben
fn error_format(&self) -> String {
return format!("Error on line: {}", self.lx.current_line_number().unwrap());
}
//überprüft, ob das ihr übergebene Token gleich dem aktuellen
fn check_and_eat_token(&mut self, token: Option<C1Token>) -> ParseResult {
if self.lx.current_token() == token {
self.eat();
return Result::Ok(());
}
return Result::Err(self.error_format());
}
//wie check_and_eat_token, gibt Vergleich zurück
fn current_matches(&mut self, token: C1Token) -> bool {
self.lx.current_token() == Some(token)
}
//wie check_and_eat_token für nächstes Token, gibt Vergleich zurück
fn next_matches(&mut self, token: C1Token) -> bool {
self.lx.peek_token() == Some(token)
}
}
\ No newline at end of file