= nanore

image:https://travis-ci.org/y-fujii/nanore.svg?branch=master["Build Status", link="https://travis-ci.org/y-fujii/nanore"]
image:https://docs.rs/nanore/badge.svg["Documentation", link="https://docs.rs/nanore/"]

nanore is a tiny (≃ 0.2K SLOC) regular expression matcher for arbitrary data
types written in Rust.

* O(|regexp||sequence|) time and O(|regexp|) space.  No exponential blowup.
* Support online matching.
* Matching states can be copied at any time.
* Support regex weighting.
* Support path marking.

== Example

=== Basics

[source, rust]
----
use nanore::*;

let re = RegExRoot::<_, ()>::new(
    atom(|_, e| *e % 2 != 0) * atom(|_, e| *e % 2 == 0) + rep(atom(|_, e| *e > 0))
);
let mut m = Matcher::new(&re);

assert!(m.is_match());
m.feed(&1);
assert!(m.is_match());
m.feed(&2);
assert!(m.is_match());
m.feed(&3);
assert!(m.is_match());
m.feed(&0);
assert!(!m.is_match());
----

Constructs: `*` (concatenation), `+` (alternation), `rep()`, `opt()`, `eps()`,
`atom()`, `any()`, `val()`, `weight()`, `mark()`.

=== Mark & Path

[source, rust]
----
#[derive(Clone, Copy, PartialEq, Eq)]
enum Marker { Foo, Bar }

let re = RegExRoot::new(
    rep(mark(Marker::Foo) * val('a') + mark(Marker::Bar) * val('b'))
);
let mut m = Matcher::new(&re);

m.feed(&'a');
m.feed(&'b');
m.feed(&'a');
m.feed(&'b');
assert!(m.is_match());
assert!(m.path() == [(0, Marker::Foo), (1, Marker::Bar), (2, Marker::Foo), (3, Marker::Bar)]);
----

=== Weight

[source, rust]
----
let re = RegExRoot::new(
    rep(mark(Marker::Foo) * val('a')) * rep(weight(-1) * mark(Marker::Bar) * val('a'))
);
let mut m = Matcher::new(&re);

m.feed(&'a');
m.feed(&'a');
m.feed(&'a');
m.feed(&'a');
assert!(m.is_match());
assert!(m.path() == [(0, Marker::Bar), (1, Marker::Bar), (2, Marker::Bar), (3, Marker::Bar)]);
----

=== Application: Find longest fibonacci sequence

[source, rust]
----
#[derive(Clone, Copy, PartialEq, Eq)]
enum Marker { Bgn, End }

let xs = [1, 1, 2, 3, 5, 3, 2, 3, 5, 8, 13, 21, 34];
//        ^^^^^^^^^^^^^     ^^^^^^^^^^^^^^^^^^^^^^

let re = RegExRoot::new(
    rep(weight(1) * any()) * mark(Marker::Bgn) *
    any() * any() * rep(atom(|i, x| *x == xs[i - 2] + xs[i - 1])) *
    mark(Marker::End) * rep(weight(1) * any())
);
let mut m = Matcher::new(&re);
m.feed_iter(&xs);

assert!(m.path() == [(6, Marker::Bgn), (13, Marker::End)]);
----

== Reference

http://sebfisch.github.io/haskell-regexp/[Weighted RegExp Matching]::
	nanore uses (the subset of) the method in this paper.  Note that the idea
	is simple and elegant, but there are some non-trivial parts due to
	ε-transitions in implicitly generated ε-NFA (see `empty`, `final` and
	`shift`).  nanore handles normal transitions and ε-transitions separately,
	which seems a bit different from this paper (see `shift()` and
	`propagate()` in nanore).
http://research.preferred.jp/2010/11/regexp-play/[関数型的正規表現マッチ]::
	The excellent article about the paper above, in Japanese.
