blob: 4e21e1d3bf46f8cfb93702681d2e6a547834e673 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
#![warn(missing_docs)]
//! This package implements the core algorithm of the entire
//! workspace: parsing with derivatives by means of chain rule and
//! regular nulling languages.
//!
//! Since I shall not name my crate "core" to avoid collisions with
//! the Rust's own core, I decided to name this crate after what I
//! think is the essence of this algorithm, the chain-rule for
//! derivatives of languages.
pub mod atom;
// TODO: Define errors.
/// The expected behaviours of a language which can take derivatives
/// by chain rule.
pub trait Chain: Default {
/// The implementations should choose a type to represent errors.
type Error: std::error::Error;
/// Represents the language that is present after we parse the
/// empty string, that is the initial configuration of the
/// language. This may or may not be different from what
/// `Default::default` gives.
fn unit() -> Self;
/// Take the derivative by a terminal symbol.
///
/// This takes care of the union and the prepending operations.
///
/// # A little remark about the design
///
/// I have thought to separate different operations (like the
/// union, the prepending, and single derivatives) and then define
/// a function to put everything together. But I think that
/// design is not convenient to use. Also, I really do not need
/// those operations other than to provide this derivative
/// operation, so why define them? And putting all things
/// together may reduce the number of bugs caused by wrong uses of
/// those component functions, and can reduce the amount of
/// documentation strings a library user needs to read, in order
/// to make use of this trait. So I ended up with this design.
fn chain(&mut self, t: usize);
/// Return true if and only if the language contains the empty
/// string.
fn epsilon(&self) -> bool;
}
pub mod default;
|