Skip to content

Commit

Permalink
WIP: Add tests for various parsers
Browse files Browse the repository at this point in the history
Rust is not able to run the current implementation of parser combinators
since it doesn't have lazy evaluation on function calls.
  • Loading branch information
Mroik committed May 7, 2024
1 parent e0e8f6d commit 082783f
Showing 1 changed file with 53 additions and 15 deletions.
68 changes: 53 additions & 15 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ impl std::ops::BitOr<Parser> for Parser {
fn and_combinator(p1: Parser, p2: Parser) -> Parser {
let combined = move |queue: &str| match p1.execute(queue) {
Result::Failure => Result::Failure,
Result::Success(r1, rest) => match p2.execute(&rest) {
Result::Success(r1, rest1) => match p2.execute(&rest1) {
Result::Failure => Result::Failure,
Result::Success(r2, rest) => {
Result::Success(r2, rest2) => {
let mut ris = r1.clone();
ris.push_str(&r2);
Result::Success(ris, rest)
Result::Success(ris, rest2)
}
},
};
Expand All @@ -52,6 +52,7 @@ fn or_combinator(p1: Parser, p2: Parser) -> Parser {

fn char_parser(c: char) -> Parser {
let inner = move |queue: &str| {
let queue = queue.trim_start();
if queue.is_empty() || queue.chars().nth(0).unwrap() != c {
return Result::Failure;
}
Expand All @@ -62,42 +63,38 @@ fn char_parser(c: char) -> Parser {

fn word_parser() -> Parser {
let inner = move |queue: &str| {
let mut started = false;
let queue = queue.trim_start();
let mut buffer = String::new();
let mut index = queue.len();
let offset = queue.len() - queue.trim_start().len();
for (i, car) in queue.chars().enumerate() {
let mut started = false;
for (i, car) in queue.trim_start().chars().enumerate() {
if !started {
match car {
c if c >= 'A' || c <= 'Z' || c == '_' => {
c if (c >= 'A' && c <= 'Z') || c == '_' => {
started = true;
buffer.push(c);
}
_ => return Result::Failure,
}
} else {
match car {
c if c >= 'A' || c <= 'Z' || c == '_' => {
buffer.push(c);
}
c if (c >= 'A' && c <= 'Z') || c == '_' => buffer.push(c),
_ => {
index = i;
break;
}
}
}
}
Result::Success(
buffer.chars().collect(),
queue[index + offset..].to_string(),
)
Result::Success(buffer.chars().collect(), queue[index..].to_string())
};
Parser(Box::new(inner))
}

fn string_parser(s: &str) -> Parser {
let ss = String::from(s);
let inner = move |queue: &str| {
let queue = queue.trim_start();
let s = &ss;
let offset = queue.len() - queue.trim_start().len();
if queue.trim_start().starts_with(s) {
Expand Down Expand Up @@ -153,5 +150,46 @@ fn iff_parser() -> Parser {
}

fn expression_parser() -> Parser {
word_parser() | absurdum_parser() | and_parser() | or_parser() | not_parser() | implies_parser() | iff_parser()
absurdum_parser()
| word_parser()
| and_parser()
| or_parser()
| not_parser()
| implies_parser()
| iff_parser()
}

#[cfg(test)]
mod tests {
use super::{and_parser, word_parser, Result};

#[test]
fn word_parser_test() {
let queue = " ciao ";
match word_parser().execute(queue) {
Result::Failure => assert!(true),
Result::Success(_, _) => assert!(false),
}

let queue = " CIAO ";
match word_parser().execute(queue) {
Result::Failure => assert!(false),
Result::Success(m, r) => {
assert_eq!("CIAO", m.as_str());
assert_eq!(" ", r.as_str());
}
}
}

#[test]
fn and_parser_test() {
let queue = "(A ^ B)";
match and_parser().execute(queue) {
Result::Failure => assert!(false),
Result::Success(m, r) => {
assert_eq!("(A ^ B)", m.as_str());
assert_eq!("", r.as_str());
}
}
}
}

0 comments on commit 082783f

Please sign in to comment.