Skip to content
Snippets Groups Projects
Commit 35ec1716 authored by Carlos Valencia's avatar Carlos Valencia
Browse files

All combinators implemented

parent 0085ed11
No related branches found
No related tags found
No related merge requests found
use crate::Parser;
use crate::parser::Context;
pub (crate) struct Pure<T: Copy> {
pub a: T
}
impl<T : Copy> Parser<T> for Pure<T> {
fn parse_fun(&self, input: String, _ctx: &mut Context) -> Result<(T, String), String> {
Ok((self.a, input))
}
}
pub (crate) struct Empty {}
// Ideally this would have type None. I had to give it a type for rust to be happy...
impl Parser<char> for Empty {
fn parse_fun(&self, _input: String, _ctx: &mut Context) -> Result<(char, String), String> {
Err("Empty fail".to_owned())
}
}
pub (crate) struct Sat {
pub sat_fun: fn(c: char) -> bool
}
impl Parser<char> for Sat {
fn parse_fun(&self, input: String, ctx: &mut Context) -> Result<(char, String), String> {
let maybe_c = input[..1].chars().nth(0);
match maybe_c {
Some(c) => {
if (self.sat_fun)(c) {
ctx.consumed_input = ctx.consumed_input + 1;
Ok((c, input[1..].to_owned()))
} else {
Err("Didnt match char".to_owned())
}
},
None => Err("Cannot parse empty input".to_owned())
}
}
}
// If the first one fails without consuming input, then the second one is atempted
pub (crate) struct Alternative<T: Copy,> {
pub parser_first: Box<dyn Parser<T>>,
pub parser_second: Box<dyn Parser<T>>
}
impl<T: Copy> Parser<T> for Alternative<T> {
fn parse_fun(&self, input: String, ctx: &mut Context) -> Result<(T, String), String> {
let input_copy = &input[..];
let input_before = ctx.consumed_input;
let res_parse_first = &self.parser_first.parse_fun(format!("{}",input), ctx);
match res_parse_first {
Ok((parsed, rest)) => Ok((*parsed, format!("{}", rest))),
Err(_) => {
// didnt consume input
if input_before == ctx.consumed_input {
return self.parser_second.parse_fun(input_copy.to_owned(), ctx);
} else {
Err("First parser field and consumed input".to_owned())
}
}
}
}
}
// If the parser fails after consuming input then it will backtrack and 'undo' what it has done
pub (crate) struct Attempt<T: Copy> {
pub parser: Box<dyn Parser<T>>
}
impl<T: Copy> Parser<T> for Attempt<T> {
fn parse_fun(&self, input: String, ctx: &mut Context) -> Result<(T, String), String> {
let input_before = ctx.consumed_input;
let parse_res = &self.parser.parse_fun(input, ctx);
match parse_res {
Ok((parsed, rest)) => Ok((*parsed, format!("{}", rest))),
Err(e) => {
ctx.consumed_input = input_before;
Err(format!("{}", e))
},
}
}
}
pub(crate) struct Zip<A: Copy, B: Copy> {
pub parser_first: Box<dyn Parser<A>>,
pub parser_second: Box<dyn Parser<B>>
}
impl<A: Copy, B: Copy> Parser<(A, B)> for Zip<A, B> {
fn parse_fun(&self, input: String, ctx: &mut Context) -> Result <((A, B), String), String> {
let first = &self.parser_first.parse_fun(input, ctx);
match first {
Ok((parsed_first, rest_first)) => {
let second = &self.parser_second.parse_fun(format!("{}", rest_first), ctx);
match second {
Ok((parsed_second, rest)) => Ok(((*parsed_first, *parsed_second), format!("{}", rest))),
Err(e) => Err(format!("On the second parse: {}", e))
}
},
Err(e) => Err(format!("On the first parse:{}", e))
}
}
}
pub(crate) struct Map<A: Copy, B:Copy> {
pub map_a_b_fun: fn(a: A) -> B,
pub parser_a : Box<dyn Parser<A>>
}
impl<A: Copy, B: Copy> Parser<B> for Map<A, B> {
fn parse_fun(&self, input: String, ctx: &mut Context) -> Result<(B, String), String> {
if input.is_empty() {
return Err(format!("Failed to parse empty string"));
}
let res_a = &self.parser_a.parse_fun(input, ctx);
match res_a {
Ok((parsed, rest)) => {
let fun_res = (&self.map_a_b_fun)(*parsed);
Ok((fun_res, format!("{}", rest)))
},
Err(e) => Err(format!("On the first Parse: {}", e))
}
}
}
// Wrong/ Will not be used
pub(crate) struct Bind {
pub parser_first: Box<dyn Parser<char>>,
pub parser_second: Box<dyn Parser<char>>,
}
impl Parser<String> for Bind {
fn parse_fun(&self, input: String, ctx: &mut Context) -> Result<(String, String), String> {
let res_first = &self.parser_first.parse_fun(input, ctx);
match res_first {
Ok((p_first, rest_first)) => {
let res_second = &self.parser_second.parse_fun(String::from(rest_first), ctx);
match res_second {
Ok((p_second, rest_second)) => {
return Ok((format!("{}{}", p_first, p_second), String::from(rest_second)));
},
Err(e) => return Err(String::from(e)),
}
}
Err(e) => return Err(String::from(e)),
}
}
}
pub(crate) struct Many {
pub parser: Box<dyn Parser<char>>
}
impl Parser<String> for Many {
fn parse_fun(&self, input: String, ctx: &mut Context) -> Result<(String, String), String> {
let mut parsed_string = String::from("");
let mut rest_string = String::from("");
let mut result = self.parser.parse_fun(input, ctx);
loop {
match result {
Ok((parsed, rest)) => {
parsed_string = format!("{}{}", parsed_string, parsed);
rest_string = rest.to_owned();
result = self.parser.parse_fun(rest, ctx);
},
Err(_e) => break
}
}
Ok((parsed_string, rest_string))
}
}
pub (crate) struct ManyA {}
impl ManyA {
fn _parse_fun(&self, input: &str, ctx: &mut Context) -> Result<(String, String), String> {
if input.is_empty() {
Err("Empty String".to_owned())
} else if input[..1].chars().nth(0) == Some('a'){
match &self._parse_fun(&input[1..], ctx) {
Ok((parsed, rest)) => Ok((format!("a{}", parsed), format!("{}", rest))),
Err(_) => Ok(("a".to_owned(), input[1..].to_owned()))
}
} else {
Err("Not char a".to_owned())
}
}
pub fn _parse(&self, input: &str) -> Result<(String,String) , String> {
let mut ctx = Context{
consumed_input: 0,
row: 0,
col: 0
};
self._parse_fun(input, &mut ctx)
}
}
pub mod combinators;
\ No newline at end of file
hhhello
\ No newline at end of file
hello1
\ No newline at end of file
use std::env;
use std::fs;
mod parser_impls;
use parser_impls::chars::CharacterParser;
use parser_impls::chars::{AlphabeticCharacterParser, CharacterParser};
mod parser;
use parser::parser::Parser;
mod combinators;
use combinators::combinators::{Bind, Many, ManyA, Empty, Sat, Alternative, Zip, Map};
fn equals_a_fun(c: char) -> bool {
c == 'a'
}
fn equals_i_fun(c: char) -> bool {
c == 'i'
}
fn x_to_k(a: char) -> char {
'k'
}
fn main() {
let source = "src/examples/example_programs/character.txt";
let file = fs::read_to_string(source).expect("File was not found or could not be read");
let parse_a = CharacterParser{};
let res = Parser::parse(&parse_a, file);
let source = "src/examples/example_programs/word.txt";
let _file = fs::read_to_string(source).expect("File was not found or could not be read");
let _parse_a = Bind{
parser_first : Box::new(AlphabeticCharacterParser{}),
parser_second: Box::new(AlphabeticCharacterParser{}),
};
// let parse_b = Bind{
// parser_first : Box::new(AlphabeticCharacterParser{}),
// parser_second: Box::new(AlphabeticCharacterParser{}),
// };
// let parse_c = Bind{
// parser_first : Box::new(parse_a),
// parser_second: Box::new(parse_b),
// };
// let res = Parser::parse(&parse_c, file);
// Parses character h
let char_parser_h = CharacterParser {
character : 'h'
};
// let res = Parser::parse(&char_parser, file);
// Parses many of the same charcter
let _char_many_parser = Many {
parser: Box::new(char_parser_h)
};
// let res = Parser::parse(&char_many_parser, file);
//Parsers all alphabet characters
// let parser_many = Many{
// parser : Box::new(AlphabeticCharacterParser{})
// };
// let res = Parser::parse(&parser_many, file);
let _many_a = ManyA {};
// let res = many_a.parse("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaak");
let _empty = Empty{};
// let res = empty.parse("hello".to_owned());
let equals_a = Sat {
sat_fun: equals_a_fun
};
// let res = Parser::parse(&equals_a, "aaa".to_owned());
let equals_i = Sat {
sat_fun: equals_i_fun
};
// let a_or_i = Alternative{
// parser_first: Box::new(equals_a),
// parser_second: Box::new(equals_i)
// };
// let res = Parser::parse(&h_or_i, "i".to_owned());
// let a_then_i = Zip {
// parser_first: Box::new(equals_a),
// parser_second: Box::new(equals_i)
// };
// let res = Parser::parse(&a_then_i, "aa".to_owned());
let map_a_k = Map {
map_a_b_fun: x_to_k,
parser_a: Box::new(equals_a)
};
let res = Parser::parse(&map_a_k, "".to_owned());
print!("{:#?}", res);
......
pub mod parser;
pub(crate) struct Context {
pub consumed_input: usize,
pub row: usize,
pub col: usize,
}
use super::Context;
pub(crate) trait Parser {
pub(crate) trait Parser<T> {
// The parsing function resturns a tuple (Parsed, Rest) or an Error String
fn parse_fun(&self, input: String, ctx: &mut Context) -> Result<(String, String), String>;
fn parse_fun(&self, input: String, ctx: &mut Context) -> Result<(T, String), String>;
fn parse(&self, input: String) -> Result<(String,String) , String> {
fn parse(&self, input: String) -> Result<(T, String) , String> {
let mut ctx = Context{
consumed_input: 0,
row: 0,
col: 0
};
......
use crate::Parser;
use crate::parser::Context;
pub(crate) struct CharacterParser;
pub(crate) struct AlphabeticCharacterParser;
impl Parser for CharacterParser {
impl Parser<char> for AlphabeticCharacterParser {
fn parse_fun(&self, input: String, ctx: &mut Context) -> Result<(String, String), String> {
fn parse_fun(&self, input: String, ctx: &mut Context) -> Result<(char, String), String> {
if input.len() == 0 {
return Err("Empty string".to_owned());
}
let first = &input[..1];
let rest = &input[1..];
return Ok((first.to_owned(), rest.to_owned()));
match first.chars().nth(0) {
Some(c) => {
if !c.is_alphabetic() {
return Err(format!("Non alphabetic character found {} at {},{}", first, ctx.row, ctx.col));
}
return Ok((c, rest.to_owned()));
},
None => return Err(String::from("Character not found")),
}
}
}
pub(crate) struct CharacterParser {
pub character: char
}
impl Parser<char> for CharacterParser {
fn parse_fun(&self, input: String, ctx: &mut Context) -> Result<(char, String), String> {
if input.len() == 0 {
return Err("Empty string".to_owned());
}
let first = &input[..1];
let rest = &input[1..];
match first.chars().nth(0) {
Some(c) => {
if c != self.character {
return Err(format!("Expected {} but found {} at {},{}", self.character, c, ctx.row, ctx.col));
}
return Ok((c, rest.to_owned()));
},
None => return Err(String::from("Character not found")),
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment