From 891f0b3d601c881716df8b1b3aadb0e27fc4d488 Mon Sep 17 00:00:00 2001
From: "freidlan@informatik.hu-berlin.de" <freidlan@informatik.hu-berlin.de>
Date: Wed, 15 Jun 2022 22:14:31 +0200
Subject: [PATCH] =?UTF-8?q?L=C3=B6sung?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/lexer.rs  |   2 +-
 src/lib.rs    |   4 +-
 src/parser.rs | 272 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 275 insertions(+), 3 deletions(-)
 create mode 100644 src/parser.rs

diff --git a/src/lexer.rs b/src/lexer.rs
index a955a4d..d71c6d9 100644
--- a/src/lexer.rs
+++ b/src/lexer.rs
@@ -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,
diff --git a/src/lib.rs b/src/lib.rs
index 82c0db8..1435b81 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,4 +1,5 @@
 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;
diff --git a/src/parser.rs b/src/parser.rs
new file mode 100644
index 0000000..30fac85
--- /dev/null
+++ b/src/parser.rs
@@ -0,0 +1,272 @@
+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
-- 
GitLab