Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
j5ik2o committed Oct 14, 2021
1 parent df05757 commit 0dcde4a
Show file tree
Hide file tree
Showing 6 changed files with 329 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/target
.idea/
*.iml
100 changes: 100 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[package]
name = "parsing-rust"
version = "0.1.0"
edition = "2018"
license = "MIT OR Apache-2.0"

[dependencies]
regex = "0.1"
1 change: 1 addition & 0 deletions rust-toolchain
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
nightly-2021-01-05
9 changes: 9 additions & 0 deletions rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
max_width = 120
newline_style = "Unix"
indent_style = "Block"
normalize_comments = true
brace_style = "PreferSameLine"
reorder_imports = true
reorder_impl_items = true
reorder_modules = true
tab_spaces = 2
208 changes: 208 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
#![feature(generic_associated_types)]
#![feature(associated_type_defaults)]
#![allow(incomplete_features)]
// https://github.com/fpinscala/fpinscala/blob/first-edition/answers/src/main/scala/fpinscala/parsing/Parsers.scala
use regex::Regex;

pub struct Location {
input: String,
offset: u32,
}

pub struct ParseError {
stack: Vec<(Location, String)>,
}

pub trait Parser {
type Elm;

fn or<A, P>(&self, p: P) -> P
where
P: Parser<Elm = A>;

fn pure<A, P>(a: A) -> P
where
P: Parser<Elm = A>;

fn map<B, P, F>(self, f: F) -> P
where
P: Parser<Elm = B>,
F: FnOnce(Self::Elm) -> B,
Self: Sized, {
self.flat_map(|e| Self::pure(f(e)))
}

fn flat_map<B, P, F>(self, f: F) -> P
where
P: Parser<Elm = B>,
F: FnOnce(Self::Elm) -> P;
}

pub trait Parsers {
type P<A>;

fn run<A>(&self, p: Self::P<A>, input: &str) -> Result<A, ParseError>;

fn string(&self, s: String) -> Self::P<String>;

fn char(&self, c: char) -> Self::P<char> {
let s = c.to_string();
let p = self.string(s);
self.map(p, |e| e.chars().nth(0).unwrap())
}

fn default_succeed<A>(&self, a: A) -> Self::P<A> {
self.map(self.string("".to_string()),move |_| a)
}

fn succeed<A>(&self, a: A) -> Self::P<A>;

fn slice<A>(&self, p: Self::P<A>) -> Self::P<String>;

fn many1<A, PF>(&self, pf: PF) -> Self::P<Vec<A>>
where
PF: Fn() -> Self::P<A>, {
self.map2(
pf(),
|| self.many(pf),
|a, b: Vec<A>| {
let mut m = vec![];
m.push(a);
m.extend(b);
m
},
)
}

fn list_of_n<A, PF>(&self, n: i32, pf: PF) -> Self::P<Vec<A>>
where
PF: Fn() -> Self::P<A>, {
if n <= 0 {
self.succeed(Vec::new())
} else {
self.map2(
pf(),
|| self.list_of_n(n - 1, pf),
|a, b: Vec<A>| {
let mut m = vec![];
m.push(a);
m.extend(b);
m
},
)
}
}

fn many<A, PF>(&self, pf: PF) -> Self::P<Vec<A>>
where
PF: Fn() -> Self::P<A>, {
let map2 = self.map2(
pf(),
|| self.many(pf),
|a, b: Vec<A>| {
let mut m = vec![];
m.push(a);
m.extend(b);
m
},
);
self.or(map2, self.succeed(Vec::new()))
}

fn or<A>(&self, p1: Self::P<A>, p2: Self::P<A>) -> Self::P<A>;

fn flat_map<A, B, PF>(&self, p: Self::P<A>, f: PF) -> Self::P<B>
where
PF: FnOnce(A) -> Self::P<B>;

fn regex(&self, r: Regex) -> Self::P<String>;

fn product<A, B, PF>(&self, p1: Self::P<A>, p2f: PF) -> Self::P<(A, B)>
where
PF: FnOnce() -> Self::P<B>, {
self.flat_map(p1, |a| self.map(p2f(), move |b| (a, b)))
}

fn map2<A, B, C, PF, F>(&self, pa: Self::P<A>, pbf: PF, f: F) -> Self::P<C>
where
PF: FnOnce() -> Self::P<B>,
F: Fn(A, B) -> C, {
self.flat_map(pa, |a| self.map(pbf(), |b| f(a, b)))
}

fn map<A, B, F>(&self, p: Self::P<A>, f: F) -> Self::P<B>
where
F: FnOnce(A) -> B, {
self.flat_map(p, move |e| self.succeed(f(e)))
}

fn label<A>(&self, msg: String, p: Self::P<A>) -> Self::P<A>;

fn scope<A>(&self, msg: String, p: Self::P<A>) -> Self::P<A>;

fn attempt<A>(&self, p: Self::P<A>) -> Self::P<A>;

fn skip_l<X, B, PF>(&self, p1: Self::P<X>, p2f: PF) -> Self::P<B>
where
PF: Fn() -> Self::P<B>, {
self.map2(self.slice(p1), p2f, |_, b| b)
}

fn skip_r<X, A, PF>(&self, p1: Self::P<A>, p2f: PF) -> Self::P<A>
where
PF: FnOnce() -> Self::P<X>, {
self.map2(p1, || self.slice(p2f()), |a, _| a)
}

fn opt<A>(&self, p: Self::P<A>) -> Self::P<Option<A>> {
self.or(self.map(p, Some), self.succeed(None))
}

fn whitespace(&self) -> Self::P<String> {
self.regex(Regex::new("\\s*").unwrap())
}

fn digits(&self) -> Self::P<String> {
self.regex(Regex::new("\\d+").unwrap())
}

fn double_string(&self) -> Self::P<String> {
self.token(self.regex(Regex::new("[-+]?([0-9]*\\.)?[0-9]+([eE][-+]?[0-9]+)?").unwrap()))
}

fn double(&self) -> Self::P<f64> {
let ds = self.double_string();
let p = self.map(ds, |s: String| s.parse::<f64>().unwrap());
self.label("double literal".to_string(), p)
}

fn token<A>(&self, p: Self::P<A>) -> Self::P<A> {
self.skip_r(self.attempt(p), || self.whitespace())
}

// fn sep<X, A, PF>(&self, p1: Self::P<A>, p2f: PF) -> Self::P<Vec<A>>
// where
// PF: FnOnce() -> Self::P<X>;

// fn sep1<X, A, PF1, PF2>(&self, p1f: PF1, p2f: PF2) -> Self::P<Vec<A>>
// where
// PF1: Fn() -> Self::P<A>,
// PF2: Fn() -> Self::P<X>,
// {
// let a = self.many(|| self.skip_l(p2f(), p1f));
// self.map2(
// p1f(),
// || a,
// |a, b: Vec<A>| {
// let mut m = vec![];
// m.push(a);
// m.extend(b);
// m
// },
// )
// }
}

fn main() {
println!("Hello, world!");
}

0 comments on commit 0dcde4a

Please sign in to comment.