Skip to content
Snippets Groups Projects
Commit 14e06f87 authored by Paul's avatar Paul
Browse files

Init

parent b67e08b1
No related merge requests found
use std::fs::File;
use crate::{C1Lexer, C1Token, lexer, ParseResult};
pub struct C1Parser<'a> {
lx: C1Lexer<'a>,
}
impl<'a> C1Parser<'a> {
fn new(text: &str) -> C1Parser {
C1Parser {
lx: C1Lexer::new(text),
}
}
pub fn parse(text: &str) -> ParseResult {
let mut instance = C1Parser::new(text);
println!("Starting parsing");
instance.program().unwrap();
Ok(())
}
fn program(&mut self) -> ParseResult {
self.functiondefinition().unwrap();
Ok(())
}
fn functiondefinition(&mut self) -> ParseResult {
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(());
}
return Err(format!("Expected token group 'type' but found {:?}", self.lx.current_token()));
}
fn statementlist(&mut self) -> ParseResult {
print!("statementlist->");
//self.block().unwrap(); //TODO: While loop
/*if self.lx.current_token() == Some(C1Token::LeftBrace) && self.lx.peek_token() == Some(C1Token::RightBrace) {
self.lx.eat();
self.lx.eat();
println!("eat");
return Ok(());
}
if self.lx.current_token() == Some(C1Token::LeftBrace){
self.check_and_eat_token(C1Token::LeftBrace).unwrap();
while !(self.lx.current_token() == Some(C1Token::RightBrace)) {
println!("r");
if self.lx.current_token() == Some(C1Token::LeftBrace){
self.statementlist().unwrap();
}
self.statement().unwrap();
}
println!("block finished!!!");
self.check_and_eat_token(C1Token::RightBrace).unwrap();
}*/
while !(self.lx.current_token() == Some(C1Token::RightBrace)) {
self.block().unwrap();
}
Ok(())
}
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();
}else{
self.statement().unwrap();
}
Ok(())
}
fn statement(&mut self) -> ParseResult {
print!("statement->");
match self.lx.current_token() {
Some(C1Token::KwIf) => {
self.ifstatement().unwrap();
Ok(())
},
Some(C1Token::KwReturn) => {
self.returnstatement().unwrap();
self.check_and_eat_token(C1Token::Semicolon).unwrap();
Ok(())
},
Some(C1Token::KwPrintf) => {
self.printfstatement().unwrap();
self.check_and_eat_token(C1Token::Semicolon).unwrap();
Ok(())
},
Some(C1Token::Identifier) => {
if self.lx.peek_token() == Some(C1Token::Assign) {
self.statassignment().unwrap();
self.check_and_eat_token(C1Token::Semicolon).unwrap();
}else{
self.functioncall().unwrap();
self.check_and_eat_token(C1Token::Semicolon).unwrap();
}
Ok(())
},
_ => Err(format!("Expected token group 'statement' but found {:?}", 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(())
}
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(())
}
fn returnstatement(&mut self) -> ParseResult {
print!("returnstatement->");
self.check_and_eat_token(C1Token::KwReturn).unwrap();
self.assignment(); //TODO: Maybe?
Ok(())
}
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(())
}
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(())
}
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(());
}else{
println!("assignment: Not Identifier");
self.expr().unwrap();
return Ok(());
}
}
fn expr(&mut self) -> ParseResult {
print!("expr->");
self.simpexpr().unwrap();
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.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.term().unwrap();
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();
}
Ok(())
}
fn term(&mut self) -> ParseResult {
print!("term->");
self.factor().unwrap();
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();
}
Ok(())
}
fn factor(&mut self) -> ParseResult {
print!("factor->");
match self.lx.current_token() {
Some(C1Token::ConstInt) => {
self.check_and_eat_token(C1Token::ConstInt).unwrap();
Ok(())
},
Some(C1Token::ConstFloat) => {
self.check_and_eat_token(C1Token::ConstFloat).unwrap();
Ok(())
},
Some(C1Token::ConstBoolean) => {
self.check_and_eat_token(C1Token::ConstBoolean).unwrap();
Ok(())
},
Some(C1Token::Identifier) => {
if self.lx.peek_token() == Some(C1Token::LeftParenthesis) {
self.functioncall().unwrap();
}else{
self.check_and_eat_token(C1Token::Identifier).unwrap();
}
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();
Ok(())
},
_ => Err(format!("Expected token group 'factor' but found {:?}", self.lx.current_token().unwrap())),
}
}
fn current_matches(&self, token: C1Token) -> ParseResult {
if self.lx.current_token() == Some(token) {
Ok(())
} else {
Err(format!("Expected token {:?}", token))
}
}
fn check_and_eat_token(&mut self, token: C1Token) -> ParseResult{
println!("Checking token: {:?} with text {:?} in line {:?}", token, self.lx.current_text().unwrap(), self.lx.current_line_number().unwrap());
match self.lx.current_token() {
Some(x) => {
if x == token {
println!("Correct: {:?}", x);
self.lx.eat();
return Ok(());
}
println!("Wrong: {:?}", x);
return Err(format!("Expected token {:?} but found {:?}", token, x));
},
None => Err("No token".to_owned()),
}
}
}
\ No newline at end of file
......@@ -126,6 +126,10 @@ pub enum C1Token {
#[regex("//[^\n]*(\n)?", logos::skip)]
CPPComment,
#[regex(r"\r", logos::skip)] //NEW
carriagereturn,
// We can also use this variant to define whitespace,
// or any other matches we wish to skip.
#[regex(r"[ \t\f]+", logos::skip)]
......
......@@ -10,3 +10,5 @@ pub use lexer::C1Token;
// You will need a re-export of your C1Parser definition. Here is an example:
// mod parser;
// pub use parser::C1Parser;
mod C1_parser;
pub use C1_parser::C1Parser;
......@@ -4,6 +4,9 @@ use std::fs;
#[test]
fn run_example() {
let text = fs::read_to_string("tests/data/beispiel.c-1").unwrap();
println!("test1");
let result = C1Parser::parse(text.as_str());
assert!(result.is_ok(), "Parse result: {}", result.err().unwrap());
}
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